2013-06-18 7 views
39

Ruby 2.0 führt einen auf Copy-on-Write-fähigen Garbage Collector ein. Meine Prozesse scheinen den Speicher nicht länger als ein paar Minuten geteilt zu haben - er scheint sich ziemlich schnell von shared_dirty zu private_dirty zu bewegen.So verbessern Sie die Speicherfreigabe zwischen Unicorn-Prozessen mit Ruby 2.0 unter Linux

Einige andere haben Erfolg bekommen diese arbeiten musste:

Dieses Programm kann verwendet werden, um Speicherstatistiken auf Linux zu überprüfen: https://gist.github.com/kenn/5105061

Mein Einhorn Konfiguration: https://gist.github.com/inspire22/f82c77c0a465f1945305

Aus irgendeinem Grund haben meine Einhorn-Apps, auch mit preload_app = true, viel weniger gemeinsamen Speicher. Ruby-2.0-p195, Schienen 3.2, Linux 2.6.18 (CentOS)

[[email protected] script]# ruby memstats.rb 4946 
Process:    4946 
Command Line:  unicorn_rails worker[4] -c /u/apps/newap/current/lib/unicorn.rb -E production -D 
Memory Summary: 
    private_clean     0 kB 
    private_dirty    56,324 kB 
    pss      60,256 kB 
    rss      83,628 kB 
    shared_clean    4,204 kB 
    shared_dirty    23,100 kB 
    size      108,156 kB 
    swap       68 kB 

Wenn ich Abschaltung der Master-Prozess vollständig (und nicht nur ein HUP) anschließend neu starten und sofort einen Arbeiter überprüfen, bevor irgendwelche Anforderungen in der Warteschlange haben, ich erhalten eine bessere Geschichte:

[[email protected] script]# ruby memstats.rb 5743 
Process:    5743 
Command Line:  unicorn_rails worker[4] -c /u/apps/newap/current/lib/unicorn.rb -E production -D 
Memory Summary: 
    private_clean     0 kB 
    private_dirty    21,572 kB 
    pss      27,735 kB 
    rss      66,296 kB 
    shared_clean    2,484 kB 
    shared_dirty    42,240 kB 
    size      91,768 kB 
    swap       0 kB 

Aber innerhalb von 5 Sekunden wird in Betrieb genommen, sie zu ~ 20MB shared_clean + shared_dirty sind zurück.

Ich vermutete, dass swapping das Problem verursachen kann, aber nachdem Schwanken verringert und sichergestellt wird, dass weder die Eltern- noch die Kindprozesse ausgelagert werden (mit swapstats.rb), bleibt das Problem bestehen.

Ich verstehe nicht genau, was shared_dirty Speicher ist, und wie es in privaten Speicher verwandelt wird. Ich würde auch gerne Vorschläge zur Verbesserung der Langlebigkeit und Menge meines gemeinsamen Gedächtnisses. Vielen Dank!

+0

Ich habe immer noch keine Lösung für diese. Ich glaube jetzt, es ist ein Problem von a) 32-Bit-Linux-Version, und b) eine Umgebung mit eingeschränktem Speicher (obwohl selbst mit Swappiness abgelehnt immer noch auftritt) – Kevin

+0

Ich habe diesen Kommentar vom Autor des Gist: https: // Twitter.com/kenn/status/402832587007086592 –

+0

genial, danke :) – Kevin

Antwort

7

Nach this answer, die Sie bereits gesehen haben können, gibt es eine Zeile, die liest:

Beachten Sie, dass eine „Share-able“ Seite als Privat Mapping gezählt wird, bis er tatsächlich geteilt. Wenn es nur einen Prozess gibt, der libfoo verwendet, wird der Textabschnitt dieser Bibliothek in den privaten Zuordnungen des Prozesses angezeigt. Es wird in den gemeinsamen Zuordnungen (und , die von den privaten entfernt werden) nur dann berücksichtigt, wenn/wenn ein anderer Prozess startet, der diese Bibliothek verwendet.

Was ich tun würde, zu testen, ob Sie die Vorteile, wenn es darum outlined in this article, wird eine 10 MB XML-Datei als Zeichenkette direkt in den Quelltext setzen. Wenn Sie dann 20 Mitarbeiter starten, können Sie sehen, ob Sie 200 MB Arbeitsspeicher oder nur 10 MB verwenden, wie es bei der neuen Speicherbereinigungsfunktion der Fall ist.

UPDATE:

Ich war auf der Suche durch the unicorn source und fand einen Verweis auf this wonderful article.

Zusammenfassend heißt es, dass, um Ihre Anwendungen anzupassen Kollektor, um die Vorteile von Ruby Enterprise Edition der copy-on-write freundlichen Mülls, müssen Sie Satz GC.copy_on_write_friendly auf true, bevor Sie Gabel.

Basierend auf Ihrer bereitgestellten Unicorn-Konfigurationsdatei scheint die Zuweisung zu fehlen.

Auch genossen das Lesen ich diese in Verbindung stehende Artikel:

Nach dem fork man page:

Unter Linux ist fork() mit Copy-on-Write-Seiten implementiert, so dass die einzige Strafe die Zeit und der Arbeitsspeicher ist, die für erforderlich sind, um die Seitentabellen des übergeordneten Elements zu duplizieren und eine eindeutige -Struktur für das untergeordnete Element zu erstellen .

Seit Version 2.3.3, anstatt die Kernel-fork() System Aufruf aufgerufen wird, die glibc fork() Wrapper, der als Teil der NPTL Einfädeln Implementierung zur Verfügung gestellt ruft Klon (2) mit Flags, die zur Verfügung stellen Der gleiche Effekt wie der traditionelle Systemaufruf. (Ein Aufruf von fork() ist entspricht einem Aufruf von Klon (2), Flags nur als SIGCHLD zu spezifizieren.) Der Glibc-Wrapper ruft alle Forkhandler auf, die mit pthread_atfork (3) erstellt wurden.

Und nach den clone man page:

Anders als Gabel (2) ermöglichen diese Anrufe das Kind Prozess Teile seinen Ausführungskontext mit dem anrufenden Prozess, wie der Speicher Raum zu teilen, die Tabelle der Dateideskriptoren und die Tabelle der Signale Handler.

Also, ich lese dies zu bedeuten: linux Gabel copy-on-write, die das Merkmal ist, dass Einhorn Speicherfreigabe auf implementieren angewiesen ist, nicht bis libc 2.2.3 implementiert wurde (bitte jemand richtig wenn ich mich bei dieser Interpretation geirrt habe).

Um zu überprüfen, welche Version von libc Sie laufen, können Sie Folgendes eingeben:

ldd --version 

Oder glibc finden und direkt ausgeführt werden. Auf meinem System fand es die Datei an der folgenden Stelle:

locate libc.so 
/lib/x86_64-linux-gnu/libc.so.6 
+0

Interessante Testidee, danke! Theoretisch sollte das memstats.rb-Programm, das ich oben verbinde, dafür verantwortlich sein, aber Sie wissen nie. – Kevin

+0

Je mehr ich es betrachte, ist dies eine ziemlich schlechte Frage, da es "open ended" ist. Ohne Zugang zu einem System wäre es unmöglich, eine Antwort zu finden. Ihre Antwort gibt Ihnen einen guten Weg, um weiter zu debuggen, was möglicherweise schief läuft. Letztendlich vermute ich, dass es etwas mit einer älteren Version von Linux auf einem 32-Bit-System zu tun hat, mit einigen milden Speicherbeschränkungen/Swapping. Dein Test ist eine großartige Idee, obwohl er mit dem Skript memstats.rb dupliziert werden kann. – Kevin

+0

@Kevin Ein Update hinzugefügt, das die Ursache Ihres Problems zu sein scheint. Bitte lassen Sie mich wissen, wenn es für Sie klappt. – Homer6