by shigemk2

当面は技術的なことしか書かない

まとめ あなたのScalaを爆速にする7つの方法 #ScalaMatsuri #sm_c

  • アドテクスタジオのひと
  • 許諾事項 並列実行については考慮していない

EC2インスタンス メモリ30ギガ 8コア

Random Read

  • 2ギガの文字列の羅列のファイル

  • SSD

  • memcache

Aのほうがはやい!

  • SUIKAという文字列をサーチする
  • memcacheよりfileのほうが速いのはmemory mapped fileを使っているから(ユーザ空間のみでディスクの内容をバッファリングできるから)
  • memcacheのほうが遅いのはキャッシュ出来る最大量は1MBまでなので、2048回アクセスしないといけないのがしんどい
    • なお、JVMの環境だとmemory mapped fileは2GBまでしか使えない
    • Apache Spark MyLib
  • memory mapped fileを使うと高速になる

for内包表記 vs flatmapとmap

  • 答えは同じ
  • ベンチマークをとっても全く一緒
    • デコンパイルすると全く一緒の結果が出た!
    • バイトコードレベルだと全く同じだから

append & insert

  • collectionの性能特性

http://docs.scala-lang.org/ja/overviews/collections/performance-characteristics.html

  • VectorとArrayBuffer 末尾再帰はどっちがはやい
    • ArrayBufferのほうが速い
  • Vectorは既存のインスタンスにコピーしている
  • ArrayBufferはインスタンス自身をリサイズしている " ソースコードを読もう

  • var Listとval ListBuffer 先頭挿入はどっちがはやい

    • var Listのほうが速い
    • Listは結構速い
    • 先頭挿入の場合はListのほうが速い
  • Listはheadとtailをサーチして先頭挿入
  • ListBufferは内部変数の再代入してる

  • 末尾追加はArrayBuffer ListBuffer

  • 先頭挿入はListを使うと良い

remove collection

  • var List vs val ListBuffer 削除はどちらが速いか
    • ListBufferのほうが速い
  • StreamはSOになってしんどい
  • Buffer系のやつが速い
  • ListのdropRightはO(N)
  • ListBufferの削除は定数時間
  • 削除のほうが線形の増加がすごい
    • dropRightよりtakeのほうが少しだけ速い
  • 大量の要素を削除するときはListBuffer/ArrayBuffer 書き込み操作はmutableなやつのほうが速い

random read

  • Vector vs ListBufferどちらが速いか
    • Vectorのほうがはやい(ListBufferよりも速い)
    • ランダムアクセスについてはArrayBuffer Vectorのほうがはやい
  • Arrayのrandom readは定数時間 ArrayBufferとVectorは内部的にArrayが使われている
  • Arrayの仲間はrandom readのほうが速い

fibonacci sequence

  • StreamとArrayどちらが早くフィボナッチ数列を作ることができるか
    • Streamのほうが速い
    • Streamは遅延評価リストなので、呼び出したいタイミングで呼び出せる
      • take(n)がミソ 呼び出したいタイミングで計算する
      • StreamをtoListをすると圧倒的に遅くなる
      • 実際の時間は再帰よりO(N)のほうが速い
  • 遅延評価は便利だけど具現化するときはそれなりのコストがかかる

regexp

  • 正規表現はCPUリソースを食う 特に\wはやばいO(N2)
  • \wの数が増えれば増えるほど遅くなる findAllIn vs findPrefixOfとquantifier
    • findPrefixOfとquantifier
  • /.+でバックトラッキングが発生している
  • 文字列の後方をサーチするものなので、ある文字列にマッチさせたものの後ろをとるほうが速い
  • findAllInはすべてマッチさせてしまうので遅い
  • spray-routingのソースコードについて、URIのパスを区切るところがあるけど、findPrefixOfが使われている

  • 先頭から1回だけマッチさせたい場合は、findPrefixOfのほうが速い

  • バックトラッキングが発生するとおそくなることだけ覚えておこう

まとめ

  • memory mapped fileは速い
  • forとflatmap&mapは同じ
  • コレクションの更新はBuffer
  • 先頭挿入はList
  • Arrayの仲間はrandom readで速い
  • 遅延評価は便利だが、具現化するときはリソースを食う
  • findPrefixOfは便利 正規表現を使うときはその計算量を考えるべし