自作のnoboxというライブラリの現状報告

すでにこのライブラリのことについて2回書いてますが、
primitive型のArrayのwrapper
scala.collection.mutable.ArrayOpsの遅さ

思ったより飽きずに開発続いてるので、また現状報告

  • 誰も使ってない*1と思うが、tagをつけておいたほうがわかりやすいだろうから、一応もう0.1.0、0.1.1、0.1.2、0.1.3と4回もリリースしてる
  • sonatypeへの登録面倒なので*2bintraryというサイト利用 https://bintray.com/xuwei-k/maven/nobox
  • sbt-releaseというplugin導入して、tag打ったり色々自動でやってくれるので便利
  • 全部がコード生成なため、この問題が発生し sbt で自動生成したコードが source の jar に含まれない件、そのために、無理矢理で問題だらけなworkaroundをしているのですが、なにかもっといい方法ないですか
  • 0.1.3の時点で、コード生成のためのコードが1000行くらい https://github.com/xuwei-k/nobox/blob/v0.1.3/project/Generate.scala 生成後のコードが、1万3千行と、結構大きくなった
    • コード生成のコード自体が大きくなって、大量の地味な文字列連結でだいぶ辛くなってきたけど、ほかにいい方法*3もないし、このままいくつもり
  • Array以外にも、primitive型それぞれに特化したListをつくって少しベンチマークとってみたら、2〜3倍程度しか速くならなくて、Arrayの場合ほど効果がないので、ひとまず辞めた
  • https://github.com/dragos/noboxing-plugin noboxing-pluginという、メンテされてない(?)コンパイラプラグインが存在するので、自分でforkなり、埋め込むなどして、導入して効果がありそうだったら試してみるかも
  • scalameter(パフォーマンス計測のためのライブラリ)を使ったベンチマークを追加したpull reqもらってmergeした https://github.com/xuwei-k/nobox/pull/2
    • scalameter自体の存在は知っていたが、ひとまずオレオレベンチマークでどうにかなってるし、この先どうするか(併用か、どちらか片方のみ使うか)
    • どちらにしろ、もっと詳細で正確なベンチマークとりたいし、オレオレベンチマークコードが現状あまり綺麗ではないので、どうにかしたい
    • scalameterの設計思想や、利点、できること、などをほとんど理解していないので、まずはそれを調べて理解してから・・・
  • scanRightとreveseMapが、ArrayOpsのそれよりも、それぞれ500倍、900倍速くなった*4 とても正しいツッコミを受けたので、一番下に貼り付けたtwitterのやりとりみてください
    • つまり「単にboxingが問題」なだけではなく、ArrayOpsのscanRightとreverseMapが、かなり上の方の親*5*6のデフォルト実装を使っており、アルゴリズム自体が適切でなく、Array向けに最適化されてない
    • 900倍まで顕著ではないが、20倍くらいの差がでるものもあるので、同じように、boxing以外のアルゴリズム面で最適化して速くなる可能性があるメソッドが他にもあるかもしれない
    • つまり、プリミティブに限らず、AnyRef用のArrayのラッパーをつくっても、ArrayOps.ofRefより速くなる可能性があるかもしれないので、branch分けて製作中
  • 思ったより飽きずに続いているが、暇だからできるのであって、やっぱりいつまでやる気が続くのかは怪しい
  • 実際に使うことよりも、Scalaコレクションライブラリを調べることになったり、「いつboxingやunboxinが発生するのか?の正確な理解」、「どうやれば正確なベンチマークとれるか?」といったことを考えて実践することが、一番勉強になってメリットになってる


*1:自分でさえ使ってないし、使う予定もいまのところない

*2:bintraryだと、誰でもユーザー登録してすぐに使い始められるので、sonatypeみたいに「issueをJIRAに手動で作ったり、メールしたり」 http://pab-tech.tumblr.com/post/23240310972/scala-maven-central という謎な手間は不要

*3:macroやtreehuggerという手もあるが、それらよりは余計なこと考える必要なくて、結果的にいいという判断。まぁtreehugger使うかどうかは、好みの問題な気がする。macroで現状やってることが全て可能なのかどうかは、そもそも分からない

*4:もちろん、大きいサイズの配列で、しかもプリミティブ?など、一定の条件はあるが

*5:Scalaのコレクションライブラリは巨大で、継承関係が入り乱れているので

*6:おそらくIndexSeqとかで一旦overrideするべきな気がする。せめてscanLeftと同じ性能がでるべき