Successfully reported this slideshow.
Your SlideShare is downloading. ×

Scalaのコンパイルを3倍速くした話

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 19 Ad

More Related Content

Slideshows for you (20)

Advertisement

Recently uploaded (20)

Advertisement

Scalaのコンパイルを3倍速くした話

  1. 1. TBD
  2. 2. 自己紹介 • @todesking • ジャバ(バッチ) → Ruby(ソシャゲサーバサ イド) → Scala(広告システムサーバサイド)
  3. 3. 近況 • ビルドシステムと戦っている http://twitter.com/todesking/status/488675512424734720! sbt/ivy使えばパッケージ管理の問題を解決してくれるというのは幻覚だったということがわかった、社会は厳しい
  4. 4. 何はともあれ • みんな大好きなあの話をします
  5. 5. Scalaのコンパイルが 3倍 速くなった話
  6. 6. 問題 https://twitter.com/todesking/status/449393123894906880! Scala、みんなコンパイルの遅さに困ってるが解決手段が無いためコンパイル中に音楽を流すプラグインを作成して慰みを得ているということがわかった。Ruby 使ったほうがいいと思う。!
  7. 7. (́・_・`) • https://twitter.com/ todesking/status/ 449406714123927553
  8. 8. どれくらい遅いか [Info] Compiling 278 Scala sources and 4 Java sources to target/scala-2.10/classes... . . . . . . . .[success] Total time: 425 s
  9. 9. ?! • 他のプロジェクト [info] Compiling 234 Scala sources and 5 Java sources to target/scala-2.10/ classes... . . [success] Total time: 64 s ! はやい(相対的に)
  10. 10. さすがに死っぽいので 調査しました • 特定のプロジェクトだけすごく遅い • プロジェクトの設定? • 使用ライブラリ?
  11. 11. hprof: JVM標準 プロファイラ • jvmオプションつけてsbt compile • 結果はjava.hprof.txtに出力されま す $ sbt -J-agentlib:hprof=cpu=samples,depth=5 clean compile
  12. 12. 結果見る • depth=5で荒い解析 • クラスのロードが大量にされている……? rank self accum count trace method 1 12.04% 12.04% 2158 300093 java.util.zip.ZipFile.getEntry 2 9.90% 21.95% 1775 300065 java.lang.Throwable.fillInStackTrace 3 7.21% 29.16% 1293 303874 java.lang.Class.forName0 4 5.40% 34.56% 967 300200 java.lang.Throwable.fillInStackTrace 5 2.76% 37.32% 495 300061 java.lang.ClassLoader.defineClass1 6 1.66% 38.98% 298 300616 java.lang.ClassLoader.findLoadedClass0 7 1.32% 40.30% 236 303922 scala.collection.IndexedSeqOptimized$cl 8 1.27% 41.57% 228 303902 scala.collection.IndexedSeqOptimized$cl 9 1.27% 42.84% 228 301496 java.net.SocketInputStream.socketRead0 10 1.15% 43.99% 206 300711 java.lang.ClassLoader.findLoadedClass0 11 1.03% 45.02% 184 304106 java.lang.Class.forName 12 0.95% 45.97% 170 300630 java.lang.ClassLoader.loadClass 13 0.86% 46.83% 155 304054 java.lang.Object.hashCode 14 0.84% 47.68% 151 303870 java.io.UnixFileSystem.getBooleanAttrib 15 0.84% 48.51% 150 303879 java.lang.ClassLoader.loadClass 16 0.81% 49.33% 146 304060 java.security.AccessController.doPrivil
  13. 13. スタックトレースの詳細 • 処理時間上位の処理を見ていく • この処理がどこから呼ばれてるかを知りたい • スタックトレースの深度を増やして再実行 TRACE 300093: java.util.zip.ZipFile.getEntry(ZipFile.java:Unknown java.util.zip.ZipFile.getEntry(ZipFile.java:306) java.util.jar.JarFile.getEntry(JarFile.java:226) java.util.jar.JarFile.getJarEntry(JarFile.java:209) sun.misc.URLClassPath$JarLoader.getResource(URLClass
  14. 14. 結果見る • depth = 50 • トレース深度を増やしてみる CPU SAMPLES BEGIN (total = 22833) Tue Jul 15 15:02:57 2014 rank self accum count trace method 1 0.58% 0.58% 132 312316 java.util.zip.ZipFile.getEntry 2 0.56% 1.14% 128 313147 java.util.zip.ZipFile.getEntry 3 0.53% 1.67% 121 313118 java.util.zip.ZipFile.getEntry 4 0.45% 2.12% 103 313343 java.lang.Object.hashCode 5 0.44% 2.56% 100 313093 java.util.zip.ZipFile.getEntry 6 0.42% 2.98% 96 306293 java.net.SocketInputStream.socketRea 7 0.42% 3.39% 95 312675 java.util.zip.ZipFile.getEntry 8 0.38% 3.78% 87 314506 java.util.zip.ZipFile.getEntry 9 0.36% 4.14% 83 313104 java.lang.Class.forName0 10 0.32% 4.45% 72 306826 java.net.SocketInputStream.socketRea 11 0.29% 4.74% 66 312099 java.util.zip.ZipFile.getEntry 12 0.28% 5.02% 63 313314 java.lang.Class.forName0 13 0.27% 5.29% 61 313184 java.lang.Class.forName0 14 0.25% 5.54% 57 312970 java.lang.Throwable.fillInStackTrace 15 0.25% 5.79% 57 313083 java.util.zip.ZipFile.getEntry 16 0.24% 6.03% 55 312783 java.lang.Class.forName0
  15. 15. 結果見る • 怪しいものが TRACE 313147: java.util.zip.ZipFile.getEntry(ZipFile.java:Unknown line) java.util.zip.ZipFile.getEntry(ZipFile.java:306) java.util.jar.JarFile.getEntry(JarFile.java:226) java.util.jar.JarFile.getJarEntry(JarFile.java:209) : scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scal scala.reflect.macros.runtime.Evals$class.eval(Evals.scala:16) scala.reflect.macros.runtime.Context.eval(Context.scala:6) scalikejdbc.SQLInterpolationMacro$.selectDynamic(SQLInterpolationMacro. sun.reflect.GeneratedMethodAccessor3.invoke(<Unknown Source>:Unknown li java.lang.reflect.Method.invoke(Method.java:606) scala.tools.nsc.typechecker.Macros$$anonfun$scala$tools$nsc$typechecker
  16. 16. 原因特定 • scalikejdbcのマクロが原因 • context.eval()が遅い 26 object SQLInterpolationMacro {! 27 ! 28 def selectDynamic[E: c.WeakTypeTag](c: Context)(name: c.Expr[ 29 import c.universe._! 30 ! 31 val nameOpt: Option[String] = try {! 32 Some(c.eval(c.Expr[String](c.resetAllAttrs(name.tree.dupl 33 } catch {! 34 case t: Throwable => None! 35 }! 36
  17. 17. ツイッター便利 https://twitter.com/todesking/status/461816289086820352
  18. 18. 修正しました • [success] Total time: 122 s • scalikejdbc 1.7.7からは速いよ https://github.com/scalikejdbc/scalikejdbc/pull/241
  19. 19. 学び • 基本的にコンパイルは遅い(社会は厳しい) • でもユースケースによっては高速化の余地が! • コンパイラがJVM上で動くので既存のプロファ イリングノウハウが使えて便利 • Scalaエコシステムはフロンティア • 目が届いてないとこが残ってるのでコントリビュートチャン スだ • ツイッター便利

×