[ Home | Programming Tips | Mail ]

Using Handle is good?


なるべく Memory確保は Handleを使った方が良い?

 昔の Memoryが 1M byteくらいしか搭載されていなかった時代はともかく、多量の Memoryと仮想記憶のもとではこれは迷信に近いです。
 そもそもよく例に上げられている Handleの使い方には間違った物が多いです。例えば

	h = NewHandle(100);
	HLock(h);
		:
	DrawPicture(picHnd,&destRect);	// needs big work space
		:

みたいに Handleを安易に HLock()してはいけません。特に作業領域を大量に必要とする Toolbox callの前では決定的にまずいです。
 これに対して

	p = NewPtr(100);
		:
	DrawPicture(picHnd,&destRect);	// needs big work space
		:

は問題ありません。これはなぜでしょうか?

 NewHandle()は確保した Memory Blockが Relocatableで邪魔にならないことを前提にしていますから、Memory Managerは最初に見つけた空き領域を使います。このため多くの場合 Application Heapの真ん中辺りにひょいと確保されます。これをそのまま HLock()してしまうと Application Heapが Lockした Handle Blockでまっぷたつに分割されます。この状態で大きな作業領域を必要とする Toolboxを使ったり、大きな Memory Blockを要求すると Memory不足で失敗する可能性が高くなります。

 一方 NewPtr()の場合 Memory Managerは Memory Blockが邪魔にならないように可能な限り Application Heapの端に確保します。ですから残りの Heap Spaceが分断されるようなことはありません。ただし Application Heapの端に確保するためには、最適な位置を探したり、邪魔な Relocatable Blockを移動させる必要があるため NewHandle()に比べてはるかに時間がかかります。

 どうしても Handleを Lockしたい場合は

	h = NewHandle(100);
	HLockHi(h);                     // Heapの端に移動して Lock
		:
	DrawPicture(picHnd,&destRect);  // needs big work space
		:

とします。HLockHi()も NewPtr()同様時間のかかる作業ですので、わざわざこんなことをするくらいなら最初から NewPtr()を使うべきです。
 NewPtr()の遅さが問題になる場合は malloc() / newを使います。malloc() / newはあらかじめ大きめの Non Relocatable Blockを確保し、その中を割り振りますので高速です。特に C++の Objectなど数 K byte以下のサイズは全て malloc() / newを使うべきです。

 では Handle Blockを使うのはどんな場合でしょうか? 私の判断基準は以下の通りです。

 基本的にこれ以外は全部 newで確保しています。
 要点をまとめると

 また malloc() / new()を使うことは性能面だけでなく OS固有の Memory Allocation Serviceを 隠しますので Source Fileレベルでの移植性を向上させます。
 File Access等の I/Oを直接 OSの Serviceで行わず抽象的な Stream(PowerPlantで言えば LStream class)に対して行うのも性能/移植性の面で同様の効果があります。


この Pageは MacOS X + Radio UserLand で作っています。