2007年12月16日日曜日

高速な文字列の結合(連結)

pokeとmemexpandを利用した文字列の結合(連結)。
HSP標準の+=やnoteaddよりも高速に実行することができます。

このモジュール最大の利点は、memexpandによる変数の自動拡張にあります。(X)HTMLコンバータのように出力結果の大きさが分からないスクリプトで重宝するでしょう。
サンプルスクリプトのように決まった文字列を結合(連結)し続ける場合(リフレイン)、この命令よりもFujiさんのブログの記事で紹介されている方法の方がより高速です。

先日の(X)HTML変換スクリプトの他、開発wikiの置換モジュールでも似たような処理が使われています。

#module
#const EXPAND_SIZE 1024
// 文字列の初期値を設定する
#deffunc set_string str str_to_set
    string_length = strlen(str_to_set)
;   string_size = EXPAND_SIZE * (1 + string_length / EXPAND_SIZE)
    string_size = 64            // 測定のために公平化
    sdim string, string_size
    poke string, 0, str_to_set
    return

// 文字列を返す
#deffunc get_string var target
    target = string
    return

// 文字列の長さを返す
#defcfunc get_string_length
    return string_length

// 文字列を連結する
#deffunc add_string str str_to_add
    len = strlen(str_to_add)
    if string_size <= string_length + len {
        string_size += EXPAND_SIZE
        memexpand string, string_size
    }
    poke string, string_length, str_to_add
    string_length += len
    return
#global

#const TRIAL_TIME 10000
#uselib "winmm.dll"
    #cfunc timeGetTime "timeGetTime"

    mes "充分なサイズを確保せずに文字列の結合(連結)を実行。"

    mes "独自命令版計測中……"
    set_string ""
    time_start = timeGetTime()
    repeat TRIAL_TIME
        add_string "sample string\n"
    loop
    time(0) = timeGetTime() - time_start
    mes strf("独自命令を使用:%d[ms]", time(0))
    mes "独自命令版計測終了。\n"

    mes "+=使用版計測開始……"
    string = ""
    time_start = timeGetTime()
    repeat TRIAL_TIME
        string += "sample string\n"
    loop
    time(1) = timeGetTime() - time_start
    mes strf("標準の+=を使用:%d[ms]", time(1))
    mes "+=使用版計測終了。\n"

    mes "noteadd使用版計測開始……"
    notesel string
    sdim string, 64
    time_start = timeGetTime()
    repeat TRIAL_TIME
        noteadd "sample string"
    loop
    time(2) = timeGetTime() - time_start
    mes strf("noteaddを使用:%d[ms]", time(2))
    mes "noteadd使用版計測終了。"
    stop

2 件のコメント:

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

加算じゃなくて連結って言ったほうがいいと思う。

eller さんのコメント...

ご指摘ありがとうございます。
HSP3のヘルプを確認しましたら、結合と表記されていましたのでそちらに変更したいと思います。連結も併記しておきます。