pattern match vs subscript マイロクベンチマーク

ある値が ~[ で始まっているかをテストしたい時に、 zsh では、

$string == '~['* vs $string[1,2] == '~[' どっちが速い…もとい、“軽い”のか?

後者の方がコードのテキストの量は多いものの実際にはどうなのか、というところ。パターンマッチと、文字列を array subscript して切り出して比較するのとを比較してみたいです。

以下、ここで試してみたコード。

# > zsh --version
# zsh 5.4.2 (x86_64-debian-linux-gnu)
string="~[test test]"
f () { [[ "$string" = '~['* ]] }
g () { [[ "$string" = \~\[* ]] }
h () { [[ "$string[1,2]" = '~[' ]] }
# okp () { "$1" && echo ok }
# okp f
# okp g
# okp h

perf () { repeat 65535 "$1" }

#perf "$1" ;#

# > valgrind zsh -f perfmatchsubscript.zsh f 2>&1 |grep 'total heap'
# ==767==   total heap usage: 460,135 allocs, 459,063 frees, 20,618,468 bytes allocated
# > valgrind zsh -f perfmatchsubscript.zsh g 2>&1 |grep 'total heap'
# ==792==   total heap usage: 460,135 allocs, 459,063 frees, 20,618,468 bytes allocated
# > valgrind zsh -f perfmatchsubscript.zsh h 2>&1 |grep 'total heap'
# ==810==   total heap usage: 591,206 allocs, 590,133 frees, 58,366,788 bytes allocated

#time (perf "$1") ;#

# > repeat 10 zsh -f perfmatchsubscript.zsh f
# ( perf "$1"; )  0.86s user 0.30s system 107% cpu 1.083 total
# ( perf "$1"; )  0.86s user 0.25s system 108% cpu 1.028 total
# ( perf "$1"; )  0.76s user 0.33s system 109% cpu 0.999 total
# ( perf "$1"; )  0.77s user 0.33s system 108% cpu 1.012 total
# ( perf "$1"; )  0.78s user 0.27s system 111% cpu 0.945 total
# ( perf "$1"; )  0.82s user 0.30s system 108% cpu 1.029 total
# ( perf "$1"; )  0.80s user 0.32s system 107% cpu 1.034 total
# ( perf "$1"; )  0.80s user 0.28s system 108% cpu 0.991 total
# ( perf "$1"; )  0.77s user 0.30s system 107% cpu 0.998 total
# ( perf "$1"; )  0.78s user 0.26s system 106% cpu 0.972 total
# > repeat 10 zsh -f perfmatchsubscript.zsh g
# ( perf "$1"; )  0.92s user 0.24s system 108% cpu 1.075 total
# ( perf "$1"; )  0.85s user 0.28s system 106% cpu 1.060 total
# ( perf "$1"; )  0.80s user 0.28s system 108% cpu 0.986 total
# ( perf "$1"; )  0.80s user 0.25s system 106% cpu 0.978 total
# ( perf "$1"; )  0.84s user 0.29s system 107% cpu 1.051 total
# ( perf "$1"; )  0.82s user 0.24s system 107% cpu 0.997 total
# ( perf "$1"; )  0.81s user 0.25s system 110% cpu 0.957 total
# ( perf "$1"; )  0.77s user 0.28s system 107% cpu 0.973 total
# ( perf "$1"; )  0.86s user 0.26s system 107% cpu 1.041 total
# ( perf "$1"; )  0.86s user 0.24s system 107% cpu 1.016 total
# > repeat 10 zsh -f perfmatchsubscript.zsh h
# ( perf "$1"; )  1.02s user 0.31s system 108% cpu 1.231 total
# ( perf "$1"; )  0.99s user 0.24s system 109% cpu 1.121 total
# ( perf "$1"; )  0.92s user 0.23s system 109% cpu 1.053 total
# ( perf "$1"; )  0.96s user 0.28s system 111% cpu 1.111 total
# ( perf "$1"; )  0.93s user 0.27s system 107% cpu 1.102 total
# ( perf "$1"; )  0.95s user 0.28s system 107% cpu 1.143 total
# ( perf "$1"; )  0.94s user 0.22s system 106% cpu 1.090 total
# ( perf "$1"; )  0.97s user 0.22s system 108% cpu 1.089 total
# ( perf "$1"; )  0.98s user 0.34s system 107% cpu 1.225 total
# ( perf "$1"; )  0.83s user 0.31s system 107% cpu 1.065 total

この場合、パターンマッチの方が、メモリアロケーションも少なくて済み、速度も速いという結果になりました。微妙な差だけれども。(それも、実際にはありえないような repeat 65535 … です、あしからずという。)

このコードは、ファイルの入力補完に使われるコードの中、多分一回は呼ばれるようになる箇所で使いたいと思っていて、両者の違いはそんなに問題にならないと思っています。