型によって速度に違いがある

プログラミング言語でたまに話題になるのが「数値型はこの型が一番速いのでこれを使いましょう」という話です。VBAについても同じように型によって処理速度に違いが出ます。

そこで数値型のInteger型、Long型、Single型、Double型、Currency型、LongLong型(64bit版のみ)の6つを比較してみます。Byte型やBoolean型も数値型ではありますが、用途が違うので除外します。

32bit環境(2010年度仕様程度:Windows7 + Core i3 + Office2010)と64bit環境(2020年度仕様程度:Windows10 + Ryzen9 3900X + Office365)のそれぞれで計測しました。

先に答えを書いてしまうと、環境によって速い順が異なりました。32bit環境(Windows7 + Core i3 +Office2010)では速かった順でInteger、Long、Currency、Double、Singleでした。64bit環境(Windows10 + Ryzen9 3900X+Office365)ではDouble、Single、Long、Integer、LongLong、Currencyでした。

ただ、いずれの場合も速度の違いは微々たるものでした。64bit環境に至ってはほとんど差がありませんでした。

比較用コード

以下のコードで処理の開始と終了をマイクロ秒で取得して、開始と終了の差から処理時間を計測します。

処理自体は100000回×10000回、つまり10億回のループで足し算を行うプログラムです。

実行する際に2行目から6行目で計測対象の数値型のみコメントをはずして実行します。

比較には「VBAでミリ秒やマイクロ秒の計測を行う」で紹介しているマイクロ秒計測関数「GetMicroSecond」を利用しています。

 

比較結果

結果は以下の通り、環境によって変わりました。

32bit環境での結果

順位 数値型 平均速度 1位と速度差率
1位 Integer 12.4480567194987 100.00%
2位 Long 12.4500986955128 100.02%
3位 Currency 15.1783854221925 121.93%
4位 Double 18.5107456908387 148.70%
5位 Single 18.7996578843275 151.02%

32bit環境(Windows7 + Core i3 + Office2010)では、Integer、Long、Currency、Double、Single、の順に速かったです。

IntegerとLongは0.02%しか違いがなく、ほとんど速度差はありませんでした。

意外だったのはCurrency型が結構速かったことです。Currency型は15桁の整数と4桁の小数を保持できます。扱う数値が整数15桁+小数4桁のCurrency型の範囲に入ることが分かっている場合は、Double型よりもCurrency型を利用した方が処理速度向上が見込めます。

SingleとDoubleでは、一般的には単精度(Single)と倍精度(Double)では単精度(Single)の方が速いと言われます。VBAの実装は分からないのですが、言語やインタプリターやコンパイラーによっては単精度は一度倍精度に変換して単精度に戻すようなものもあるため、そういう場合は倍精度(Double)の方が速かったりします。なので、SingleとDoubleでDoubleが速かったのは私の環境だけかも、という点を補足しておきます。

64bit環境での結果

順位 数値型 平均速度 1位と速度差率
1位 Double 6.53384666005150 100.00%
2位 Single 6.62837783996947 101.45%
3位 Long 6.68528776005842 102.32%
4位 Integer 6.75233754003420 103.34%
5位 LongLong 7.15234209997579 109.47%
6位 Currency 7.18892749999650 110.03%

64bitOS(Windows10 + Ryzen 9 3900X + Office365)では、Double、Single、Long、Interger、LongLong、Currency、の順に速かったです。

ただ、10億回で1位のDoubleの6.5秒と6位のCurrencyの7.18秒なので、数値型の速度を気にすること自体がほとんど意味をなさなくなっています。計測に使ったRyzen9 3900Xは12コア、24スレッドというかなり高速なCPUですが、それでも2020年以降のCPUは複数コア、複数スレッドが当たり前になりもう数値型での速度差がほとんど分からないぐらい高速になっているということです。

 

10億回のループでこの程度の差なので気にしなくてよい

上のテストコードは10億回ものループ処理を行っています。ここまでのループを行う処理は実際のVBAの処理ではなかなか無いと思います。VBAにそこまでの高速性を求めるようなことはほとんどないでしょう。

10億回で32bit環境が12秒から19秒の範囲、64bit環境が6.5秒から7.2秒の範囲ですから、差は微々たるものでしかありません。ここでは単純な足し算しかやっていませんが他の処理が増えれば一気に処理時間は増えることになります。

その上での差ですので、PCの処理速度がどんどん向上している現在では、もはや型での速度の違いを言ってもほとんど意味を成さなくなっているのが現実です。上の32bit環境ではそこそこの差がありますが、64bit環境は1位のDoubleと6位のCurrencyの差は、10億回演算しても1秒も差がありません。

IntegerとLongの比較で、「Long型の方が速い。なのでLong型一択で大丈夫。」みたいなことを書いてあるサイトが結構あるのですが、VBAのバージョンによって実装が違いあったり、PC環境や演算の仕方によって、上の結果の通り32bit環境ではInteger型が速いこともあれば、64bit環境ではLong型が速いこともあります。そしてこれが重要ですが、ほとんど差がありません。

確かにオーバーフローの予防を考えるのであればIntegerと比べればLongを使った方がいいと思いますが、それはあくまでもInteger型と比較すればという話であってLong型でもオーバーフローは発生しますし、Integer型で回避できなかったものがLong型だからといって必ず回避できるというわけでもありません。

そのため、Integer型やLong型の用途を無視して無条件に「Long型でOK」と言いきってしまうのはあまりにも速度偏重が強く、個人的には好みません。

むしろ、型の違いによる速度低下を気にするよりも、コーディングルールを適切に守りコードの品質を保つように努めた方がいいと思います。

比較結果詳細

細かいデータは特にいらないとは思いますが、上のコードを数値型ごとに5回ずつ実行した結果が以下になります。

そこまでばらつきも無い様子なので回数を増やしても変わらないと思い、5回ずつにしています。

32bit環境

数値型 回数 計測結果 平均
Integer 1回目 12.4729496697546 12.4480567194987
2回目 12.4415238746442
3回目 12.4542038372310
4回目 12.4340643484320
5回目 12.4375418674317
Long 1回目 12.4478783314989 12.4500986955128
2回目 12.4387873804080
3回目 12.4419057826744
4回目 12.4624607504811
5回目 12.4594612325018
Single 1回目 18.7943262018380 18.7996578843275
2回目 18.8006258363894
3回目 18.8132765399059
4回目 18.8008454335213
5回目 18.7892154099827
Double 1回目 18.5085296386969 18.5107456908387
2回目 18.5132394270913
3回目 18.4997657733329
4回目 18.5088228454988
5回目 18.5233707695734
Currency 1回目 15.1820697259391 15.1783854221925
2回目 15.1716516444285
3回目 15.1673936778679
4回目 15.1990255185228
5回目 15.1717865442042

64bit環境

数値型 回数 計測結果 平均
Double 1回目 6.59408730012365 6.53384666005150
2回目 6.56563029997051
3回目 6.51702979998663
4回目 6.49236790020950
5回目 6.50011799996719
Single 1回目 6.49714199989103 6.62837783996947
2回目 6.66059960005805
3回目 6.66253690002486
4回目 6.66429349989630
5回目 6.65731719997711
Long 1回目 6.74913280014880 6.68528776005842
2回目 6.69596919999458
3回目 6.66865999996662
4回目 6.65295680006966
5回目 6.65972000011243
Integer 1回目 6.76376889995299 6.75233754003420
2回目 6.78791770013049
3回目 6.76623210008256
4回目 6.73979989998043
5回目 6.70396910002455
LongLong 1回目 7.14884630008601 7.15234209997579
2回目 7.14873969997279
3回目 7.13808579999022
4回目 7.15316769992933
5回目 7.17287099990062
Currency 1回目 7.13816550001502 7.18892749999650
2回目 7.20302979997359
3回目 7.19893419998698
4回目 7.20264680008404
5回目 7.20186119992286