2008年1月2日水曜日

lstrlenAとstrlenの速度比較

今回の条件ではlstrlenAよりもstrlenの方が高速な模様。

※別の書き方ではlstrlenAの方が速くなります。むしろそちらの書き方の方が普通と考えられます。m(_ _;)m
// lstrlenAとstrlenの速度比較

#uselib "kernel32.dll"
#cfunc lstrlenA "lstrlenA" sptr

#uselib "winmm.dll"
#cfunc timeGetTime "timeGetTime"

#const trial_times 1000

    font msgothic14
    repeat 31
        trial_strlen = cnt * cnt * cnt * 1000
        sdim trial_string, trial_strlen + 1
        memset trial_string, 'a', trial_strlen

        // lstrlenAの速度計測
        time(0) = timeGetTime()
        repeat trial_times
            tmp = strlen(trial_string)
        loop
        time(0) = timeGetTime() - time(0)

        // strlenの速度計測
        time(1) = timeGetTime()
        repeat trial_times
            tmp = lstrlenA(trial_string)
        loop
        time(1) = timeGetTime() - time(1)

        mes strf("文字列長(%dbytes)の場合:", trial_strlen)
        mes strf(" strlen  :%d[msec]", time(0))
        mes strf(" lstrlenA:%d[msec]", time(1))
        mes ""
    loop
    stop

6 件のコメント:

  1. #cfunc lstrlenA "lstrlenA" var
    にすると lstrlenA の方が早くなりました。
    こうすると、変数のメモリアドレスを渡すだけになるので速くなる...ということなのかも。

    返信削除
  2. 書き込みありがとうございます。手元の環境でもそうなりました。
    sptr(またはstr)の場合は、メモリに文字列をコピーした上でそのアドレスを渡しているのでしょうね。
    それならばコピーする作業分だけ遅くなると理解できます。

    返信削除
  3. マルチバイト文字列限定ですがこんな方法もあります。
    #module
    #uselib "ntdll.dll"
    #func memchr "memchr" var, int, int
    #defcfunc _strlen var _p1
    ; バッファサイズを取得[簡易版](ref:小ワザ/ポインタを使ってのあれこれ@HSP開発wiki)
    mref _hspctx, 68
    dupptr _vptr, _hspctx(207), 8, 4
    dupptr _pval, _vptr(0), 48, 4
    _aptr = _vptr(1)
    if _aptr {
    dupptr _pd, _pval(8)+_aptr*4, 4, 4
    dupptr _strinf, _pd-24, 24, 4
    } else {
    dupptr _strinf, _pval(7)-24, 24, 4
    }
    ; 文字列長を取得
    memchr _p1, 0, _strinf(2)
    return stat - varptr(_p1)
    #global
    あとtimeGetTimeを使用する場合は timeBeginPeriod/timeEndPeriodを使用したほうが精度が高いことが多いですよ。

    返信削除
  4. shark++さん、書き込みありがとうございます。

    memchrの意味は分かりましたが構造体のサイズが分からなかったため、_hspctx(207)や_pval(8)などが何のポインタなのかわからないため、もう少し調べてみます。
    構造体のサイズ取得方法(sizeof)も理解できましたし、いい勉強になりました。

    すべて理解できましたら、memchrおよびtimeBeginPeriod/timeEndPeriodを使用したスクリプトを載せたいと思います。

    返信削除
  5. VC++2005にてsizeof演算子を使用して調べた結果(中間報告):

    _hspctx(207)がprmstackのポインタ
    _vptrがprmstack
    _pvalが第1引数を表すPVAL構造体
    _aptr=_vptr(1)が第1引数の配列の要素(s(n)を_strlenに渡すと_aptrがnになる)
    _pval(7)がptr to array
    _pval(8)がMaster pointer for data

    _pval(8)+_aptr*4と_pd-24と_pval(7)-24を調べる内に時間切れになりました。
    おそらく1つめが調べる配列へのポインタ、残り2つが変数が確保しているメモリサイズだと思うのですが。
    _pval(7)&_pval(8)の指す内容がまだ理解できていません。

    返信削除
  6. 些細なことですが訂正。
    主にsizeof演算子ではなくポインタでした。

    HSPCTX ctx;
    printf("prmstackの位置 %d\n", (int)&ctx.prmstack - (int)&ctx);

    わからなかったところは開発wikiで補いました。
    明日あたり反映させます。

    返信削除