HSP Document Library のソースを読んでみました。
hdl.hsp(バージョン 1.0 ) 1234 行目、 1305 行目と 1446 行目あたりで以下のように文字列の連結を行っていました。
tmp = "" ; accelerator ▽
repeat count
( 略 )
tmp += ( 略 )
if 1000000\(cnt+1)=0 : buf += tmp:tmp="" ; accelerator
sql_next
loop
buf += tmp ; accelerator △
これって tmp という変数を使わずに直接 buf に連結しても多分大丈夫だと思うんですが、こうした方が高速なのでしょう。文字列を連結するときには先頭から文字列の終端を探すことになるので、長い文字列だと時間がかかります。連結する文字列をまとめてから連結することで、長い文字列に連結する回数が減って高速になる、ということです。
本当に速くなるのか試しに実験。
#uselib "winmm.dll"
#cfunc timeGetTime "timeGetTime"
#const trial_times 2000
proc = *a, *b
repeat 5, 1
trial_strlen = cnt * cnt * cnt * 1000
mes strf("文字列長(%dbytes)の場合:", trial_strlen)
foreach proc
sdim buf, trial_strlen + 1
memset buf, 'a', trial_strlen
time = timeGetTime()
gosub proc.cnt
time = timeGetTime() - time
mes strf(" %c : ", 'a'+cnt) + strf( "%d[msec]", time )
await
loop
mes
loop
stop
*a
repeat trial_times
buf += "sample string"
loop
return
*b
tmp = ""
repeat trial_times
tmp += "sample string"
if 1000000\(cnt+1)=0 : buf += tmp:tmp=""
loop
buf += tmp
return
文字列長(1000bytes)の場合: a : 35[msec] b : 6[msec] 文字列長(8000bytes)の場合: a : 62[msec] b : 6[msec] 文字列長(27000bytes)の場合: a : 125[msec] b : 9[msec] 文字列長(64000bytes)の場合: a : 215[msec] b : 10[msec] 文字列長(125000bytes)の場合: a : 329[msec] b : 14[msec]
なかなか速くなっているようで驚き。
HSP3のスクリプトを垂れ流すブログ: 高速な文字列の結合(連結) のスクリプトに以下を追加して試してみました。
mes "\ntmp使用版計測開始……"
string = ""
tmp = ""
time_start = timeGetTime()
repeat TRIAL_TIME
tmp += "sample string\n"
if 1000000\(cnt+1)=0 : string += tmp:tmp=""
loop
string += tmp
time(3) = timeGetTime() - time_start
mes strf("tmpを使用:%d[ms]", time(3))
mes "tmp使用版計測終了。"
独自命令版計測中…… 独自命令を使用:88[ms] 独自命令版計測終了。 +=使用版計測開始…… 標準の+=を使用:1020[ms] +=使用版計測終了。 noteadd使用版計測開始…… noteaddを使用:3306[ms] noteadd使用版計測終了。 tmp使用版計測開始…… tmpを使用:123[ms] tmp使用版計測終了。
poke を使うのよりやや遅いくらいです。 += を使うのでも工夫すれば速くなるのですね。
計測した環境は Windows XP Home SP2 / Pentium 4 CPU 2.40GHz / 512 MB RAM です。