LoginSignup
43
12

More than 5 years have passed since last update.

elmのコンパイラがめっちゃ遅かったから速くした

Last updated at Posted at 2018-08-20

社内LTの資料(ほぼ)そのままなので雑な記事です

elmのコンパイラがめっちゃ遅かったから速くした


大筋

  • これをやってみたというわけです-> https://medium.com/@antewcode/faster-elm-builds-e0669580ee67
  • めっちゃelmを書いていたらビルドに260秒くらいかかってた
  • 解決するためにコンパイラのメトリクスをとった
  • GCに問題があったのでヒープサイズ変更した
  • ビルドは40秒くらいになった。嬉しい。

elmを書いていたらビルドに260秒くらいかかってた

  • 差分ビルドは変更するモジュールによるが、5秒 ~ 1分
    • 変更モジュールの参照が多いほど時間は伸びる
  • LOC2万5千くらい

  • elmのコンパイラーにはバグがあってビルドが長くなるケースある
  • 複雑なパターンマッチ (ex. タプル)があるとコンパイラがCPU100%食いつぶす -> 複雑なパターンマッチをアプリケーションのコードから取り除く

複雑なパターンマッチをアプリケーションのコードから取り除く

compareMonth : Month -> Month -> Order
compareMonth m1 m2 =
  case (m1, m2) of
    (Jan, Jan) -> EQ
    (Jan, _)   -> LT
    (Feb, Jan) -> GT
    (Feb, Feb) -> EQ
    (Feb, _)   -> LT
    (Mar, Jan) -> GT
    ...

複雑なパターンマッチをアプリケーションのコードから取り除く

compareMonth : Month -> Month -> Order
compareMonth m1 m2 =
  case m1 of
    (Jan) -> case m2 of
        (Jan) -> EQ
        (_) -> LT
    (Mar) -> 
    (Feb) -> case m2 of
        (Jan) -> GT
        (Feb) -> EQ
    (_) -> LT
    (Mar) -> case m2 of
    ...

複雑なパターンマッチを取り除いたが

効果がなかった

(いうほど複雑なパターンマッチなかった)


解決するためにコンパイラのメトリクスをとった

  • elmのコンパイラにRTSオプション、ランタイムでのオプションを渡すとコンパイラの実行時リソースのメトリクスが取れる
    • elmのコンパイラがhaskellによって作られるバイナリなのでできた

  • 取れるメトリクス(一部)
  INIT    time    0.000s  (  0.001s elapsed)
  MUT     time   55.344s  ( 40.095s elapsed)
  GC      time  169.701s  ( 54.688s elapsed)
  EXIT    time    0.003s  (  0.020s elapsed)
  Total   time  225.050s  ( 94.803s elapsed)

GCしすぎ! """GC time 169.701s"""


GCが多い -> heapサイズが足りてないんじゃない?メモリが全然使われてない

269 MB total memory in use (0 MB lost due to fragmentation)

haskellのRTS(ランタイムオプション)からheapサイズをコントロールする
-> そういう類のオプションがあった(厳密にそうなのかはわからない)


  • 渡してみた elm-make +RTS -A126M -RTS src/Main.elm

効果がなかった..? """GC time 169.701s"""

269 MB total memory in use (0 MB lost due to fragmentation)
  • うまくオプションが渡ってなさそう。。。

  • haskellのコンパイラ解説サイト様より
リンク時に-rtsoptsフラグを適切に設定していたなら、
プログラムを実行するときにRTSオプションを
コマンド行で与えることができる。
  • elmのコンパイラは-rtspotsが設定されていなかった(オワタ - 厳密にいうと設定されてないわけじゃないけど使えない的な

コンパイラのコンパイルを試みた

  • haskellのツール周りを調べてどうやらcabalというものでelmはコンパイルできるようだ -> 諦めた
  • yak shavingにもほどが過ぎた
    • GCC周りでエラー
    • elmのコンパイラが依存しているhaskellライブラリ依存解決でエラー

インターネッツに再コンパイルされたコンパイラが落ちてた

  • 自分と同じようなことをしている人がいた
  • 心優しいその人がmac用のバイナリを例のオプションをつけてコンパイルしてくれていた

  • 渡してみた
elm-make +RTS -A126M -RTS src/Main.elm
INIT    time    0.001s  (  0.002s elapsed)
MUT     time   39.714s  ( 41.069s elapsed)
GC      time    4.076s  (  2.170s elapsed)
EXIT    time    0.003s  (  0.003s elapsed)
Total   time   43.797s  ( 43.244s elapsed)

効果があった! """GC time 4.076s"""

1209 MB total memory in use (0 MB lost due to fragmentation)
  • メモリもふんだんに使われている
GC time: 169.701s -> 4.076s
Total time: 225.050s -> 43.797s
  • GC時間は40倍短く
  • トータル6倍速く

結論

  •  elmのコンパイラをrtsフラグ有効にしてコンパイルし直したやつ、またはhttps://medium.com/@antewcode/faster-elm-builds-e0669580ee67 で配布してくれているやつを使いつつRTSオプションでメモリいっぱい使うようにしたら速くなることもある。

ちなみに

  • 次のバージョンのelmコンパイラではRTSオプションを標準で渡せるのでコンパイラのコンパイルはいらない(はず)

追記

  • 0.19でRTSオプションが渡せるようになってました。
  • 0.19ではRTSオプション気にしなくても超早くなりました。

参考url
elmのビルド速くしたぜ記事:
https://medium.com/@antewcode/faster-elm-builds-e0669580ee67
haskellのランタイムオプション説明してくれているページ:
: http://www.kotha.net/ghcguide_ja/7.6.2/runtime-control.html

43
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
12