昨日の話は、一日考えて、Cプログラマに若干の負担を負わせないとやっぱり無理なのでは?と、いう結論に。

  • 型情報生成ツールを使って型情報を生成すること
  • メモリアロケート時に、その型情報を渡すこと
  • スタックとローカル変数辿れるように、DWARF2デバッグ情報を残すこと
  • intとポインタをごっちゃにしない

いや、でも、許容範囲だと思うんだけど…


まあいいか。気が向いたらやってみる…って、最近、気が向いたらキューを溜めすぎだよな。(いや、気が向いたらキューは溜まらないよ。すぐオーバーフローする。)


それはいいとして、連続するメモリ領域について考える。
オブジェクトがヒープにいるのかを判定するにするには、ヒープ領域が分断されてるよりも、ひとかたまりになっていたほうが良い。そうすれば、一回の判定で、ヒープのオブジェクトなのかどうかが判定できる。

bool is_heap( void *ptr )
{
	if ( ptr >= heap_begin && ptr < heap_end ) {
		return true;
	}
	return false;
}

だが、しかし、ここで問題がある。ヒープ領域をひとつにしたい、ということは、ヒープ領域を分断できない、ということである。。
もし、なんかのライブラリがヒープ領域を使ってた場合、GCの領域を拡張できないかもしれない

GCがヒープ確保→なんかのライブラリがmalloc→GCの領域を拡張

このとき、GCの領域を拡張するのが不可能になるかもしれない。


この問題で、一番手っ取り早い解決方法は、最初に超余裕を持って領域を確保しておく方法だ。

	/* 512M !! */
	gc_heap = malloc( 512*1024*1024 );

仮想メモリがちゃんとしてあるOSだったら、このぐらいやっちゃっても、実際に書き込まれるまでは、メモリ割り当ては起こらない。必要なときに、必要なだけOSがメモリを割り当ててくれるわけだ。OSは偉い。


でも、この方法はもうちょっと改良したい部分がある。無駄なスワップが起こるという部分だ。
たとえば、一時的に、300MBぐらいメモリを使って、そのあとGCが動いて、使ってるメモリが15MBぐらいになったとする。
このとき、使わない285MBは、必要の無い領域になる、が、しかし、この領域には一旦書き込んでしまってるので、ページが割り当てられているわけだ。そうなると、他のプロセスがメモリを必要としたときに、この領域がスワップアウトしてしまう。
つまり、無駄なスワップが発生してしまうわけだ。PC使ってる時のストレスの80%ぐらいはスワップが原因(多分)なので、無駄なスワップが発生するのは心苦しい。


けど、まあ、なんか方法があるだろう、と思って、適当に調べてみた。(ここまでが前フリ)


まず、Windowsの場合、MEM_RESERVEとかいうのがあって、メモリは割り当てないけど、アドレス領域は空けとく、とかいうのができるっぽい。
http://www.microsoft.com/japan/developer/library/jpwinpf/_win32_virtualallocex.htm
最初にメモリを割り当てるかわりにRESERVEしておいて、ちょびちょびコミットしたり解放したりしていけば良い感じ。


んで、Linuxの場合。ちょっと汚いけど、mremapを使えばできるような。
一回領域を小さくしてやれば、ページの後ろのほうは、未使用領域にできるはず。多分。

#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main( int argc, char **argv )
{
	int sz = atoi( argv[1] );
	int i;
	char *p;
	p = mmap( 0, sz*1024*1024, PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0 );

	for ( i=0; i<sz*1024*1024/4096; i++ ) {
		memset( p+4096*i, 0xf, 4096 );
	}

	mremap( p, sz*1024*1024, 4096, 0 );
	mremap( p, 4096, sz*1024*1024, 0 );

	sleep( 30000 );
}

こういう感じ。マルチスレッドだとアレだが。


あと、BSDでは、madviseというので、MADV_FREEというのを使えば、できる…ように見えたんだけど、手元のMacではなんかよくわからんかった。使い方が間違ってたのかな…


いや、だからなんだ、という話ではあるんだけど。まあ、知ってれば、そのうち役に立つこともあるかもしれない。