FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

ScalaのTry型での例外処理コスト

こんにちは、広幡です。

最近Scalaのコードを見ていると、Try(throw new Exception)していたり、Failure(new Exception)していたりと、
人によってバラバラなので揃えたいなーと感じています。

そこで、どっちを扱うほうがいいのか気になったので少し調べてみました。

実行環境

会社支給のMacBook Proで行いました。

OS OS X 10.9.5
CPU 2.3 GHz Intel Core i7
Memory 16 GB 1600 MHz DDR3
Java Java8

この調査にあたり、sbt-jmhというツールを使っています。 github.com

これについては弊社の記事で書いてありますので、そちらをご参照ください。 labs.septeni.co.jp

結果

いきなりですが、以下が調査結果です。
ソースコードは最後の方に記載しています。

Scoreは単位時間あたりの実行回数が表示されているので、数字が大きいほうが良いです。
ただError(誤差の範囲)が大きいのはご愛嬌。

Benchmark                        Mode  Cnt          Score         Error  Units
ExceptionCost.Success型          thrpt   30  143024047.847 ± 3022678.257  ops/s
ExceptionCost.Failure型          thrpt   30     914107.851 ±   21209.436  ops/s
ExceptionCost.Try型の中でthrow    thrpt   30     832233.753 ±   16570.238  ops/s
ExceptionCost.例外を握りつぶす      thrpt   30     814094.755 ±   14750.842  ops/s

これを見る限り、Success型のやつは高得点を叩きだしてますね。
Failure型パターンとTry型の中でthrowパターンを比べると、Failure型の方が高い得点を出していることがわかります。
もちろん例外を握りつぶすパターンは一番得点が低いですね。

知ってました。このような結果になるのは分かってました。
やはりTryの中でthrowせず、出来る限りFailureで例外を定義したほうがいいという確証が得られました。

まとめ

Try(throw new Exception)ではなくFailure(new Exception)を使え

検証コード

import org.openjdk.jmh.annotations.Benchmark

import scala.util.{Try, Failure, Success}

class ExceptionCost {

  @Benchmark
  def Success型: Try[Object] = {
    Success(new Object)
  }

  @Benchmark
  def Failure型: Try[Object] = {
    Failure(new Exception)
  }

  @Benchmark
  def Try型の中でthrow: Try[Object] = {
    Try(throw new Exception)
  }

  @Benchmark
  def 例外を握りつぶす: Try[Object] = {
    Try(throw new Exception).recover {
      case e: Throwable => Success(new Object)
    }
  }

}