Ember.js: [2.15.0] – Ember baut Speicherfehler auf, während CI-Tools verwendet werden

Erstellt am 7. Sept. 2017  ·  23Kommentare  ·  Quelle: emberjs/ember.js

Das parallele Babel-Transpiling wurde in Ember 2.15 eingeführt. (https://github.com/babel/broccoli-babel-transpiler#number-of-jobs)

Standardmäßig verwendet broccoli-babel-transpiler Systemressourcen (cpus), um die Anzahl der Jobs zu bestimmen, die parallel ausgeführt werden können.

Die meisten modernen CI-Tools verwenden Docker, um Builds von anderen Builds zu isolieren, die auf einem bestimmten Server ausgeführt werden. Dadurch können sie große VMs verwenden, um viele Builds auszuführen, die weitgehend voneinander isoliert sind. Zum Beispiel haben die VMs, auf denen Circle CI läuft, normalerweise 36 CPU-Kerne ... Aber die Builds selbst sind auf zwei beschränkt.

Das Problem tritt auf, wenn versucht wird, herkömmliche Mittel zu verwenden, um zu bestimmen, welche Ressourcen für das Programm verfügbar sind. Um beispielsweise die Anzahl der CPUs zu ermitteln, die den Knoten verwenden, können Sie node -e "console.log(require('os').cpus().length);" . Diese Informationen geben jedoch tatsächlich die Instanzressourcen an, nicht die begrenzten Ressourcen, die dem Docker-Container zur Verfügung stehen. Was dazu führt, dass alles, was läuft, denkt, es hat Zugriff auf 36 Kerne, aber in Wirklichkeit hat es nur zwei.

Ich habe ein Beispiel-Repo erstellt:
https://github.com/mwisner/ember-circleci-example , in dem Sie sowohl den erfolgreichen als auch den fehlgeschlagenen Build-Verlauf sehen können (https://circleci.com/gh/mwisner/ember-circleci-example) (https:// travis-ci.org/mwisner/ember-circleci-example/builds) (Ich habe den Travis-Build noch nicht repariert.)

Getestete CI-Tools
-- Kreis-CI 2.0
-- Kreis-CI 1.0
- Travis CI (Fehler bei standardmäßig bereitgestelltem Travis CI)

Dokumente zu parallelen Jobs: https://github.com/babel/broccoli-babel-transpiler#number -of-jobs

Wenn Fehler auftreten, sehen sie in etwa so aus wie in der Ausgabe unten. In vielen Situationen (z. B. Travis CI) läuft es jedoch nach 10 Minuten ohne Informationen einfach ab.)

#!/bin/bash -eo pipefail
ember test
Could not start watchman
Visit https://ember-cli.com/user-guide/#watchman for more info.
Building
'instrument' is imported from external module 'ember-data/-debug' but never used
/usr/local/bin/node[1116]: ../src/node_file.cc:598:void node::InternalModuleReadFile(const v8::FunctionCallbackInfo<v8::Value>&): Assertion `(numchars) >= (0)' failed.
fs.js:682
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: ENOMEM: not enough memory, read
    at Object.fs.readSync (fs.js:682:19)
    at tryReadSync (fs.js:480:20)
    at Object.fs.readFileSync (fs.js:509:19)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at /home/circleci/app/node_modules/esutils/lib/utils.js:31:23
fs.js:682
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: ENOMEM: not enough memory, read
    at Object.fs.readSync (fs.js:682:19)
    at tryReadSync (fs.js:480:20)
    at Object.fs.readFileSync (fs.js:509:19)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/circleci/app/node_modules/ember-power-select/node_modules/babel-core/lib/transformation/transformers/index.js:43:22)
fs.js:682
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: ENOMEM: not enough memory, read
    at Object.fs.readSync (fs.js:682:19)
    at tryReadSync (fs.js:480:20)
    at Object.fs.readFileSync (fs.js:509:19)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/circleci/app/node_modules/debug/src/node.js:14:28)
 1: node::Abort() [/usr/local/bin/node]
 2: node::Assert(char const* const (*) [4]) [/usr/local/bin/node]
 3: 0x12e49fa [/usr/local/bin/node]
 4: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [/usr/local/bin/node]
 5: 0xb45e2c [/usr/local/bin/node]
 6: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
 7: 0x1cbf812040c7
fs.js:682
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: ENOMEM: not enough memory, read
    at Object.fs.readSync (fs.js:682:19)
    at tryReadSync (fs.js:480:20)
    at Object.fs.readFileSync (fs.js:509:19)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/circleci/app/node_modules/debug/src/node.js:14:28)
fs.js:682
  var r = binding.read(fd, buffer, offset, length, position);
                  ^

Error: ENOMEM: not enough memory, read
    at Object.fs.readSync (fs.js:682:19)
    at tryReadSync (fs.js:480:20)
    at Object.fs.readFileSync (fs.js:509:19)
    at Object.Module._extensions..js (module.js:579:20)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/circleci/app/node_modules/regenerator/node_modules/ast-types/lib/node-path.js:6:12)
cleaning up
cleaning up...
Build failed.
The Broccoli Plugin: [BroccoliMergeTrees: Addon#treeFor (ember-concurrency - addon)] failed with:
Error: Worker terminated unexpectedly
    at ChildProcess.<anonymous> (/home/circleci/app/node_modules/workerpool/lib/WorkerHandler.js:177:17)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:194:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)

The broccoli plugin was instantiated at: 
    at BroccoliMergeTrees.Plugin (/home/circleci/app/node_modules/broccoli-plugin/index.js:7:31)
    at new BroccoliMergeTrees (/home/circleci/app/node_modules/broccoli-merge-trees/index.js:16:10)
    at Function.BroccoliMergeTrees [as _upstreamMergeTrees] (/home/circleci/app/node_modules/broccoli-merge-trees/index.js:10:53)
    at mergeTrees (/home/circleci/app/node_modules/ember-cli/lib/broccoli/merge-trees.js:85:33)
    at Class.treeFor (/home/circleci/app/node_modules/ember-cli/lib/models/addon.js:526:30)
    at addons.reduce (/home/circleci/app/node_modules/ember-cli/lib/models/addon.js:383:26)
    at Array.reduce (native)
    at Class.eachAddonInvoke (/home/circleci/app/node_modules/ember-cli/lib/models/addon.js:380:24)
    at Class.treeFor (/home/circleci/app/node_modules/ember-cli/lib/models/addon.js:515:22)
    at project.addons.reduce (/home/circleci/app/node_modules/ember-cli/lib/broccoli/ember-app.js:559:25)


Exited with code 1

Die von @rwjblue bereitgestellte "Workaround"-Lösung besteht darin, die Anzahl der Jobs, die Sie für das parallele Transpiling verwenden möchten, speziell zu definieren, indem Sie die ENV-Variable JOBS nutzen. (https://github.com/mwisner/ember-circleci-example/blob/09c63e11c34d4cdfe602b63166b71e6f31e30f3c/.circleci/config.yml#L42)

Has Reproduction

Hilfreichster Kommentar

Ich habe mich am Wochenende ein wenig mit @mwisner und @kiwiup darüber unterhalten und wir haben herausgefunden, dass es mit der neuen Parallelität zu tun hat, die zu broccoli-babel-transpiler hinzugefügt wurde. Es wird standardmäßig auf die Anzahl der derzeit vorhandenen CPUs parallelisiert. Leider zeigt dies auf CircleCI 36 CPUs an, aber der Job selbst ist auf 2 gleichzeitige Prozesse beschränkt (und auch im verfügbaren RAM begrenzt).

Die Lösung hier besteht darin, die Umgebungsvariable JOBS auf 1 zu setzen, um die Parallelität auf CI im Wesentlichen zu deaktivieren.

Alle 23 Kommentare

Es scheint, dass es einige Leute gibt, die Karma-Tests haben, die mit diesem Schritt arbeiten:

https://discuss.circleci.com/t/running-browser-tests/10998/9

Nach den letzten Stunden konnte ich dies noch nicht erfolgreich zum Laufen bringen, aber ich bin ziemlich zuversichtlich, dass dies nicht speziell ember.js ist .... Schließt vorerst.

Ich habe das gleiche Problem und konnte es nicht lösen.

Ich habe mich am Wochenende ein wenig mit @mwisner und @kiwiup darüber unterhalten und wir haben herausgefunden, dass es mit der neuen Parallelität zu tun hat, die zu broccoli-babel-transpiler hinzugefügt wurde. Es wird standardmäßig auf die Anzahl der derzeit vorhandenen CPUs parallelisiert. Leider zeigt dies auf CircleCI 36 CPUs an, aber der Job selbst ist auf 2 gleichzeitige Prozesse beschränkt (und auch im verfügbaren RAM begrenzt).

Die Lösung hier besteht darin, die Umgebungsvariable JOBS auf 1 zu setzen, um die Parallelität auf CI im Wesentlichen zu deaktivieren.

@rwjblue danke für den Kontext hier!

Selbst mit der Parallelität von Circle würde ich denken (weil sie in Container aufgeteilt sind), dass JOBS dann immer 1 sein müsste. Also durch...

um die Parallelität auf CI im Wesentlichen zu deaktivieren

... Ich gehe davon aus, dass Sie die Broccoli-Babel-Transpiler-Parallelität und nicht die Container-Parallelität von Circle deaktivieren möchten. Ist das richtig?

@eric-hu scheint dir das auch eine korrekte Lektüre zu sein? Ist dies etwas, von dem wir erwarten sollten, dass es von Circle behoben wird, damit die tatsächlich im Job verfügbaren CPUs angezeigt werden? Verhindert dies jede Art von Parallelität auf der Seite von Circle (durch Aufteilen von Tests mit etwas wie ember-exam zum Beispiel)?

Ich bin mir nicht sicher, ob wir selbst ein Fix-Formular erwarten können ... Ich bin nicht super 100%, aber ich denke, es ist eher ein Docker-Problem als ein spezielles Kreisproblem. Oder vielleicht ein Node + Docker-Problem, das die vom Docker-Container auferlegten CPU-/Speicherbeschränkungen nicht genau erkennen kann.

Ich habe dieses Repo zu Experimentierzwecken erstellt: https://github.com/mwisner/ember-circleci-example.

Es enthält Circleci 2.0 (funktioniert mit der von @rwjblue bereitgestellten JOBS=1-Problemumgehung) (https://github.com/mwisner/ember-circleci-example/blob/master/.circleci/config.yml)

Zusammen mit den öffentlichen Zirkelaufbauten: https://circleci.com/gh/mwisner/ember-circleci-example/83

Ich habe das Repo jedoch auch zu Travis ci hinzugefügt, das auch Docker für Builds verwendet. Ich habe die Travis-Konfigurationsdatei noch nicht repariert, aber Sie können sehen, dass die Travis-Builds mit der bereitgestellten Travis-Konfiguration fehlschlagen (https://travis- ci.org/mwisner/ember-circleci-example/builds)

Danke @mwisner. Habe ich richtig gedacht, dass JOBS=1 _nicht_ bedeutet, dass wir die Builds selbst nicht parallelisieren können?

@JoshSmith Ja, wenn ich das richtig verstehe, soll die Parallelität im Broccoli-Babel-Transpiler deaktiviert werden. Sich nicht umkreisen. Theoretisch wäre also die Verwendung von circleci parallelism + jobs=1 in Ordnung?

Aber ich persönlich habe nicht mit der Verwendung der Parallelitätsfunktion von circleci experimentiert. Ich bin mir also nicht 100% sicher, wie eine Konfigurationsdatei dafür aussehen würde.

Macht Sinn! Ich wollte sichergehen, dass ich hier nur eine klare Linie zwischen scheinbar zwei unterschiedlichen Verwendungen von „Parallelität“ ziehe, also denke ich, dass ich endlich auf derselben Seite bin.

Mir ist aufgefallen, dass Sie JOBS=1 manuell in der Konfiguration vor ember test eingestellt haben, aber es scheint, als könnte dies auf der ENV-Variablenebene in Circle eingestellt werden, vielleicht ohne Probleme?

Es ist auch nicht spezifisch für Tests. Das OOM-Problem wird während der Build-Phase des Ember-Tests verursacht. Ich habe auch nur ember build mit dem gleichen OOM-Ergebnis getestet.

@JoshSmith Ich glaube, dass das Festlegen von JOBS = 1 auf der Ebene der Umgebungsvariablen ebenfalls funktionieren würde, aber ich habe es nicht bestätigt.

Mir ist aufgefallen, dass es ein Muster zum Festlegen von env-Variablen für Ember-CLI-Befehle für einige Add-Ons gibt:

https://github.com/ember-cli/broccoli-viz#usage
https://github.com/kategengler/ember-cli-code-coverage#usage

Also ging ich einfach von diesen Nutzungsmustern aus.

Ohne _irgendetwas_ darüber zu wissen, wie broccoli-babel-transpiler tatsächlich funktioniert, ist es für mich schwer zu sagen, ob Circle (oder Docker oder wer auch immer) eine Lösung dafür bereitstellen könnte oder nicht. Das _Gefühl_ meines Laien – nicht Nachdenken – wäre, dass wir hier vielleicht das Problem der reinen Inferenz vermeiden könnten, wenn der Transpiler explizite Anweisungen dazu entgegennehmen könnte, wie viele Kerne verfügbar sind. Auch dies kommt von einem Ort tiefer Unwissenheit.

Nur zur Aktualisierung kann ich diese Builds erfolgreich ausführen, wenn JOBS $ in den Umgebungseinstellungen von Circle auf 1 gesetzt ist. Nochmals vielen Dank @rwjblue , @mwisner und @eric-hu.

Ich bin gerade auf dasselbe Problem auf CircleCI gestoßen, und JOBS=1 hat es auch für mich behoben, danke an alle :v:

@eric-hu scheint dir das auch eine korrekte Lektüre zu sein? Ist dies etwas, von dem wir erwarten sollten, dass es von Circle behoben wird, damit die tatsächlich im Job verfügbaren CPUs angezeigt werden? Verhindert dies jede Art von Parallelität auf der Seite von Circle (durch Aufteilen von Tests mit so etwas wie Ember-Exam zum Beispiel)?

@JoshSmith Für CircleCI 2.0 sind zwei Parallelitätskonzepte zu beachten:

A. Parallelität pro Befehl, begrenzt auf die Anzahl der Kerne, die einer Containergruppe zur Verfügung stehen. Standardmäßig werden jeder Containergruppe 2 CPU-Anteile zugewiesen, was garantiert, dass sie 2 CPU-Kerne erhält. Es gibt eine Premium-Funktion für konfigurierbare Ressourcen, mit der Sie einen größeren/kleineren Anteil auswählen können (1, 4, 8 von oben nach unten).

B. CircleCI-Parallelität, die Sie sich vorstellen können als „auf wie viele Maschinen [1] möchte ich das verteilen?“. Dies ist nützlich für die Testisolierung, wenn Sie möglicherweise zwei Tests gleichzeitig ausführen und beide in eine Datenbank schreiben möchten. Dies ist beispielsweise weniger nützlich, um Ihre Assets zu transpilieren; Wahrscheinlich möchten Sie, dass alle Ihre Tests mit den transpilierten Assets ausgeführt werden.

Zu A: Da Sie standardmäßig 2 Kerne garantiert zur Verfügung haben, können Sie den gewünschten Befehl möglicherweise mit JOBS=2 ausführen. Dies kann die Ausführung beschleunigen, aber ich habe nicht überprüft, ob es funktioniert.

Bezüglich B: Selbst mit JOBS=1 können Sie immer noch CircleCI-Parallelität verwenden, um Ihre Testsuite zu beschleunigen.

In Bezug auf „Wer sollte das beheben?“ habe ich dies als ein lang andauerndes Problem mit mehreren Containerisierungstools gesehen. Die Containerisierungstools CircleCI 2.0 und 1.0 – Docker bzw. LXC – lecken Informationen über das Hostsystem für viele gängige Linux-Befehle, wie z. B. diejenigen, die verwendet werden, um zu prüfen, wie viele Kerne verfügbar sind. Das ist schon seit einigen Jahren so, ich denke, wenn es eine einfache Lösung gäbe, wäre es jetzt gelöst. Um die Sache noch komplizierter zu machen, änderte CircleCI das CPU-Kern-Verfügbarkeitsmodell von 1.0 auf 2.0. In 1.0 bekamen Sie eine feste Anzahl von Kernen für einen Job. In 2.0 werden Ihnen CPU-Anteile zugewiesen, um Ihre Mindestanzahl an Kernen zu garantieren. Wenn Sie sich auf einem voll ausgelasteten Host befinden, erhalten Sie mindestens so viele Kerne. Wenn Sie auf einem nicht ausgelasteten Host arbeiten, stehen Ihnen mehr Kerne zur Verfügung. Tools wie broccoli-babel-transpiler neigen jedoch dazu, die Anzahl der verwendeten Kerne nur einmal zuzuweisen, und die verfügbaren Ressourcen können sich während der Lebensdauer des Programms ändern. Am besten codieren Sie Ihre CI-Skripts einfach fest, um die garantierten verfügbaren Ressourcen zu verwenden.

[1] Ihr Code wird möglicherweise nicht auf N-Computern für N-Parallelität ausgeführt. Aber Sie können es sich so vorstellen, da sie effektiv voneinander isoliert sind.

Ich habe gerade JOBS=2 in meiner App ausprobiert und der Build war ebenfalls erfolgreich. Sollte das hier der kanonische Rat sein?

Kein merklicher Zeitunterschied zwischen diesen Werten in meiner kleinen Beispiel-FWIW.

@rwjblue Ich weiß, dass Sie empfohlen haben, dieses Problem im Ember-Cli-Repo zu haben. Ich habe dieses Problem jedoch geöffnet, als ich das Problem zum ersten Mal entdeckte, und es sieht so aus, als ob es gefunden wurde, bevor ich ein weiteres im Ember-Cli-Repo öffnen konnte ... Möchten Sie, dass ich dort ein weiteres Problem eröffne und nur auf diese Konversation verweise? Wissen Sie trotzdem, wie Sie es leicht verschieben können?

Ich habe dieses Problem erneut geöffnet, da nach einigen zusätzlichen Tests die bereitgestellte travisci.yml-Konfiguration, die mit Ember geliefert wird, ebenfalls auf dieses Problem stößt.

Obwohl ich verstehe, dass Ember Circle nicht unterstützt, denke ich, dass es schön wäre, wenn das Problem zumindest in der mitgelieferten travisci.yml-Datei behoben wäre.

Ich habe auch den Titel und die Beschreibung aktualisiert, um sie ein wenig allgemeiner zu gestalten und nicht speziell auf circleCI zu beziehen

@eric-hu vielen Dank für die ausführliche Beratung hier. Sehr hilfreich für die Community, um zu verstehen, was im Detail vor sich geht. Es wäre großartig, ein kanonisches Beispiel pro Framework in der Dokumentation zu sehen, obwohl ich die Zeit verstehe und schätze, die dies in Anspruch nehmen würde.

@bgentry danke für die Berichterstattung über den Zeitunterschied. Ich hatte gehofft, dass es die Bauzeiten beschleunigen würde. Ich werde auch JOBS=2 setzen, bin aber etwas enttäuscht darüber, da meine Build-Zeiten bei weitem mein größtes Hindernis bei der Beschleunigung von Circle-Jobs sind.

oh wow, ich bin froh, dass ich endlich diese Konversation gefunden habe, denn das ist mir auch passiert. Ich wusste zunächst nicht, wonach ich suchen sollte, weil npm test für mich auf Travis das Zeitlimit überschritten hatte, ohne Rückmeldung. Erst als ich versuchte, Timeouts zu überschreiben (was Sie normalerweise dem Support schreiben müssten), bekam ich eine ENOMEM , was mich schließlich hierher führte.

Der Wechsel zu JOBS=2 npm test hat dazu geführt, dass meine Builds erneut bestanden wurden (oder zumindest aus den richtigen Gründen fehlgeschlagen sind 😆), also danke an alle!

Vielleicht ist mir das nur auf Travis passiert, weil die Anwendung starke Abhängigkeiten hat, aber es war schwierig zu debuggen und ich habe es lange Zeit einfach ignoriert, also scheint es eine Überlegung wert zu sein, wie man damit im Ember-CLI-Blueprint oder anderweitig umgeht es.

In meinen Tests läuft ein Standard-Out-of-the-Box-Ember-Projekt ohne Änderungen einwandfrei, die Einführung einer Reihe von Abhängigkeiten verursacht letztendlich den Fehler.

Ich bin mir nicht sicher, was in einem Ember-Projekt als "viele" Abhängigkeiten angesehen wird. Aber da Travis der De-facto-Weg ist, CI mit Ember-Addons zu machen, denke ich, dass die Leute dies immer mehr sehen werden, wenn die Leute anfangen zu aktualisieren / neue Addons zu erstellen.

Ich habe vor kurzem damit begonnen, alle Abhängigkeiten für das Ember-Burger-Menü-Projekt zu aktualisieren, und erhalte diesen Fehler.
Beispiel:
https://travis-ci.org/offirgolan/ember-burger-menu/builds/275031562?utm_source=github_status&utm_medium=notification
https://github.com/offirgolan/ember-burger-menu/pull/95

Oh! Vielen Dank @mwisner für das Posten dieses Problems und @rwjblue für die vorübergehende Lösung! Ich habe nur ein paar Stunden damit verbracht zu verstehen, warum meine Builds fehlschlagen. Das Setzen von JOBS auf 1 reicht aus 🎉

Das Schließen als JOBS=1 wurde vor einiger Zeit als Standard in Ember-Cli aktualisiert. Entschuldigung für die Probleme...

Ich musste nur JOBS=1 hinzufügen, um dieses Problem auf 3.16.0 zu beheben. Gab es einen Rückfall?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen