Ember.js: [2.15.0] — Ошибки Ember build out of memory при использовании инструментов CI.

Созданный на 7 сент. 2017  ·  23Комментарии  ·  Источник: emberjs/ember.js

Параллельная транспиляция babel была введена в ember 2.15. (https://github.com/babel/broccoli-babel-transpiler#number-of-jobs)

По умолчанию broccoli-babel-transpiler использует системные ресурсы (процессор) для определения количества заданий, которые могут выполняться параллельно.

Большинство современных инструментов CI используют докер, чтобы изолировать сборки от других сборок, работающих на данном сервере. Это позволяет им использовать большие виртуальные машины для запуска большого количества сборок, которые в значительной степени изолированы друг от друга. Например, виртуальные машины, на которых работает Circle CI, обычно имеют 36 ядер ЦП. Но сами сборки ограничены двумя.

Проблема возникает при попытке использовать традиционные средства для определения того, какие ресурсы доступны для программы. Например, чтобы определить количество процессоров, использующих node, вы можете сделать node -e "console.log(require('os').cpus().length);" . Однако эта информация фактически сообщает о ресурсах экземпляра, а не об ограниченных ресурсах, доступных для контейнера Docker. В результате все, что работает, думает, что у него есть доступ к 36 ядрам, но на самом деле их всего два.

Я создал пример репо:
https://github.com/mwisner/ember-circleci-example , в котором вы можете увидеть как пройденную, так и неудачную историю сборки (https://circleci.com/gh/mwisner/ember-circleci-example) (https:// travis-ci.org/mwisner/ember-circleci-example/builds) (я еще не исправил сборку travis.)

Проверенные инструменты непрерывной интеграции
-- Круг КИ 2.0
-- Круг КИ 1.0
-- Travis CI (сбой при предоставленном по умолчанию Travis CI)

Документы по параллельным заданиям: https://github.com/babel/broccoli-babel-transpiler#number -of-jobs

Когда возникают ошибки, они выглядят примерно так, как показано ниже. Однако во многих ситуациях (например, travis CI) он просто отключается через 10 минут без какой-либо информации)

#!/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

Решение «Обходной путь», предоставленное @rwjblue , заключается в том, чтобы конкретно определить количество заданий, которые вы хотите использовать для параллельной транспиляции, используя преимущества переменной ENV JOBS . (https://github.com/mwisner/ember-circleci-example/blob/09c63e11c34d4cdfe602b63166b71e6f31e30f3c/.circleci/config.yml#L42)

Has Reproduction

Самый полезный комментарий

Я немного поболтал об этом с @mwisner и @kiwiup на выходных, и мы выяснили, что это связано с новым параллелизмом, который был добавлен в broccoli-babel-transpiler. По умолчанию используется распараллеливание с количеством процессоров, присутствующих в данный момент. К сожалению, в CircleCI это отображается как 36 процессоров, но само задание ограничено двумя одновременными процессами (а также ограничено доступной оперативной памятью).

Исправление здесь заключается в том, чтобы установить для переменной среды JOBS значение 1, чтобы по существу отключить параллелизм в CI.

Все 23 Комментарий

Похоже, что есть люди, у которых есть тесты кармы, работающие с этим шагом:

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

После последних нескольких часов я еще не смог заставить это работать успешно, но я почти уверен, что это не конкретно ember.js.... На данный момент закрытие.

У меня такая же проблема, и я не могу решить.

Я немного поболтал об этом с @mwisner и @kiwiup на выходных, и мы выяснили, что это связано с новым параллелизмом, который был добавлен в broccoli-babel-transpiler. По умолчанию используется распараллеливание с количеством процессоров, присутствующих в данный момент. К сожалению, в CircleCI это отображается как 36 процессоров, но само задание ограничено двумя одновременными процессами (а также ограничено доступной оперативной памятью).

Исправление здесь заключается в том, чтобы установить для переменной среды JOBS значение 1, чтобы по существу отключить параллелизм в CI.

@rwjblue спасибо за контекст здесь!

Даже с параллелизмом Circle я бы подумал (потому что они разделены на контейнеры), что тогда JOBS всегда должно быть 1. Итак, по...

по существу отключить параллелизм в CI

... Я предполагаю, что вы хотите отключить параллелизм broccoli-babel-transpiler, а не контейнерный параллелизм Circle. Это правильно?

@eric-hu это тоже кажется вам правильным чтением? Следует ли нам ожидать исправления от Circle, чтобы отображались процессоры, фактически доступные в задании? Предотвращает ли это какой-либо параллелизм на стороне Circle (например, путем разделения тестов на что-то вроде ember-exam )?

Я не уверен, можем ли мы ожидать исправления от самих кругов... Я не супер на 100%, но я думаю, что это скорее проблема Докера, чем конкретно проблема круга. Или, может быть, проблема Node + Docker не в состоянии точно определить ограничения процессора/памяти, налагаемые контейнером докера.

Я создал это репо для экспериментов: https://github.com/mwisner/ember-circleci-example.

Он включает в себя Circleci 2.0 (работает с обходным решением JOBS=1, предоставленным @rwjblue) (https://github.com/mwisner/ember-circleci-example/blob/master/.circleci/config.yml)

Наряду со сборками общественного круга: https://circleci.com/gh/mwisner/ember-circleci-example/83

Однако я также добавил репозиторий в travis ci, который также использует Docker для сборки, я еще не исправил файл конфигурации travis, но вы можете видеть, что сборки travis терпят неудачу с предоставленной конфигурацией travis (https://travis- ci.org/mwisner/ember-circleci-example/builds)

Спасибо @mwisner. Правильно ли я понял, что JOBS=1 _не_ означает, что мы не можем распараллелить сами сборки?

@JoshSmith Да, если я правильно понимаю, это нужно для отключения параллелизма в broccoli-babel-transpiler. Не кружись сама. Так что теоретически использование параллелизма Circleci + jobs = 1 было бы хорошо?

Но лично я не экспериментировал с использованием функциональности параллелизма в Circleci. Поэтому я не уверен на 100%, как будет выглядеть файл конфигурации для этого.

Имеет смысл! Я хотел быть уверен, что просто провел четкую границу между тем, что казалось здесь двумя разными вариантами использования слова «параллелизм», так что я думаю, что наконец-то нахожусь на одной странице.

Я заметил, что вы устанавливали JOBS=1 вручную в конфигурации до ember test , но похоже, что это можно установить на уровне переменной ENV в Circle, возможно, без проблем?

Это также не относится к тестированию. Проблема OOM возникает на этапе сборки Ember Test. Я также тестировал запуск ember build с тем же результатом OOM.

@JoshSmith Я верю, что установка JOBS=1 на уровне env var тоже сработает, но я не подтвердил.

Я заметил, что существует шаблон для установки env vars для команд ember cli для нескольких дополнений:

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

Так что я просто уходил от этих шаблонов использования.

Не зная _ничего_ о том, как на самом деле работает broccoli-babel-transpiler , мне трудно сказать, может ли Circle (или Docker, или кто-то еще) предоставить исправление для этого. Мое непрофессиональное _чувство_ - не размышление - вокруг этого будет заключаться в том, что если бы транспилятор мог получать явные инструкции о том, сколько ядер доступно, то мы, возможно, могли бы избежать здесь проблемы чистого вывода. Опять же, это исходит из места глубокого невежества.

Просто для обновления я могу успешно запустить эти сборки, установив для $ JOBS значение 1 в настройках среды Circle. Еще раз спасибо @rwjblue , @mwisner и @eric-hu.

Я только что столкнулся с этой же проблемой на CircleCI, и JOBS=1 также исправили ее для меня, всем спасибо :v:

@eric-hu это тоже кажется вам правильным чтением? Следует ли нам ожидать исправления от Circle, чтобы отображались процессоры, фактически доступные в задании? Предотвращает ли это какой-либо параллелизм на стороне Circle (например, путем разделения тестов чем-то вроде ember-exam)?

@JoshSmith есть две концепции параллелизма, о которых следует помнить для CircleCI 2.0:

A. Параллелизм для каждой команды, ограниченный количеством ядер, доступных для группы контейнеров. По умолчанию каждой группе контейнеров выделяется 2 доли ЦП, что гарантирует получение ими 2 ядер ЦП. Существует премиальная функция настраиваемых ресурсов, которая позволяет вам выбирать большую / меньшую долю (1, 4, 8 на мой взгляд).

B. Параллелизм CircleCI, который вы можете представить себе как «на сколько машин [1] я хочу разделить это?». Это полезно для изоляции тестов, когда вы можете запустить 2 теста одновременно и оба записывать в базу данных. Это менее полезно, скажем, для переноса ваших ресурсов; вы, вероятно, хотите, чтобы все ваши тесты выполнялись с транспилированными активами.

Относительно A: поскольку у вас есть 2 ядра, гарантированно доступных по умолчанию, вы можете запустить нужную команду с JOBS=2. Это может ускорить выполнение, но я не проверял, работает ли это.

Что касается B: даже при JOBS=1 вы все равно можете использовать параллелизм CircleCI для ускорения набора тестов.

Что касается «кто должен это исправить», я считаю это давней проблемой с несколькими инструментами контейнеризации. Инструменты контейнеризации CircleCI 2.0 и 1.0 — Docker и LXC соответственно — пропускают информацию о хост-системе для многих распространенных команд Linux, таких как те, которые используются для проверки количества доступных ядер. Так было в течение нескольких лет, я думаю, что если бы было простое решение, это было бы решено сейчас. Еще больше усложнив ситуацию, CircleCI изменил модель доступности ядра ЦП с 1.0 на 2.0. В версии 1.0 вы получали фиксированное количество ядер для работы. В версии 2.0 вы получаете назначенные доли ЦП, чтобы гарантировать минимальное количество ядер. Если вы находитесь на полностью загруженном хосте, вы получите как минимум столько же ядер. Если вы работаете на недостаточно загруженном хосте, вам будет доступно больше ядер. Однако такие инструменты, как broccoli-babel-transpiler , как правило, назначают количество ядер, которое они будут использовать только один раз, и доступные ресурсы могут меняться в течение срока выполнения программы. Лучше просто жестко закодировать сценарии CI, чтобы использовать гарантированно доступные ресурсы.

[1] Ваш код может не работать на N машинах для N параллелизма. Но вы можете думать об этом таким образом, поскольку они эффективно изолированы друг от друга.

Только что попробовал JOBS=2 в моем приложении, и сборка также прошла успешно. Должен ли это быть каноническим советом здесь?

Нет заметной разницы во времени между этими значениями в моей небольшой выборке FWIW.

@rwjblue Я знаю, что вы рекомендовали добавить эту проблему в репозиторий ember-cli. Однако я открыл эту проблему, когда впервые обнаружил проблему, и похоже, что она была обнаружена до того, как я смог открыть другую в репозитории ember-cli... Вы хотите, чтобы я открыл там еще одну проблему и просто сослался на этот разговор? Знаете ли вы, как легко его переместить?

Я повторно открыл эту проблему, потому что после дополнительного тестирования предоставленная конфигурация travisci.yml, поставляемая с ember, также столкнулась с этой проблемой.

Хотя я понимаю, что ember не поддерживает круг, я думаю, что было бы неплохо, по крайней мере, исправить эту проблему в поставляемом файле travisci.yml.

Я также обновил заголовок и описание, чтобы сделать его немного более общим и не привязанным конкретно к CircleCI.

@eric-hu большое спасибо за подробный совет здесь. Очень полезно для сообщества, чтобы понять, что происходит в деталях. Было бы здорово увидеть канонический пример в документации для каждой платформы, хотя я понимаю и ценю время, которое это займет.

@bgentry спасибо, что сообщили о разнице во времени. Я надеялся, что это ускорит время сборки. Я также собираюсь установить JOBS=2 , но я немного разочарован этим, поскольку мое время сборки, безусловно, является моим самым большим препятствием в ускорении заданий Circle.

о ничего себе, я рад, что наконец нашел этот разговор, потому что это происходило со мной тоже. Сначала я не знал, что искать, потому что npm test истекал для меня на Трэвисе, а обратной связи не было. Только когда я попытался переопределить тайм-ауты (что обычно нужно написать в службу поддержки), я получил ENOMEM , что, наконец, привело меня сюда.

Изменение на JOBS=2 npm test привело к тому, что мои сборки снова прошли (или, по крайней мере, не прошли по правильным причинам 😆), так что всем спасибо!

Может быть, это происходило только со мной на Travis, потому что приложение имеет большие зависимости, но его было сложно отлаживать, и я просто долгое время игнорировал его, поэтому, похоже, стоит подумать, как справиться с этим в схеме Ember CLI или как-то иначе. Это.

В моем тестировании стандартный проект ember без каких-либо изменений проходит нормально, введение набора зависимостей приводит к ошибке.

Я не уверен, что считается «множеством» зависимостей в проекте Ember. Но поскольку travis де-факто является способом сделать CI с аддонами ember, я думаю, что по мере того, как люди начнут обновлять / создавать новые аддоны, люди будут видеть это все больше и больше.

Недавно я начал работать над обновлением всех зависимостей для проекта ember-burger-menu и получаю эту ошибку.
Пример:
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

Ой! Спасибо @mwisner за публикацию этой проблемы и @rwjblue за временное решение! Я просто потратил несколько часов, пытаясь понять, почему мои сборки терпят неудачу. Установка JOBS на 1 делает свое дело 🎉

Закрытие как JOBS=1 было обновлено по умолчанию в ember-cli некоторое время назад. Извините за беспокойство...

Мне просто нужно было добавить JOBS=1 , чтобы исправить эту проблему в 3.16.0. Был ли регресс?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги