2008/08/26

データ変換速度比較

VB.NET/.NetFramwork2で型変換の速度差、特色について気になりだしたので、実験してみました。

興味があった変換は、普段よく使う

  • Object→Int32への変換
  • String→Int32への変換

です。

実験したものはCtype、CInt、DirectCast、Convert.ToInt32、Int32.Parse、 Int32.TryParse。

実験結果としてはこんな感じです。【 】の中の数値はObjectなりStringなりのmyData変数を、それぞれのメソッドなりでの変換したものです。Int32.TryParseで【 0】となっているのは、変換できなかったということですね。

実験結果

(速度の早い順に並び替え)
  1. Dim my_Data As Object = 12345  
  2. DirectCast :        【     12345】00:00:00.0004363  
  3. CInt :              【     12345】00:00:00.0023329 'CtypeとCInt、Convert.ToInt32は順位が入れ替わるときがあります。  
  4. CType :             【     12345】00:00:00.0023815  
  5. Convert.ToInt32 :   【     12345】00:00:00.0030900  
  6. Int32.Parse :       【     12345】00:00:00.0468925 'Int32.ParseとInt32.TryParseは順位が入れ替わるときがあります。  
  7. Int32.TryParse :    【     12345】00:00:00.0475714  
  8.   
  9.   
  10. Dim my_Data As Object = 12345.5  
  11. CInt :              【     12346】00:00:00.0039555  
  12. CType :             【     12346】00:00:00.0040038  
  13. Convert.ToInt32 :   【     12346】00:00:00.0052587  
  14. Int32.TryParse :    【         0】00:00:00.0631435  
  15.   
  16.   
  17. Dim my_Data As String = "12345"  
  18. Int32.Parse :       【     12345】00:00:00.0198393  
  19. Int32.TryParse :    【     12345】00:00:00.0206115  
  20. Convert.ToInt32 :   【     12345】00:00:00.0214960  
  21. CType :             【     12345】00:00:01.7970309  
  22. CInt :              【     12345】00:00:01.7990923  
  23.   
  24.   
  25. Dim my_Data As String = "12345.5"  
  26. Int32.TryParse :    【         0】00:00:00.0198050  
  27. CInt :              【     12346】00:00:01.8433437  
  28. CType :             【     12346】00:00:01.8474300  

所感としては、Object型のときは、DirectCastを使うのが一番高速(但しDirectCastは丸め処理などは行わず、Int32に変換するのに小数などを引数に渡すとエラーを吐きます)。String型のときは、Int32.Parseが一番高速…、というところでしょうかね。現実問題としてはInt32.TryParseも、使い勝手がよさそうです。

サンプルソース

▲TextBox1に結果が出るわけです…。

※Int32.Parseの引数はもともとString型なので、Option StrictはOffにしないと走りません。

  1. Imports System.Diagnostics  
  2.   
  3.   
  4. Public Class Form1  
  5.     Private Sub Button1_Click(ByVal sender As Object, _  
  6.                               ByVal e As System.EventArgs) _  
  7.                               Handles Button1.Click  
  8.   
  9.         Dim sw As New Stopwatch  
  10.         Dim sb_Data As New System.Text.StringBuilder  
  11.         Dim bl_result As Boolean  
  12.         Dim my_Dict As New Dictionary(Of StringString)  
  13.   
  14.   
  15.         Dim my_Data As Object = 12345  '#---ここをあれこれ差し替えました。  
  16.         '                                   少数の値をセットしたりして  
  17.         '                                   エラーができるときは、  
  18.         '                                   型変換部分も  
  19.         '                                   コメントアウトします。  
  20.         Dim int_Data As Int32  
  21.   
  22.         '----------------------------------  
  23.         sw.Reset()  
  24.         sw.Start()  
  25.         For i As Int32 = 0 To 100000  
  26.             int_Data = CType(my_Data, Int32)  
  27.         Next  
  28.         sw.Stop()  
  29.         my_Dict.Add("CType" & vbTab _  
  30.                     & int_Data.ToString, _  
  31.                     sw.Elapsed.ToString)  
  32.         '----------------------------------  
  33.         sw.Reset()  
  34.         sw.Start()  
  35.         For i As Int32 = 0 To 100000  
  36.             int_Data = CInt(my_Data)  
  37.         Next  
  38.         sw.Stop()  
  39.         my_Dict.Add("CInt" & vbTab _  
  40.                     & int_Data.ToString, _  
  41.                     sw.Elapsed.ToString)  
  42.         '----------------------------------  
  43.         sw.Reset()  
  44.         sw.Start()  
  45.         For i As Int32 = 0 To 100000  
  46.             int_Data = DirectCast(my_Data, Int32)  
  47.         Next  
  48.         sw.Stop()  
  49.         my_Dict.Add("DirectCast" & vbTab _  
  50.                     & int_Data.ToString, _  
  51.                     sw.Elapsed.ToString)  
  52.         '----------------------------------  
  53.         sw.Reset()  
  54.         sw.Start()  
  55.         For i As Int32 = 0 To 100000  
  56.             int_Data = Convert.ToInt32(my_Data)  
  57.         Next  
  58.         sw.Stop()  
  59.         my_Dict.Add("Convert.ToInt32" & vbTab _  
  60.                     & int_Data.ToString, _  
  61.                     sw.Elapsed.ToString)  
  62.         '----------------------------------  
  63.         sw.Reset()  
  64.         sw.Start()  
  65.         For i As Int32 = 0 To 100000  
  66.             int_Data = Int32.Parse(my_Data)  
  67.         Next  
  68.         sw.Stop()  
  69.         my_Dict.Add("Int32.Parse" & vbTab _  
  70.                     & int_Data.ToString, _  
  71.                     sw.Elapsed.ToString)  
  72.         '----------------------------------  
  73.         sw.Reset()  
  74.         sw.Start()  
  75.         For i As Int32 = 0 To 100000  
  76.             bl_result = Int32.TryParse(my_Data, _  
  77.                                        int_Data)  
  78.         Next  
  79.         sw.Stop()  
  80.         my_Dict.Add("Int32.TryParse" & vbTab _  
  81.                     & int_Data.ToString, _  
  82.                     sw.Elapsed.ToString)  
  83.         '----------------------------------  
  84.   
  85.         Dim sorted As List(Of KeyValuePair(Of StringString)) _  
  86.                 = sortByValue(my_Dict)  
  87.   
  88.         sorted.Reverse()  
  89.   
  90.         For Each kvp As KeyValuePair(Of StringStringIn sorted  
  91.   
  92.             Dim str_SPL() As String _  
  93.                 = kvp.Key.Split(vbTab.ToCharArray)  
  94.             Dim str_Num As String _  
  95.             = Strings.StrDup(10, " ") & str_SPL(1)  
  96.   
  97.             sb_Data.Append((str_SPL(0) & " :" _  
  98.               & Strings.StrDup(20, " ")).Substring(0, 20) _  
  99.               & "【" & (str_Num).Substring(str_Num.Length - 10, 10) & "】" _  
  100.               & kvp.Value & vbCrLf)  
  101.   
  102.         Next  
  103.   
  104.         Me.TextBox1.Text = sb_Data.ToString  
  105.         sb_Data.Remove(0, sb_Data.Length)  
  106.         sb_Data = Nothing  
  107.   
  108.     End Sub  
  109.   
  110.   
  111.     Shared Function hikaku(Of TKey, TValue As IComparable(Of TValue))( _  
  112.       ByVal kvp1 As KeyValuePair(Of TKey, TValue), _  
  113.       ByVal kvp2 As KeyValuePair(Of TKey, TValue)) As Integer  
  114.   
  115.         Return kvp2.Value.CompareTo(kvp1.Value)  
  116.     End Function  
  117.   
  118.   
  119.     Shared Function sortByValue(Of TKey, TValue As IComparable(Of TValue))( _  
  120.       ByVal dict As Dictionary(Of TKey, TValue)) _  
  121.       As List(Of KeyValuePair(Of TKey, TValue))  
  122.   
  123.         Dim list As New List(Of KeyValuePair(Of TKey, TValue))(dict)  
  124.   
  125.         'Valueの大きい順にソート  
  126.         list.Sort(AddressOf hikaku)  
  127.         Return list  
  128.     End Function  
  129. End Class  

0 件のコメント: