ありゃー、Sony...。
いや、もうこれだけでなんとなく察するものがあるという人も多いのではないでしょうか。このサイトでは、あんまり企業や製品のことについて言及することは避けようと思っているのですが、あまりと言えばあまりな成り行きについ。
閑話休題。「AppleScript でアルゴリズム」でクイックソートを掲載したのですが、面白いことをデザイナーの池田さんが教えてくれました。
池田さんのサイトでは「AppleScript 実験室」と題していろいろな実験結果を掲載されています。Mac OS X になってから、AppleScript でいろいろ実験をしてその結果を掲載しているサイトというのは少ないので、こういうサイトはとても貴重です。
さて、その「AppleScript 実験室」には「レコード内のリストの参照」というコンテンツがあります。池田さんが行った実験というのは、「レコード内のリストの要素の参照と通常のリストの要素の参照、どれぐらいアクセス速度が異なるか」というものです(詳しくは、池田さんのサイトの方を参照してください)。おそらく、リストを参照するよりレコード内のリストを参照する方が遅くなるだろう...という予測をもとに実験を行ったのだと思いますが、予想外の結果になっています。レコード内のリストを参照した方が速いのです。
この書き方だと誤解がありますが、リストに a reference to を使うより、レコードに a reference to を使う方が速い、という方が正確ですね。以下の結果を見てもらうと分かりますが。
実験結果をクイックソートに適用したものを送ってきてくださいました。これを動かしてみると、確かに速いのです。なぜ?
クイックソートでは分かりにくいので、以下のようなスクリプトを作って試してみました。
set theList to {}
repeat with i from 1 to 10000
set end of theList to i
end repeat
set cd to current date
repeat 100000 times
item 10 of theList
end repeat
(current date) - cd
整数値をリストに 1 万項目入れて、10 番目の要素を 10 万回取り出すだけのスクリプトです。これは、環境によって結果が異なりますが、iMac G5 では約 160 秒。これではあまりにも遅いので、通常は a reference to を使ってリストの参照を用います。
set theList to {}
set theListRef to a reference to theList -- リストを参照に変換
repeat with i from 1 to 10000
set end of theListRef to i
end repeat
set cd to current date
repeat 100000 times
item 10 of theListRef -- リストの参照にアクセス
end repeat
(current date) - cd
こうするだけで約 3 秒になります。次に池田さんが行った実験を適用します。
set theList to {}
set theListRef to a reference to theList
repeat with i from 1 to 10000
set end of theListRef to i
end repeat
set theRecord to {numList:{}}
set theRecordRef to a reference to theRecord -- レコードの参照に変換
set numList of theRecordRef to theList
set cd to current date
repeat 100000 times
item 10 of numList of theRecordRef -- レコードの参照にアクセス
end repeat
(current date) - cd
こうすると、さらに速くなって約 1 秒。レコードにアクセスする方が速いのかと思い、a reference to を使わずに比較してみるけど、リストのときと変わりません。
set theList to {}
repeat with i from 1 to 10000
set end of theList to i
end repeat
set theRecord to {numList:{}}
set numList of theRecord to theList
set cd to current date
repeat 5000 times
item 10 of numList of theRecord -- ここ
end repeat
(current date) - cd
このスクリプトの numList of theRecord を theList に変えても速度的に差はないんですね。a reference to で参照に変換したときだけ速いんです。原因不明。この結果を理解するには、AppleScript の内部に踏み込まないといけないような。どなたか、なぜ速くなるかご存知でしょうか?
誤解のないように、追記。a reference to を使うと速度的には速くなりますが、乱用すると逆に遅くなります。なんでもかんでも速くなるわけではないので。