201711-arithmetic.sh (5690B)
1 #!/usr/bin/env bash 2 3 if [[ ! ${BLE_VERSION-} ]]; then 4 source ../../src/benchmark.sh 5 fi 6 7 #------------------------------------------------------------------------------ 8 # 1 条件コマンドと算術式コマンドのどちらが速いのか? 9 # 10 # →算術式コマンド (()) が最も速い。 11 # 条件コマンドが次に速い。 12 # 算術式コマンド let は遅い。 13 # 14 15 function measure1 { 16 wtype=1 atype=-1 17 function greater.w0 { [[ wtype -ge 0 ]]; } 18 function greater.w1 { ((wtype>=0)); } 19 function greater.w2 { let 'wtype>=0'; } 20 function greater.a0 { [[ atype -ge 0 ]]; } 21 function greater.a1 { ((atype>=0)); } 22 function greater.a2 { let 'atype>=0'; } 23 24 ble-measure 'greater.w0' # 19.20 usec/eval 25 ble-measure 'greater.w1' # 16.50 usec/eval 26 ble-measure 'greater.w2' # 20.80 usec/eval 27 ble-measure 'greater.a0' # 19.40 usec/eval 28 ble-measure 'greater.a1' # 16.70 usec/eval 29 ble-measure 'greater.a2' # 21.10 usec/eval 30 } 31 32 #------------------------------------------------------------------------------ 33 # 2 条件コマンド一個で済ませた方が速いのか、算術式コマンドと条件コマンドに分割した方が速いのか。 34 # 35 # →どちらとも言えない。最初の条件が満たされない時には、分割した方が速い。 36 # 両方が評価される時には単体の条件コマンドの方が微妙に速い。 37 # 38 39 function measure2 { 40 arr=(1 2 3) 41 wtype=1 atype=-1 42 function greater.w0 { [[ wtype -ge 0 && ${arr[wtype]} ]]; } 43 function greater.w1 { ((wtype>=0)) && [[ ${arr[wtype]} ]]; } 44 function greater.a0 { [[ atype -ge 0 && ${arr[atype]} ]]; } 45 function greater.a1 { ((atype>=0)) && [[ ${arr[atype]} ]]; } 46 47 ble-measure 'greater.w0' # 29.30 usec/eval 48 ble-measure 'greater.w1' # 30.20 usec/eval 49 ble-measure 'greater.a0' # 21.00 usec/eval 50 ble-measure 'greater.a1' # 19.20 usec/eval 51 } 52 53 #------------------------------------------------------------------------------ 54 # 3 実は代入は算術式の外でやった方が速かったりするのか? 55 # 56 # * 算術式の中でやった方が速い。 57 # これは実のところ bash の構文解析&評価が、 58 # 算術式の中と外でどちらの方が速いのかという競争である。 59 # 60 # * 流石に直接代入する場合には変数代入の方が速い。 61 # 62 63 function measure3 { 64 a=2 b=3 c=4 65 function assign.d1 { ((x=a*2+b*3-c*4)); } 66 function assign.d2 { x=$((a*2+b*3-c*4)); } 67 function assign.c1 { x=0; ((x+=a*2+b*3-c*4)); } 68 function assign.c2 { x=0; x=$((x+a*2+b*3-c*4)); } 69 70 ble-measure 'assign.d1' # 22.10 usec/eval 71 ble-measure 'assign.d2' # 23.20 usec/eval 72 ble-measure 'assign.c1' # 28.10 usec/eval 73 ble-measure 'assign.c2' # 29.40 usec/eval 74 75 function assign.a1 { ((x=a)); } 76 function assign.a2 { x=$a; } 77 function assign.a3 { x=$((a)); } # a に式が含まれている可能性がある時 78 ble-measure 'assign.a1' # 17.50 usec/eval 79 ble-measure 'assign.a2' # 16.20 usec/eval 80 ble-measure 'assign.a3' # 19.40 usec/eval 81 } 82 measure3 83 84 #------------------------------------------------------------------------------ 85 # 4 変数代入で配列要素を読み出すのと、再帰算術式で読み出すのでどちらが速いか? 86 # 87 # →再帰算術式で読み出すのが断然速い。 88 # 意外と直接呼び出すのと大した違いはないようだ。 89 # 90 91 function measure4 { 92 arr=(1 2 3) 93 ref='arr[1]' 94 function element.0 { ((arr[1]>=1)); } 95 function element.1 { ((ref>=1)); } 96 function element.2 { val=${arr[1]}; ((val>=1)); } 97 ble-measure 'element.0' # 19.80 usec/eval 98 ble-measure 'element.1' # 20.10 usec/eval 99 ble-measure 'element.2' # 29.50 usec/eval 100 } 101 #measure4 102 103 #------------------------------------------------------------------------------ 104 # 5 等値比較 105 # 106 # 整数値が標準形 ($value が $((value)) と同じになる) のとき、 107 # 意外なことに、算術式で比較した方が速い。 108 # 109 # 但し、2つの文字列の文字数比較では条件コマンドの方が微妙に速かった。 110 # 111 function measure5 { 112 value=3 113 function compare.1 { [[ $value == 3 ]]; } 114 function compare.2 { ((value==3)); } 115 ble-measure 'compare.1' # 17.40 usec/eval 116 ble-measure 'compare.2' # 16.80 usec/eval 117 118 lhs=3 rhs=3 119 function compare.a1 { [[ $lhs == "$rhs" ]]; } 120 function compare.a2 { ((lhs==rhs)); } 121 ble-measure 'compare.a1' # 20.10 usec/eval 122 ble-measure 'compare.a2' # 17.60 usec/eval 123 124 atext=1234 btext=4321 125 function compare.b1 { [[ ${#atext} == ${#btext} ]]; } 126 function compare.b2 { ((${#atext}==${#btext})); } 127 ble-measure 'compare.b1' # 27.60 usec/eval 128 ble-measure 'compare.b2' # 27.90 usec/eval 129 } 130 #measure5 131 132 #------------------------------------------------------------------------------ 133 # 6 条件つきの代入 134 # 135 # 条件が満たされるときは単一の算術式にまとめてしまった方が速い。 136 # また、もし分割するならば ((bar=c)) よりは bar=$c の方が速い。 137 # 条件が満たされないときは分割した方が良い。 138 # 139 140 function measure6 { 141 value=3 142 function cond-assign.a1 { c=4; ((c>value&&(bar=c))); } 143 function cond-assign.a2 { c=4; ((c>value)) && ((bar=c)); } 144 function cond-assign.a3 { c=4; ((c>value)) && bar=$c; } 145 function cond-assign.b1 { c=3; ((c>value&&(bar=c))); } 146 function cond-assign.b2 { c=3; ((c>value)) && ((bar=c)); } 147 function cond-assign.b3 { c=3; ((c>value)) && bar=$c; } 148 ble-measure 'cond-assign.a1' # 29.10 usec/eval 149 ble-measure 'cond-assign.a2' # 32.90 usec/eval 150 ble-measure 'cond-assign.a3' # 31.30 usec/eval 151 ble-measure 'cond-assign.b1' # 27.70 usec/eval 152 ble-measure 'cond-assign.b2' # 25.60 usec/eval 153 ble-measure 'cond-assign.b3' # 25.60 usec/eval 154 } 155 #measure6