AddStringの速度比較          <TOP>


コンボボックス、リストボックスにAddStringする速度を比較テストします。

LockWindowUpdate 再描画しようとするウィンドウをロックする

timeGetTime システムが起動してからの起動時間を取得

timeBeginPeriod アプリケーションまたはデバイスドライバの最小タイマ分解能を設定

SendMessage ウィンドウにメッセージを送信

 

F-BasicでのAddStringと、SendNessageでCB_ADDSTRING(LB_ADDSTRING)を送った場合の速度をを比較してみます。

例では、5000までの数値を(昇順・降順は関係ありません)AddStringしています。
それぞれ、リスト表示しながら読み込んだ場合、リスト非表示で読み込み込んだ場合、読み込み完了まで再描画を停止した場合の時間を計測します。

ComboBox

    F-Basicの場合

   

    SendNessageでCB_ADDSTRINGを送った場合

   

ListBox(リストボックスを非表示した状態・・画面体裁上List1にAddStringしている間、List2「ダミー」を表示させています。)

    F-Basicの場合

   
    SendNessageで
LB_ADDSTRINGを送った場合

   


timeGetTime
この関数と timeGetSystemTime関数との唯一の違いは、timeGetSystemTime関数では、システム時刻を返すのにMMTIME構造体を使う点です。timeGetTime関数では、timeGetSystemTime関数よりもオーバーヘッドが少なくて済みます。
timeGetTime関数で返される値は DWORD 値であることに注意してください。戻り値は0 ミリ秒から 2^32 ミリ秒の間を循環します。2^32 ミリ秒は約 49.71 日にあたります。
計算にtimeGetTime関数の戻り値を直接使うようなコードでは、特にコードの実行を制御する場合などに、問題が発生する可能性があります。計算では常に、2つの timeGetTime関数の戻り値の差を使います。Windows NT:timeGetTime関数の既定の精度は、マシンによっては5 ミリ秒以上になる場合があります。timeGetTime関数の精度は、timeBeginPeriod関数とtimeEndPeriod関数を使って上げることができます。こうすると、2 つの連続したtimeGetTime関数の戻り値の差の最小値は、timeBeginPeriod関数と timeEndPeriod関数を使って設定された間隔の最小値と同じになります。高い分解能で短い時間間隔を測定するには、QueryPerformanceCounter関数とQueryPerformanceFrequency関数を使います。Windows 95:timeGetTime関数の既定の精度は1 ミリ秒です。
つまり、timeGetTime関数は、1 ミリ秒しか違わない連続値を返すことができます。timeBeginPeriod関数とtimeEndPeriod関数に対して行われた呼び出しがどのような性質のものであっても、これは変わりません。
<SDKより抜粋>

 

'================================================================
'= AddString速度比較
'================================================================
#include "Windows.bi"

' 再描画しようとするウィンドウをロックする
Declare Function Api_LockWindowUpdate& Lib "user32" Alias "LockWindowUpdate" (ByVal hwndLock&)

' システムが起動してからの起動時間を取得
Declare Function Api_timeGetTime& Lib "winmm" Alias "timeGetTime" ()

' アプリケーションまたはデバイスドライバの最小タイマ分解能を設定
Declare Function Api_timeBeginPeriod& Lib "winmm" Alias "timeBeginPeriod" (ByVal uPeriod&)

' 以前にセットされた最小タイマ分解能をクリア
Declare Function Api_timeEndPeriod& Lib "winmm" Alias "timeEndPeriod" (ByVal uPeriod&)

' ウィンドウにメッセージを送信。この関数は、指定したウィンドウのウィンドウプロシージャが処理を終了するまで制御を返さない
Declare Function Api_SendMessage& Lib "user32" Alias "SendMessageA" (ByVal hWnd&, ByVal wMsg&, ByVal wParam&, lParam As Any)

#define CB_SHOWDROPDOWN &H14F           'コンボボックスのリストボックスの表示または非表示を切り替える
#define CB_ADDSTRING &H143              'コンボボックスのリストボックスに文字列を追加する
#define LB_ADDSTRING &H180              'リストボックスに文字列を追加する

Var Shared Combo1 As Object
Var Shared Text1 As Object
Var Shared List(1) As Object
Var Shared Check(1) As Object
Var Shared Radio(1) As Object

Combo1.Attach GetDlgItem("Combo1") : Combo1.SetFontSize 14
Text1.Attach GetDlgItem("Text1") : Text1.SetFontSize 14

For i = 0 To 1
    List(i).Attach GetDlgItem("List" & Trim$(Str$(i + 1)))
    Check(i).Attach GetDlgItem("Check" & Trim$(Str$(i + 1)))
    Radio(i).Attach GetDlgItem("Radio" & Trim$(Str$(i + 1)))

    List(i).SetFontSize 14
    Check(i).SetFontSize 14
    Radio(i).SetFontSize 14
Next

'================================================================
'=
'================================================================
Declare Function Index bdecl () As Integer
Function Index()
    Index = Val(Mid$(GetDlgRadioSelect("Radio1"), 6)) -1
End Function

'================================================================
'= F-BASIC による項目書き込み
'================================================================
Declare Sub Button1_on edecl ()
Sub Button1_on()
    Var Item As String
    Var i As Integer
    Var nStart As Long
    Var nEnd As Long
    Var Ret As Long
  
    Combo1.ResetContent
    List(0).ResetContent
    Text1.SetWindowText ""

    If Check(0).GetCheck = 1 Then
        'ComboBox・ListBox非表示
        List(1).ShowWindow -1 : List(0).ShowWindow 0
    Else If Index = 0 Then
        Ret = Api_SendMessage(Combo1.GethWnd, CB_SHOWDROPDOWN, 1, ByVal 0)
    End If            

    Ret = Api_timeBeginPeriod(1)
    nStart = Api_timeGetTime()

    'コンボボックス
    If Index = 0 Then
        If Check(1).GetCheck = 1 Then Ret = Api_LockWindowUpdate(Combo1.GethWnd)
 
        For i = 5000 To 1 step -1
            Item = Str$(i)
            Combo1.AddString Item
        Next

    'リストボックス
    Else
        '再描画を停止
        If Check(1).GetCheck = 1 Then Ret = Api_LockWindowUpdate(List(0).GethWnd)

        For i = 5000 To 1 step -1
            Item = Str$(i)
            List(0).AddString Item
        Next
    End If

    '再描画を解放
    Ret = Api_LockWindowUpdate(0)

    nEnd = Api_timeGetTime()
    Ret = Api_timeEndPeriod(1)

    List(1).ShowWindow 0
    List(0).ShowWindow -1

    Text1.SetWindowtext Str$((Cdbl(nEnd) - Cdbl(nStart)) / 1000) & " 秒"
End Sub

'================================================================
'= Win32 API による項目書き込み
'================================================================
Declare Sub Button2_on edecl ()
Sub Button2_on()
    Var Item As String
    Var i As Integer
    Var nStart As Long
    Var nEnd As Long
    Var Ret As Long
    
    Combo1.ResetContent
    List(0).ResetContent
    Text1.SetWindowText ""

    If Check(0).GetCheck = 1 Then
        'ComboBox・ListBox非表示
        List(1).ShowWindow -1 : List(0).ShowWindow 0
    Else If Index = 0 Then
        'ComboBoxプルダウン表示        
        Ret = Api_SendMessage(Combo1.GethWnd, CB_SHOWDROPDOWN, 1, ByVal 0)
    End If            

    Ret = Api_timeBeginPeriod(1)
    nStart = Api_timeGetTime()

    'コンボボックス
    If Index = 0 Then
        If Check(1).GetCheck = 1 Then Ret = Api_LockWindowUpdate(Combo1.GethWnd)
        For i = 5000 To 1 step -1
            Item = Str$(i)
            Ret = Api_SendMessage(Combo1.GethWnd, CB_ADDSTRING, 0, Item)
        Next
        Ret = Api_SendMessage(Combo1.GethWnd, CB_SHOWDROPDOWN, 1, ByVal 0)

    'リストボックス
    Else
        '再描画を停止
        If Check(1).GetCheck = 1 Then Ret = Api_LockWindowUpdate(List(0).GethWnd)
        For i = 5000 To 1 step -1
            Item = Str$(i)
            Ret = Api_SendMessage(List(0).GethWnd, LB_ADDSTRING, 0, Item)
        Next
    End If

    '再描画解放
    Ret = Api_LockWindowUpdate(0)

    nEnd = Api_timeGetTime()
    Ret = Api_timeEndPeriod(1)

    List(1).ShowWindow 0
    List(0).ShowWindow -1

    Text1.SetWindowtext Str$((Cdbl(nEnd) - Cdbl(nStart)) / 1000) & " 秒"
End Sub

'================================================================
'=
'================================================================
While 1
    WaitEvent
Wend
Stop
End