Ember-cli Build Arbeitsspeichernutzung riskiert Fehlschlag (OOM) auf minimaler Instanzgröße

Während des Upgrades ist die bei weitem größte Belastung für den Speicher (RAM+Swap), wenn der Prozess ‘ember’ läuft. Ich glaube, jedes Mal, wenn ich ein Update durchgeführt habe, war es größer als zuvor, und es nähert sich der Unfähigkeit, auf Computern mit der empfohlenen Mindestgröße zu laufen.

Es wäre gut, dies zu untersuchen, bevor es tatsächlich fehlschlägt. (Hoffentlich wird die Antwort aus Kostengründen nicht lauten, die empfohlene Mindestgröße zu erhöhen. Eine Erhöhung des Swaps würde helfen, wenn genügend Speicherplatz vorhanden ist. Grundsätzlich könnte man vorübergehend zu einer teureren Instanz mit mehr RAM wechseln.)

Ich betreibe zwei Foren von moderater Größe auf kleinen Instanzen - beide liegen meiner Meinung nach innerhalb der empfohlenen Mindestwerte. In beiden Fällen beträgt RAM+Swap=3G. In einem Fall eine Digital Ocean-Instanz mit 1G RAM und 2G Swap, in dem anderen Fall eine Hetzner-Instanz mit 2G RAM und 1G Swap.

Hier sind drei Momentaufnahmen des Ember-Prozesses auf der DO-Maschine, die ps auxc verwenden.

USER       PID %CPU %MEM      VSZ    RSS TTY   STAT START   TIME COMMAND
1000     10342 87.7 65.1 32930460 657936 ?     Rl   16:57   2:23 ember

USER       PID %CPU %MEM      VSZ    RSS TTY   STAT START   TIME COMMAND
1000     10342 84.9 60.7 43572204 612668 ?     Rl   16:57   2:57 ember

USER       PID %CPU %MEM      VSZ    RSS TTY   STAT START   TIME COMMAND
1000     10342 81.2 55.2 43405220 557128 ?     Rl   16:57   3:40 ember

Offensichtlich sind die 43 GB Prozessgröße nicht vollständig im virtuellen Speicher vorhanden, da wir nur 3 GB zur Verfügung haben. 65 % der RAM-Größe für RSS zu verwenden, ist beeindruckend, aber an sich kein Problem. Die Menge an freiem Speicher und freiem Swap zeigt, dass die Maschine nahe an einem Out-of-Memory (OOM)-Zustand ist, was höchstwahrscheinlich dazu führen würde, dass ein Prozess beendet wird und das Update unsauber endet.

Hier ist free als Momentaufnahme:

# free
              total        used        free      shared  buff/cache   available
Mem:        1009140      863552       72768        6224       72820       34868
Swap:       2097144     1160628      936516

Um die Situation am Rande des Scheiterns zu erfassen, habe ich vmstat 5 verwendet.

# vmstat 5 5
procs -----------memory----------    ---swap-- -----io----  -system-- ------cpu-----
 r  b   swpd    free   buff  cache    si    so    bi    bo   in    cs us sy id wa st
 3  0 1392140  61200  11632  76432    41    32   117    93    0     1  2  1 97  0  0
 1  1 1467220  63416    324  67284  8786 20499 13178 20567 2539  8924 77 13  0 10  0
 0  2 1593340  57916   1096  53832 24262 46868 29986 46889 5377 18534 44 22  0 34  0
 4  0 1155632 120680   2772  86280 39111 35424 54768 37824 6987 25174 38 27  0 35  0
 3  0 1102988  74096   2852  85276 11261   246 12610   271 1879  6365 86  6  0  8  0

Sie werden viele Kontextwechsel (cs), viel Festplattenaktivität (bi, bo) und viel Swap-Aktivität (si, so) bemerken, aber das Wichtigste ist die Swap-Nutzung bis zu 1,6 G, während der freie Speicher auf 60 M und die Puffer auf nur 54 M reduziert ist. Das bedeutet, dass etwa 2,6 G der verfügbaren 3 G virtuellen Speichers belegt sind. Das sind 87 % der Kapazität. (Es könnte etwas schlimmer sein, da wir nur alle 5 Sekunden abfragen.)

Beachten Sie, dass die Situation besorgniserregend war (ca. 2 G belegt, also bei weitem nicht so kritisch wie heute), als ich im August ein Update durchführte:

# vmstat 5 5
procs -----------memory----------    ---swap-- -----io----  -system-- ------cpu-----
 r  b    swpd   free   buff  cache    si    so    bi    bo   in    cs us sy id wa st
 3  0  700404  62740   1956  48748    35    29   108    92    3     8  2  1 96  0  1
 1  0  741000  65996   1880  44360  3708 11190  3982 11191  643  1437 92  4  0  3  1
 1  0  834836  70452   1480  53856   528 18969  4274 18974  532  1575 93  6  0  1  0
 4  1 1010144  82192   4644  44400 30065 38803 35455 39946 4432 19267 28 26  0 39  7
 1  0  644116 307764   1644  55348 24406 21154 27724 21945 2551  8672 52 22  0 21  6
4 „Gefällt mir“

Hallo @Ed_S – welche Version von Discourse hast du für diese Tests verwendet? Wir aktualisieren ember-cli und seine Add-ons regelmäßig, daher möchte ich sichergehen, dass wir dasselbe betrachten.

Wie viele CPU-Kerne haben deine VMs? 1? (Du kannst das überprüfen, indem du lscpu in der Konsole ausführst)

Damit wir alle mit denselben Daten arbeiten, könntest du Folgendes versuchen:

/var/discourse/launcher enter app
cd /var/www/discourse/app/assets/javascripts/discourse
apt-get update && apt-get install time
NODE_OPTIONS='--max-old-space-size=2048' /usr/bin/time -v yarn ember build -prod

Auf meinem Test-Droplet (1 CPU, 1 GB RAM, 2 GB Swap) sehe ich Folgendes:

Command being timed: "yarn ember build -prod"
	User time (seconds): 369.74
	System time (seconds): 22.62
	Percent of CPU this job got: 81%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 8:02.73
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 774912
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 253770
	Minor (reclaiming a frame) page faults: 1158920
	Voluntary context switches: 519269
	Involuntary context switches: 383328
	Swaps: 0
	File system inputs: 7521784
	File system outputs: 316304
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0

Wir verwenden hier ziemlich Standard-Ember-Tools, daher bin ich mir nicht sicher, ob wir die Speichernutzung durch Konfiguration reduzieren können. Unser langfristiges Ziel ist es, auf Embroider umzusteigen, was uns möglicherweise mehr Optionen bietet.

1 „Gefällt mir“

Danke @david – ich weiß es zu schätzen, dass Ember eine eigene Sache ist.

Ich habe gerade diese Befehle ausgeführt.

# /var/discourse/launcher enter app
x86_64 arch detected.

WARNING: We are about to start downloading the Discourse base image
This process may take anywhere between a few minutes to an hour, depending on your network speed

Please be patient

2.0.20220720-0049: Pulling from discourse/base
Digest: sha256:7ff397003c78b64c9131726756014710e2e67568fbc88daad846d2b368a02364
Status: Downloaded newer image for discourse/base:2.0.20220720-0049
docker.io/discourse/base:2.0.20220720-0049

Dies ist eine Produktionsinstallation, daher war sie bis gestern auf dem neuesten Stand. Aktuell meldet:

Installed 2.9.0.beta12 (8f5936871c)

Es ist eine Single-CPU-Instanz, wie Ihre hat sie 1 GB RAM und 2 GB Swap.

Das Ergebnis des Zeitbefehls war

Done in 303.21s.

Command being timed: "yarn ember build -prod"
User time (seconds): 222.71
System time (seconds): 17.17
Percent of CPU this job got: 78%
Elapsed (wall clock) time (h:mm:ss or m:ss): 5:04.15
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 702292
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 348190
Minor (reclaiming a frame) page faults: 1152689
Voluntary context switches: 617736
Involuntary context switches: 774189
Swaps: 0
File system inputs: 5001936
File system outputs: 318280
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

Unmittelbar zuvor hatte ich den Host aktualisiert und neu gestartet, sodass alles im Container frisch neu gestartet worden wäre.

Der schlimmste Speicherverbrauch, wie er von einem vmstat in einem anderen Fenster gemeldet wurde:

# vmstat 1
procs  -----------memory----------    ---swap--  -----io----   -system-- ------cpu-----\n r  b    swpd   free   buff  cache    si     so    bi     bo    in    cs us sy id wa st\n 2  0  704000 136044  24136 158144  1517   3503  8256   4377   886  3564 43  8 43  6  0\n...\n 5  0 1451436  71604   1248  50196 55016 110236 73204 121060 13152 45971 29 60  0 10  1\n```
2 „Gefällt mir“

Es sieht so aus, als hätten wir den zulässigen Heap von Node explizit von 500 MB auf 2 GB erhöht – möglicherweise ist das ein Schritt zu viel und 1,5 GB wären besser:

Es ist erwähnenswert, dass Ember nicht das Einzige ist, was auf der Maschine läuft, und wir stoßen an die globale Grenze von RAM+Swap. Die Historie der Maschine und die Bedürfnisse aller anderen laufenden Prozesse spielen also eine Rolle. Mein Neustart hat hier möglicherweise geholfen, einen niedrigeren Höchststand im Vergleich zu gestern zu erreichen.
Der obige Pull-Request wurde in
Fehlgeschlagen, Discourse-Instanz auf den 15. Februar 2022 zu aktualisieren
referenziert, wo wir auch feststellen, dass jemand einen Speichermangel hatte, der durch einen Neustart behoben wurde.

Es ist bedauerlich, dass der time-Befehl die Spitzen-Speichernutzung nicht anzeigt. Möglicherweise würde auf einer Maschine mit mindestens 3 GB RAM und ohne Swap die RSS-Zählung die Spitzen-Nutzung von Ember anzeigen. Oder vielleicht könnten wir eine andere Taktik anwenden – mehrere sind hier skizziert und es gibt einige Ideen hier.

Was schwierig ist, ist, dass wir uns wirklich für die Speichernutzung interessieren, während sich in vielen Fällen die Leute für die RAM-Nutzung interessieren, was eine andere Frage ist.

3 „Gefällt mir“

Der Grund, warum wir dieses Flag hinzugefügt haben, war, dass der eigene OOM-Killer von Node den Build beendete – 500 MB reichten nicht aus. Gerne versuche ich, es auf 1,5 GB zu ändern – ich habe es gerade auf meinem Droplet ausprobiert und es scheint in Ordnung zu funktionieren. Tatsächlich scheinen sogar 1,0 GB auszureichen.

Ich habe versucht, die Speichernutzung mit verschiedenen maximalen Heap-Größen zu verfolgen:

(while(true); do (free -m -t | grep Total | awk '{print $3}') && sleep 0.5; done) | tee 1000mb.csv

Zeigt diese Nutzung während des Builds:

Es gab sehr wenig Unterschied in der Build-Zeit, aber die Limits von 1 GB und 1,5 GB erzeugen eindeutig eine geringere Gesamtnutzung. Wie erwartet zeigt die time-Ausgabe deutlich weniger „Major page faults“, wenn das Node-Limit niedriger ist.

Es ist merkwürdig, dass der Unterschied zwischen 1,5 GB und 1 GB so gering ist… :face_with_monocle:

Auf jeden Fall stimme ich zu, dass die Reduzierung des Limits eine gute Idee ist. Um sicherzustellen, dass dies die Build-Leistung auf Maschinen mit höherer Spezifikation nicht beeinträchtigt, sollten wir das Limit nur überschreiben, wenn wir wissen, dass es zu niedrig ist. Andernfalls können wir Node seine Standardeinstellung verwenden lassen.

Hier ist ein PR – wir werden versuchen, diesen bald zusammenzuführen. Danke, dass du das angesprochen hast, @Ed_S!

4 „Gefällt mir“

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.