元ネタはこちら。
C#の記事なので、これをVB.NETのコードに変えると空の配列は
'A Dim ary = DirectCast(Enumerable.Empty(Of Integer)(), Integer())
このように書くことでメモリが無駄に使われないとのこと。 ちなみに私は
'B Dim ary = DirectCast({}, IEnumerable(Of Integer))
こう書いてました。*1
で元記事のコメントにて、速度やメモリ使用量について議論があったようなので、調べてみます。
3億ループ時の比較
ロジック | 速度(msec) | メモリ使用量(MB) |
---|---|---|
A | 18,000 | 0.008 |
B | 6,793 | 1.273 |
メモリは記事の通り、Aが圧倒的に少ないことは確認できます。*2しかし、コメントにあるとおりAが遅い。
Aのコードが遅い理由
個人的にはわざわざInteger()
でなければいけないケースはなさそうだし、IEnumerable(Of Integer)
のままでいいから、
'C Enumerable.Empty(Of Integer)()
に変えて計測してみたら、
ロジック | 速度(msec) | メモリ使用量(MB) |
---|---|---|
A | 18,000 | 0.008 |
B | 6,793 | 1.273 |
C | 6,134 | 0.008 |
になりました。つまり、型変換に時間かかってただけという…
以下、速度計測に使用したコード。検証用なので汚いです。
Sub Main() Dim cnt = 300000000 Dim sw As New Stopwatch Dim before = System.GC.GetTotalMemory(True) sw.Start() For i As Integer = 1 To cnt Dim ary = New Integer(-1) {} Next sw.Stop() Console.WriteLine("Dim ary = New Integer(-1) {}") Console.WriteLine(String.Format("{0:n0}ms", sw.ElapsedMilliseconds)) Console.WriteLine(String.Format("{0:n3}MB used", (System.GC.GetTotalMemory(False) - before) / 1024 / 1024)) sw.Reset() before = System.GC.GetTotalMemory(True) sw.Start() For i As Integer = 1 To cnt Dim ary = DirectCast({}, IEnumerable(Of Integer)) Next sw.Stop() Console.WriteLine("Dim ary = DirectCast({}, IEnumerable(Of Integer))") Console.WriteLine(String.Format("{0:n0}ms", sw.ElapsedMilliseconds)) Console.WriteLine(String.Format("{0:n3}MB used", (System.GC.GetTotalMemory(False) - before) / 1024 / 1024)) sw.Reset() before = System.GC.GetTotalMemory(True) sw.Start() For i As Integer = 1 To cnt Dim ary = DirectCast(Enumerable.Empty(Of Integer)(), Integer()) Next sw.Stop() Console.WriteLine("Dim ary = DirectCast(Enumerable.Empty(Of Integer)(), Integer())") Console.WriteLine(String.Format("{0:n0}ms", sw.ElapsedMilliseconds)) Console.WriteLine(String.Format("{0:n3}MB used", (System.GC.GetTotalMemory(False) - before) / 1024 / 1024)) sw.Reset() before = System.GC.GetTotalMemory(True) sw.Start() For i As Integer = 1 To cnt Dim ary = Enumerable.Empty(Of Integer)() Next sw.Stop() Console.WriteLine("Dim ary = Enumerable.Empty(Of Integer)()") Console.WriteLine(String.Format("{0:n0}ms", sw.ElapsedMilliseconds)) Console.WriteLine(String.Format("{0:n3}MB used", (System.GC.GetTotalMemory(False) - before) / 1024 / 1024)) Console.WriteLine("end.") Console.ReadKey() End Sub