コレの続き。まぁ、大半の読者にとってはどーでもいい話だと思うので、気になる人だけ続きをどうぞ。
結論から言うと、
近ちゃん氏が気にしていた“SetEventAfter命令を使った繰り返し実行によってメモリリークが起きるのではないか”という不安は杞憂だ。近ちゃんに限らず、諸兄も気にせずにバンバン使っていただきたい、使えるのなら。
で、この実験の過程で、表題にも書いたように「意外なこと」に気づいた(まぁ、結果から振り返るとそりゃそーだわな、って話なんだけども)ので、それを報告すべく、どんな実験をやったのかを説明していくことにする。
* * *
まず、前回予告していた通りの実験をやった。図にするとこんな感じ。
それぞれの□がメソッドだと思って欲しい。最初の左端の□は、オブジェクトの宣言部で、右へ伸びる五本の矢印は、それぞれがSetEvnetAfter命令で次のメソッドの実行イベントを設定したことを意味している。最初を除き、他の□からは次のメソッド1つだけに対しSetEventAfter命令を仕掛けている。実際には、若干の時間差を設けているので、図のように整然と並んで実行されるのではなく、バラバラと五月雨的に併走実行されることになる。
さて、それぞれの□=メソッドでは255個のローカル変数を宣言しているので、これが新たに必要なメモリ領域としてWindowsから借用(いわゆるallocate)され、結果的にタスクマネージャから見えるVRMビュワーのメモリ使用量の増加として観測される。前回も書いたように、メモリリークが発生するのであればこれが漸増するはずだが、実行開始時に微増した以外、数分動作させても(テストでは→の間隔は数ミリ秒であり、この数分は普通の使い方での1時間以上に相当すると考えて良い)変化は起こらなかった。つまり、メモリリークは発生しない、ということになる。
さて。ここでちょっと茶目っけが生まれて、さらに過酷なテストをやってみる気になった。いや、結果から言うと過酷でも何でもなかったんだけども。
基本的な考え方は最初の実験と同じだが、それぞれのメソッドは2つのメソッドに対してSetEventAfterをする。つまり、時間経過につれて同時実行されるメソッドの数が鼠算式に増えていく、という仕掛けである。もし、VRMからWindowsに対するメモリの借用が、併走するメソッド間でまったく同時におこなわれるのであれば、アッという間にWindowsの物理/仮想メモリ領域を食いつぶしてWindowsがお亡くなりになるはずである。
で、やってみたら、最初の実験同様にメモリ使用量は微増したのみで、安定してしまった。クラッシュを期待していたので拍子抜けである。これは何を意味しているのか。
話は簡単で、上に書いたような「衒学的な図」で考えていたがために生じた誤解に振り回されていただけなのだ。断言は出来ないが、VRM内部の動作から見たSetEventAfter命令というのは、SetEventAfterイベント実行エンジン(と仮に呼ぶ)という1ミリ秒毎に待ち行列を検査して実行待ちになっているメソッドがいればそれを1つ実行する仕組みに対し、「その待ち行列に並べ」とメソッドを送り込む命令に過ぎないのだ。
従って、理屈の上では上掲図のようにたくさんのメソッドが同時に実行され、その分だけメモリが消費されるように思えるこの実験も、実は単にメモリを消費する処理として実行されるメソッドの待ち行列が増えてダダ混みになるだけの話であって、決してそれでメモリリークであるとか、ましてやOSクラッシュなんて起きないのである。
ただし、この待ち行列に並んでいる人の中にはビュワーを操作するためのキー/マウス入力なんかもいる(厳密には系列が異なるはずだが、VRMの仮想マシンからすれば同じようなモンである)ので、実験を開始するとすぐにマウスカーソルが効かなくなる。無駄なテストメソッドにシステムの時間を食い尽くされて(待ち行列を占拠されて)マウス操作を処理する手が空かなくなるという寸法だ。
* * *
と、ちょっとした実験と、そこから導かれる“仮説”について述べた。
ボクがこれを書いた意図は、「VRMの中身はこうなっているのだ」と断言するためではない。断言するにはVRMを逆コンパイルしてソースを読む必要があるが、そんなことをするつもりはない。ここに書いたのはブラックボックス的なテストであるからして、実際の実装はまた違っているかも知れない。確実なのは、大なり小なりここで述べたような動作をVRMがしている、ということだ。他に説得力のある仮説が思いついた人は聞かせて欲しい。
で、ボクが言いたいのは、迷信や妄想に取り付かれる前に、こういう風に仮説と検証実験を通して自分で考える癖をつけろ、ということ。まぁ、期待してないけど。