HyperCard tribute
スピードアップさせるために
ハイパーカードはとても柔軟な言語であり、複雑な動作を非常に簡単にできるようになっています。しかし、この大変便利な特徴のおかげでスピードが遅くなってしまっているのも確かです。 スピード低下の原因にはこの他にも、HyperCardがハードディスクへのアクセスを多用していることも大きな原因となっています。例えば、HyperCardには「保存」メニューがない代わりに様々なタイミングで自動保存(ハードディスクへの書き込み)を行っています。他にも、データをメモリに読み込ずにハードディスクからデータを取る場合なども多くあるのです。 これらが、HyperCardが遅くなる原因なのですが、もう一つの原因に速く動くようなスクリプトの組み方をしていないという事も挙げられるのです。HyperCardの性質を理解し、速く動かす為の工夫をすれば10%はスピードを高めることが可能です。 ここでは、スピードを速くするための方法と、遅さを感じさせないスクリプト作りについても紹介します。 ■反応を早くする 人間が遅く感じる理由は、大きく分けて2つあります。1つ目は実際のスピード。2つ目は反応速度です。例えば、ボタンをクリックした時に反応がすぐに返ってこない、フィールドのスクロールの速度が遅い、待ち時間の間に何も反応がないなどです。 この理由には2つの原因があります。 1.スタック内のオブジェクトとデータの量が多い 2.反応を返す工夫をしていない カードの枚数は、多くなればなるほど反応が鈍くなります。カードの枚数が多いという理由とそのカードに含まれるオブジェクト、データが多くなるからです。このために、かなり多くのデータを必要とする場合は、スタックからスタックを呼び出すなどして分割する方法をとるなどすれば良いでしょう。 ボタンの数は、特に大きな影響を与えます。ボタンをなるべく作らないようにするという事と、メニューやパレットを用いるなどして、できる限り少なくするようにしましょう。 フィールドの数は上の2つに比べると、それほど遅くなるという事はありません。それよりもフィールドの場合は、1つのフィールドに書き込まれているデータの量と、画面に実際に表示されているデータの量による原因の方が速度低下が大きいのです。必要のないデータであれば、できるだけ hide しておきましょう。これにより、フィールドに多量のテキストが入っていたとしても速度低下はほとんど起こらなくなります。 反応を返す工夫をしてみます。例えば、とても簡単な事ですが、ボタンのハイライトをオンにする、クリック音を鳴らす、待ち時間にカーソルの形態をMacお馴染みの腕時計カーソルやビーチボールに変える、待ち時間に合間を縫ってユーザーに視覚的なイベントを見せるなどです。 ボタンのハイライトをオンにすれば、クリックした瞬間にボタンが反転しますので、クリックしたことがユーザーに直に伝えることができるようになります。 クリック音を鳴らすようにすれば、その音が鳴っているほんの少しの間だけでも待っているという感覚から抜け出すことができるようになります。 カーソルの形態を変えれば、長い待ち時間も「ちゃんと仕事をしてるよ」という事を感じとることができます。人を待っている時に何も連絡がないよりは、時々電話連絡があれば、待ち時間はかなり短く感じることと思います。これと同じ事ではないでしょうか。 待ち時間の合間に、例えばメッセージボックスに、現在の状況をユーザーに伝えるなどをしてみてはどうでしょうか。単純なところでは、残り何秒などと表示するなどです。これにより、スピードは逆に遅くなるかもしれません。しかし、感覚的には速く感じるのではないでしょうか。 ■画面をロックする ユーザーに見せる必要のない処理の場合は、lockscreenをして画面の書き換えをロックします。例えば、画面上のフィールド全てを表示したり、データを代入したり、カードを巡回してデータを拾ってくるようなスクリプトの時は大きな効果が現れます。 「画面をロックする場合」
「画面をロックしない場合」
それぞれ5回ずつ実行した平均値は、「画面をロックする場合」が93、「画面をロックしない場合」は805.7となりました。つまり、画面をロックしたことでスピードが8.7倍になったことになります。 ■フィールドの代わりに変数を使う フィールドに書き込むという事は、すなわちハードディスクへのアクセスがあるということですから、これを変数(メモリ)に変えることで大幅なスピードアップが図れます。 フィールドを使うと時間がかかるのは、ハードディスクへのアクセスだけではなく、画面の書き換えも関係しています。表示されているフィールドに次々とデータを書き込むと、当然の事ながら画面上でもデータを書き換えるわけですから、時間がかかるのです。 「画面をロックしない」のスクリプトを変更して実験をしてみたいと思います。フィールドの代わりに変数「test」を用いた場合と、フィールド「test」を使った場合です。 結果は、「変数を使う場合」が14.3、「フィールドを使う場合」は575.3となりました。今回は40.2倍のスピードアップです。 ■フィールドはhideして使う どうしてもフィールドを使わなければならない時は、hideして使うことでスピードを上げることができます。 「画面をロックしない」のスクリプトを用いて実験をした結果、「フィールドをhideして使う」が426.3、「フィールドをshowして使う」が805.7ですので、1.89倍のスピードアップとなりました。 ■カードを移動するのでなく、参照する 他のカードにあるフィールドからデータを取る場合、カードを移動してデータを取ってくるより、参照した方が高速となります。 しかし、同じカードの複数のフィールドからデータを取る場合は少し状況が変わります。もし10以上のフィールドからデータを取ってくるような場合は移動してからまとめてデータを取った方が高速になるでしょう。あともう一つ、他のスタックのカードからデータを取ってくるような場合は、移動してデータを取ってくるしか方法はありません。 これらのようにどうしても移動が必要な場合は画面をロックしておくことを勧めます。なぜなら、ユーザーにその画面を見せる必要がないですし、スピードも大幅に向上できるからです。 ■変数名を短くする 変数名を短くするだけでスピードは速くなります。あるスクリプトを用いて実験してみます。適当なボタンを2つ用意して、それぞれ以下のスクリプトを打ち込んでみて下さい。 「変数名が短い場合」
「変数名が長い場合」
「変数名が短い場合」が89.2、「変数名が長い場合」98.2はとなりましたので、変数名を短くしたことでスピードが10%アップしたことになります。 変数を短くすればスピードは早くなるのですが、その代わりに変数名がわかりにくくなりますので、ほどほどにするのが良いでしょう。 ■文字列はダブルクォーテーションでくくる 文字列をダブルクォーテーションでくくることでもスピードアップを図ることができます。 文字列は、変数と同じ名前でない場合はダブルクォーテーションを付けなくてもエラーにはなりません。そのため、文字列をそのままスクリプト内に記述してしまうことが多いのですが、ダブルクォーテーションでくくることにより、変数と区別されるのです。 もしダブルクォーテーションでくくらなかったとしたら、まず変数にデータが納められているかどうかを調べてから、文字列として扱うことになります。すなわち、これによりHyperCardは最初から正しいアクセスができるわけです。 「文字列をダブルクォーテーションでくくる」
「文字列をダブルクォーテーションでくくらない」
「文字列をダブルクォーテーションでくくる」が203.3、「文字列をダブルクォーテーションでくくらない」は218.3となりましたので、7%のスピードアップとなりました。 ■イコール(等しい)でなく、ノットイコール(等しくない)を使う これは非常に不思議なのですが、イコールを使うよりノットイコールを使った方が、少しですが早くなります。 「ノットイコールを使う」
「イコールを使う」
「ノットイコールを使う」が46.7、「イコールを使う」は45となりましたので、3%のスピードアップとなりました。 ■関数は the xxxx を使う HyperCardの関数の呼び出しは、theを使う方法と、()を使う方法の2通りがあります。この時、theを使って記述するとスピードが向上します。 theを使うと、呼び出しは直接HyperCardに送られるのですが、()を使うと、全てのメッセージの階層を通って同じ名前の関数がないかどうかをチェックした後でHyperCardに送られることになるため、スピードが遅くなってしまうのです。 「the xxxxを使う」
「()を使う」
「theを使う」が195.3、「()を使う」は216となりましたので、11%のスピードアップとなりました。 ■複数の式をまとめる スクリプトをわかりやすくするために、複雑な式を必要とする場合は式の値を変数などに納めてから計算をするという方法を用います。しかし、この方法は2つの問題点があります。まず、1つ目は変数が多くなってしまうということ、2つ目はスクリプトが長くなってしまうという事です。ですから、まとめることができる式はできるだけまとめるようにしましょう。 「複数の式をまとめる」
「変数に一度代入させる」
「複数の式をまとめる」が53、「変数に一度代入する」は99.7となりましたので、19%のスピードアップとなりました。 ■変数の参照を少なくする 具体的を用いて説明します。変数xをyだけ増加させようという場合、 1 put x + y into x より 2 add y to x とする方が速いのです。 なぜならば、1ではxを2回とyを1回、計3回変数を参照しますが、2ならばx、yを1回ずつの2回しか参照しないからです。 「変数の参照を少なくする」
「普通に変数の参照を行う」
「変数の参照を少なくする」が15、「普通に変数の参照を行う」は16.7となりましたので、10%のスピードアップとなりました。 ■ループ構造の中は短くする ループは何回も同じ事を繰り返すわけですから、ループ構造内はできるだけ簡潔に記述するべきです。一行でも無駄な行があれば、繰り返しの回数だけ無駄な行を実行してしまうことになるからです。 「ループ構造の中は短くする」
「普通にループ構造内を記述する」
「ループ構造の中は短くする」が19.7、「普通にループ構造内を記述する」は40.3となりましたので、2.1倍のスピードアップとなりました。 ■ハンドラからハンドラを呼び出さない 長いスクリプトの場合、一部分をまとめてハンドラとして独立させることで、スクリプトが読みやすくなります。これはスクリプト作成の点からすると非常に有効にスクリプトを利用できる方法なのですが、その分実効速度は遅くなってしまうのです。 それは、HyperCardでは、ハンドラを呼び出すとそのスクリプトのハンドル部をメモリに蓄え、スクリプトを実行後そのスクリプトのハンドル部を消去するようになっているからです。このような原因から、ハンドラからハンドラを呼び出すよりすべてハンドラの中だけで処理した方が高速化するというわけなのです。 「ハンドラからハンドラを呼び出さない」
「ハンドラを呼び出す」
「ハンドラからハンドラを呼び出さない」が26.3、「ハンドラを呼び出す」は67.3となりましたので、なんと2.6倍ものスピードアップとなりました。 ■lineマcharマitemマwordの順に利用する コンテナ内の値を構成する単位をチャンクといいますが、このチャンクを変えることによりスピードアップを図ることができます。スピードはタイトルの通り、lineマcharマitemマwordの順になっています。 「lineチャンクを用いる」
「charチャンクを用いる」
「itemチャンクを用いる」
「wordチャンクを用いる」
「lineチャンクを用いる」が24.2、「charチャンクを用いる」は28.6、「itemチャンクを用いる」が32、「wordチャンクを用いる」は48.4となりました。スピードの向上を望むならば、lineチャンクを用いるのが良いでしょう。 ■日本語を表示しないフィールドは英数字フォントを使う 日本語を表示しないフィールドは英数字フォントに設定することで少しですが、スピードアップさせることができます。「画面をロックしない」のスクリプトを用いて実験をしてみます。 結果は、フォントを「Osaka」にした場合が573、「Courier」にした場合が555.3となりました。3%のスピードアップが図れたことになります。 ■その他 この他にも、global宣言は一行で行う方が速い、オブジェクトの座標はrectよりlocの方が速いなどがあります。 |