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 件のコメント:

匿名 さんのコメント...

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

eller さんのコメント...

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

Shark++ さんのコメント...

マルチバイト文字列限定ですがこんな方法もあります。
#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を使用したほうが精度が高いことが多いですよ。

eller さんのコメント...

shark++さん、書き込みありがとうございます。

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

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

eller さんのコメント...

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)の指す内容がまだ理解できていません。

eller さんのコメント...

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

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

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