Runner in the High

技術のことをかくこころみ

Elmにおける比較処理の高速化テクニック

ここで触れられてた話がおもしろいかったのでざっくり紹介

discourse.elm-lang.org

文字列比較はcase文のほうが早い(ことがある)

これは遅い

ensureNonBreakingSpace : Char -> Char
ensureNonBreakingSpace char =
    if char == ' ' then
        nonBreakingSpace
    else
        char

これは速い

ensureNonBreakingSpace : Char -> Char
ensureNonBreakingSpace char =
    case char of
        ' ' ->
            nonBreakingSpace
        _ ->
            char

理由は以下の通り

Currently, a comparison with a character literal isn’t optimized in the same way an integer literal is. By using an elm case expression, we make the compiler generate a javascript case statement. These again are much faster because there is no function call involved.

今のElmコンパイラ(おそらく0.19)では文字リテラルの比較が最適化されていないため、こういう結果になる。

余談ではあるがElmコンパイラは比較の際にどちらかがリテラルではない場合にパフォーマンス劣化を起こす。なぜなら、ElmにおいてJSの等価演算子はオペレータで比較される2値のどちらかがリテラルでなければ生成されないからだ。

リテラル同士の比較は内部的にはJSの等価演算子だけではなくElmランタイムの比較処理を呼び出すため、その分のオーバーヘッドが発生することになる。したがって、数値の比較であっても x == y よりは (x - y) == 0 のほうがパフォーマンスには優れているとのこと。

これ以外にもcase文でMaybeやResultをパターンマッチするほうがパイプで関数をチェーンするよりも速い、レコード更新のシンタクス({ a | field = value } みたいなやつ)を使うよりも新しいレコードを生成するほうが速い、などの話が elm-physics の作者から出ているが、ベンチマークがあるわけではないので真偽は不明。