2010-08-22 12 views
10

Wenn nicht ist das Maximum, während noch leistungsfähig bleibt?gibt es eine Begrenzung für die Anzahl der Threads, die Ruby auf einmal ausführen kann?

Ich erstelle 14 Threads, von denen jeder eine Liste von URLs öffnet (etwa 500) erstellt einen neuen Thread für jeden, der es dann herunterlädt und es zu einer MySQL Datenbank hinzufügt. Die Größe des MySQL-Pools ist auf 50 festgelegt.

Dies ist eine Rake-Aufgabe in RoR.

Würde dies besser funktionieren mit Kernal#fork oder eine andere Methode?

+3

können Sie einige "ruinieren"! ;) –

+0

behoben, danke! nicht Korrektur gelesen Titel: O – loosecannon

Antwort

2

Nun, da Ihre Threads IO-gebunden werden, ist die gute Nachricht, dass sowohl Ruby 1.8 als auch 1.9 Threads dafür funktionieren. Ruby 1.8 verwendet "Userspace-Threads", dh es werden keine echten neuen Betriebssystem-Threads erstellt, wenn Sie in Ruby neue Threads erstellen. Das ist schlecht für CPU-Multitasking, da nur ein Ruby-Thread gleichzeitig ausgeführt wird, aber gut für E/A-Multitasking ist. Ruby 1.9 verwendet echte Threads und wird für beide gut sein.

Die Anzahl der Threads, die Sie erstellen können, hängt wirklich von Ihrem System ab. Es gibt natürlich praktische Grenzen, aber Sie wollen wahrscheinlich nicht in deren Nähe kommen. Erstens, wenn die Server, von denen aus Sie heruntergefahren werden, sehr langsam sind und Ihre Verbindung sehr schnell ist, werden nur ein paar Threads Ihre Internetverbindung sättigen. Auch wenn Sie viele Seiten von einem einzigen Server packen, werden 500 Anfragen gleichzeitig aus 500 Threads nicht gut.

Ich würde ziemlich klein anfangen: 10 oder 20 Threads gleichzeitig laufen. Erhöhen oder verringern Sie dies je nach Serverlast, Bandbreite usw. Es gibt auch das Problem der gleichzeitigen Verbindungen zur MySQL-Datenbank. Abhängig davon, wie Ihre Tabellen eingerichtet sind und wie groß sie sind, wird es nicht sehr gut funktionieren, wenn Sie zu viele Daten gleichzeitig einfügen möchten.

+0

Ich beendete das Threading und fügte der Datenbank einen Index hinzu, der die Suche nach Duplikaten 1000x schneller machte, so dass ich die Geschwindigkeitserhöhung nicht mehr benötigte und wie gesagt, meine Verbindung gerade überlastet war. Vielen Dank! – loosecannon

3

Mit Ruby 1.8 ist es praktisch begrenzt, wie viel Speicher Sie haben. Sie können zehntausende Threads pro Prozess erstellen. Der Ruby-Interpreter übernimmt die Verwaltung der Threads und es werden nur ein oder zwei native Threads erstellt. Es ist kein echtes Multitasking, bei dem die CPU zwischen Threads wechselt.

Ruby 1.9 verwendet native Threads. Das Limit scheint das zu sein, was das Betriebssystem erlaubt. Nur zum Testen kann ich über 2000 Threads auf meinem Mac mit Ruby 1.9 erstellen, bevor das OS keine mehr erlaubt.

Beachten Sie, dass Tausende von Threads für einen Prozess keine gute Idee ist. Die Thread-Terminierung wird lange vorher zur Last.

+0

ok danke! Vielleicht benutzen Sie einfach die ersten 14 und nicht alle Sub-Threads. Danke! – loosecannon

+0

Sie meinen praktisch unbegrenzt? (Und ja, mit mehr Threads wird Ihre App runnnn ... langsamer 1.8.6 wegen der gemeinsamen Refs für den GC, obwohl ich denke, Sie könnten REE verwenden, um diese zu vermeiden). – rogerdpack

+0

Nein, es ist sicherlich nicht unbegrenzt. Ich bin mir sicher, dass Sie zustimmen, dass es "in der Praxis begrenzt" ist, wie viel RAM verfügbar ist. – Alkaline

9
require 'open-uri' 
a = 'http://www.example.com ' * 30 
arr = a.split(' ') 

arr.each_slice(3) do |group| 
    group.map do |site| 
    Thread.new do 
     open(site) 
     p 'finished' 
    end 
    end.each(&:join) 
end 
+0

gutes Beispiel. +1 von mir. – Rubyrider

+0

Ich mag es wirklich, Threads mit each_slice zu stapeln. Niemals zuvor jedes_slice benutzt, also ist dies eine sehr aufschlussreiche Lösung –

Verwandte Themen