もりさんのプログラミング手帳

教えることは、二度学ぶこと

スポンサーリンク

【ExcelVBA】Integer型 VS Long型、速いのはどっち?【Vol.1】

『データ型によって消費メモリが異なるので、用途に合ったデータ型を指定しましょう』

『Variant型は無駄にメモリを食って実行速度が遅くなるので使用を控えましょう』

どちらも、ネットや書籍に多く記載されているVBAの基本ですね。

私自身も、
消費メモリの小さいデータ型を使う=マクロの実行速度が速い
と理解しています。

ところが、整数値について衝撃の事実発覚!

#ノンプロ研でお世話になっている高橋宣成さん(@ntakahashi0505)のコーディングガイドエクセルVBAコーディングガイドライン【随時更新】によると、

整数はLong型で統一で問題ありません。
(中略)
最近のバージョンでは、Integer型として宣言されていても、VBAはすべての整数値をLong型に変換します。したがって、Integer変数を使用することによるパフォーマンス上の利点はなくなりました。実際、Long変数はVBAで変換する必要がないため、少し速くなる可能性があります。

エェェェッ(((( ;゚Д゚)))ガクガクブルブル

これまで、変数の宣言やデータ型指定はこだわって、

・小さめの数字(カウンタ変数など)はInteger型を指定
・金額などを格納する変数はLong型を指定

と意図的に区別していたのに・・・

「百聞は一見に如かず」です。

Integer型 VS Long型
(おまけでVariant型も)比較してみましょう。

f:id:excel-accounting:20180503160940p:plain:w400

※環境
Office 2016
OS:Windows10 Home 64bit
CPU:Core i5
メモリ:4GB

整数値を扱うデータ型

データ型 表記 消費メモリ 格納できる値の範囲
バイト型 Byte 1バイト 0~255の整数
整数型 Integer 2バイト -32,768~32,767の整数
長整数型 Long 4バイト -2,147,483,648~2,147,483,647の整数

テスト

・変数をいくつか用意して適当な計算をさせ、無駄に時間を消費するマクロを作成。
・「Integer型」「Long型」「Variant型」で各10回ずつ実行し、処理時間の中央値を算出。
・WindowsAPI関数のtimeGetTimeを使用して、実行時間をミリ秒単位測定。

テスト用ソースコード

Option Explicit
Declare Function timeGetTime Lib "winmm.dll" () As Long

Sub ひたすら無駄な時間を稼ぐマクロ()

Dim cnt As Long

Do Until cnt = 10 '10回時間測定する

    Cells.ClearContents 'シート上の値を全クリア
    
    Dim StartTime As Long
    StartTime = timeGetTime '開始時刻
    
    Call 無駄な処理
    
    Dim EndTime As Long
    EndTime = timeGetTime '終了時刻
    
    Debug.Print (EndTime - StartTime) / 1000 & " 秒"
    
    cnt = cnt + 1
    DoEvents

Loop

End Sub
'*****************************************************************
Sub 無駄な処理()

'====ここのデータ型をテスト毎に書き換え======
Dim r As Long, c As Long
Dim i As Long
Dim tmp As Long, x As Long, y As Long, z As Long
'======================================

x = 1: y = 2: z = 3 '計算用なので意味はない

For c = 1 To 100
    For r = 1 To 10000
    
        '無駄に100回計算してみる
        For i = 1 To 100
            tmp = tmp + (r + r - r) + (c * c / c) + x + y + z - tmp
        Next i
        
        '計算結果をセルに書き出す
        Cells(r, c).Value = tmp
        
    Next r
Next c

End Sub

テスト結果

実行回数 Integer型 Long型 Variant型
1回目 43.288 秒 42.589 秒 109.656 秒
2回目 42.07 秒 42.396 秒 109.359 秒
3回目 43.799 秒 42.444 秒 108.435 秒
4回目 43.199 秒 41.404 秒 109.323 秒
5回目 42.563 秒 43.276 秒 109.014 秒
6回目 43.383 秒 41.604 秒 108.913 秒
7回目 42.173 秒 44.827 秒 108.439 秒
8回目 42.113 秒 41.574 秒 109.49 秒
9回目 44.626 秒 40.714 秒 109.26 秒
10回目 44.251 秒 42.081 秒 108.563 秒
中央値 43.2秒 42.2秒 109.1秒

僅差ではありますが、Long型の勝利です!

(誤差の範囲ではありますが)この結果から、「Integerを使うことのメリットはない」ので、
格納する数値の桁数によって使い分ける必要がなく「整数値はLong型で統一」といえますね。

Variant型をみてみると、これは到底誤差の範囲とは言えない大敗です。

「変数宣言だけして型は暗黙で」とか、
「よくわかんないからとりあえずVariantで」はいけないことが見て取れます。

(おまけ)
テスト用のソースコードは適当な変数と無駄な計算処理で負荷をかけたので、軽めの処理でVariant型のみ再度実行したところ、

Sub 無駄な処理2() '変数、計算少ない

Dim r As Variant, c As Variant

For c = 1 To 100
    For r = 1 To 10000
        Cells(r, c).Value = r
    Next r
Next c

End Sub

全10回の中央値は「36.9秒」と大幅短縮しました。

変数の数や計算処理が増えるほど不利になるようです。

まとめ

・VBAにおいて整数値はLong型で統一してよい。

・Variant型は変数の数や演算処理の複雑さに比例して実行速度が遅くなるので、慎重に使用すること。

(最後に)
Dim a, b, c As Long と書くと、変数b, cは型指定なし=Variant型になってしまいます。
(マクロが遅い原因、これかも!)

Dim a As Long, b As Long, c As Long  と、一つずつ指定しましょうね♪

【2018/4/6更新】Vol.2公開しました。こちらもご覧ください!
www.excel-prog.com

スポンサーリンク