DELAEMON BLOG

Live as if you were to die tomorrow. Learn as if you were to live forever.

Nodejs Jest CiecleCI

課題

CricleCIでReactjs + Jest でテストを実行していたら、最近になってメモリの制限にひっかかって失敗するようになった。

原因

CircleCI の ビルドに割り当てられる最大メモリ容量は4GB
Your build hit the 4G memory limit - CircleCI

テストフレームワーク Jest は 見えてるCPU数 - 1Coreを使う
https://github.com/facebook/jest/blob/ec782b567bf343d9d278cd79265a1af2bfc3e83c/packages/jest-runtime/src/cli/index.js#L72

nodejsはデフォルトのメモリ割り当ては1.5GBまで。v8起因。オプションつければ上げ下げできる(GCの実行判定調整)
--max_old_space_sizeで調整可能。

CircleCIはホストが8Core。コンテナへのCPU割り当てがどうなってるかは不明だけど、メモリの最大利用サイズは以下
8Core × 1.5GB = 12GB
4Core × 1.5GB = 6GB
2Core × 1.5GB = 3GB

対策

JestのWorker数を制限すればいい。
maxWorkersオプションで指定できる。

% jest --maxWorkers=2

テストの中身によるかもだけど、--maxWorkers=1にしても実行時間に大差はなかった。

GCするメモリ量も決めておくと、コマンド見ただけでイメージつきやすくて、Worker数変更したときにケアしないといけないことに気付き易くて、安心

% node --max_old_space_size=2048 jest --maxWorkers=2

無事CIはSuccess状態に戻った

おまけ

v8のオプションには他にも細かくメモリ関連のオプションが付いており、nodejsからも指定できる。

% node -v
v6.4.0
% node --v8-options | grep size
  --optimize_for_size (Enables optimizations which favor memory size over execution speed)
  --max_inlined_source_size (maximum source size in bytes considered for a single inlining)
  --typed_array_max_size_in_heap (threshold for in-heap typed array)
  --stack_size (default size of stack region v8 is allowed to use (in kBytes))
  --min_semi_space_size (min size of a semi-space (in MBytes), the new space consists of twosemi-spaces)
  --max_semi_space_size (max size of a semi-space (in MBytes), the new space consists of twosemi-spaces)
  --max_old_space_size (max size of the old space (in Mbytes))
  --initial_old_space_size (initial old space size (in Mbytes))
  --max_executable_size (max size of executable memory (in Mbytes))
  --heap_profiler_trace_objects (Dump heap object allocations/movements/size_updates)
  --sim_stack_size (Stack size of the ARM64, MIPS64 and PPC64 simulator in kBytes (default is 2 MB))
  --force_marking_deque_overflows (force overflows of marking deque by reducing it's size to 64 words)