結論からいうと次のようにやると高速にできます。
(これは「簡易的に5000行のテキストデータ作成」の部分ですが、*gogo の方も同様です。)
loop_cnt = 5000
sdim text, 10000
text_len = 0 ; text の長さ
repeat loop_cnt
; text に追加する文字列
new_line = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
new_line_len = strlen(new_line)
; poke 命令で変数のサイズを超えて書き込むとエラーになるので、変数の領域を拡張する。
if text_len + new_line_len >= varsize(text) {
memexpand text, (text_len + new_line_len + 1) * 2
}
; text の末尾に文字列を書き込む。
poke text, text_len, new_line
text_len += new_line_len
loop
; 念のため 5000 行書かれたことを確認
notesel text
mes notemax
----
解説:
文字列を書き込む先の変数 text に加えて、
それの長さを覚えておくための変数 text_len を追加します。
常に strlen(text) == text_len が成り立つようにしておくことで、
strlen(text) の計算を省略するためです。
text を変更する際は text_len も同時に変更する必要があるので、注意してください。
sdim text, 10000
text_len = 0 ; text の長さ
次に、text に文字列を追記するときの処理です。
追記する文字列の長さを何度か使うので、変数 (new_line_len) に入れています。
; text に追加する文字列
new_line = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
new_line_len = strlen(new_line)
後で poke 命令を使うのですが、これは変数のメモリを自動では拡張しないので、
追記した文字列が text の残りのメモリに収まらないとエラーになってしまいます。
そのため、 memexpand 命令を使って text のメモリを拡張します。
ここでは、文字列を追記した後に必要な大きさ (text_len + new_line_len + 1) がメモリサイズを超える場合は、
変数のメモリをその2倍の大きさまで拡張しています。(詳細は後述)
; poke 命令で変数のサイズを超えて書き込むとエラーになるので、変数の領域を拡張する。
if text_len + new_line_len >= varsize(text) {
memexpand text, (text_len + new_line_len + 1) * 2
}
最後に poke 命令を使って、text の末尾に文字列を書き込みます。
先ほど書いたように text_len も変更が必要です。
; text の末尾に文字列を書き込む。
poke text, text_len, new_line
text_len += new_line_len
なぜこれが速いか:
noteadd 命令は文字列の末尾を探すために strlen(text) に相当する計算を行っているのですが、
これは text の長さに比例して時間がかかるので、文字列が長くなってくると遅いです。
poke は書き込む位置をパラメータで直接指定できるので、この計算を省略できる、というのが理由です。
----
memexpand のメモリの計算式について:
memexpand 命令自体は、文字列全体をコピーする可能性があるので時間がかかります。
変数のメモリをぴったりにしてしまうと、ループのたびに memexpand が実行されることになり、
全体としてかなり時間がかかります。
ここではメモリを倍々に拡張していくことで memexpand が必要になる機会を少なくしています。
----
詳細は以下の記事も参照:
[HSP3 文字列のひみつ](
https://www.onionsoft.net/hsp/v36/doclib/hsp3str.htm)
[文字列の扱い](
http://prograpark.ninja-web.net/HSP/other/proc_string.html)