2022年2月17日木曜日

gcc -fanalyzer が実行しきれる CI サービスを求めて・・・

 先週書いた記事の続き
ブログズミ: メモリ不足で gcc が kill される場合になんとかビルドする

上記記事の対応で CircleCI 上でいくつかメモリリークなどの検知がされたのですが、誤検知を無視したりコード修正したりしてエラーが出ない状態にしていったものの、テストコードのビルドが最後まで完了しきらない状態に陥ってしまいました。

状態としては、無出力タイムアウトが発生していたので CircleCI の no_output_timeout を延ばして回避しようとしました。
しかし、5時間とかにしても一向に終わらない。。
エラー(警告)が出ない状態であれば ggc の設定を緩和しても kill されることはなくなったので、コンパイル速度優先の設定にしても無出力タイムアウトしてしまいダメ。

長いタイムアウト設定で何度もトライアンドエラーしてるとクレジット消費に悪影響が出るので、一旦 CircleCI を諦めて他のサービスを検討することにしました。

なるべくリソース豊富はところ、かつビルド時間が無料プランの制限を圧迫しないものを探しています。
各サービスのリソース状況はこちらのリポジトリで調べたものを参考にしています。
https://github.com/srz-zumix/ci-specs
拙著にも記載してます。(宣伝)
https://srz-zumix.booth.pm/

以下、随時更新していきます。

1. GitHub Actions (kill)
2. CircleCI (no output timeout)
3. RazorOps (kill)
4. AzurePipelines (timeout 360min)


2022年2月10日木曜日

メモリ不足で gcc が kill される場合になんとかビルドする

Process completed with exit code 137.
g++: fatal error: Killed signal terminated program cc1plus
compilation terminated.
上記のようなエラーで gcc が終了した場合、実行環境のメモリ不足が原因の場合があります。
このような場合どうしたらよいのでしょうか?

正解は「メモリを増やす」です!


・・・ですが。
そうはいかない場合もありますよね。特に筆者は CI サービスを無料の範囲で使っているので、実行環境のスペックには制限があり、増やすことが難しいです。

それでも、それでもビルドがしたい。

・・・ので無理やりがんばります。

並列数を減らす
単純な話ですが make などで並列してる場合は並列数を減らしましょう。

ガーベージコレクションの設定を調整する
--param ggc-min-heapsize

上記のコンパイラーオプションを使うことで、コンパイラーの GC (ガベージコレクション)の設定ができます。
それぞれどういう設定かの
ggc-min-expand は % 単位で、ヒープ拡張できる最小の割合。
RAM が 1GB 以上あれば 100% がデフォルト、それ以外の場合は 30% を下限に設定される。
ggc-min-heapsize は GC 開始する最小のヒープサイズ。この値が小さいと GC 頻度が上がる。デフォルトは 4MB〜128MB の間で RAM サイズや RLIMIT の数値で決定されるもよう。

ggc-min-expand/ggc-min-heapsize 両方を 0 にすると常に Full GC することになる。
これらの値を調整することで、少メモリな環境でもビルドできるようになる。
ただし、時間はめちゃくちゃかかる
片方(ggc-min-expand)0 だけでも相当時間かかってタイムアウトしてたので、無料 CI 環境では厳しい。

gcc -fanalyzer をやりたくて ggc の調整してたけど、時間かかりすぎて終わらない・・
https://github.com/srz-zumix/iutest/pull/564
もうちょいスペック高い CI を検討してみる。