Gauche:GC
GaucheはBoehm GCを使っている: A garbage collector for C and C++
(2002/12/01 20:01:41 PST) たっちん gc の話題ではないですが、他にないのでここに書きます。
pair-attribute はどういう意図で用意したのですか。現在は source-info にしか使っていないようですが。これのために ScmPairRec にポインタひとつ追加するのはもったいないような気がしますけど。
- Shiro: もったいないですね。多分、source-infoがほぼ唯一の使い道です。 メモリの節約を考えるなら、Biglooがやっているようにpairにattribute付きのものと 無しのものと2種類設けるという方法が良いと思います。 今の実装はとりあえず単純さを取りました。
- 本気でメモリを節約したいならsimple pairは2ワードまで減らせなくは ありませんが、コードを複雑化させてそこまでやる程にはまだメモリに せっぱつまってないので…
- 最近のPCなら、メモリが潤沢にあったとしてもCPU <-> メモリ間の 転送量を減らすことに性能上意味があるので、いずれそのへんのチューニングは 入れると思います。ただ現状ではVMを改善する方が先かと考えています (threaded code interpreterにするつもりでいます)。
- → Gauche:CompactingPair
(2002/09/18 06:08:37 PDT) satoru ただいま作っているメールフィルタを実行すると
GC Warning: Finalization cycle involving 84bb580
という警告が出力されたりされなかったりしされます。 この警告を防ぐにはどうしたらよいものでしょう。
- Shiro: 0.6.3では解消されます。 応急処置としては、src/port.c:104の GC_REGISTER_FINALIZERマクロ呼び出しを GC_REGISTER_FINALIZER_NO_ORDERにしてみて下さい。 (他にも直すべきところがあるんですが、そこが原因でwarningが出るケースが 一番多いと思います)。
(2002/06/20 04:18:02 PDT) RedHat 7.3だとGauche-0.5.6がgcでクラッシュするという報告があった。 Gauche-0.5.6はBoehm GC-6.0を使っている。 Boehm GC 6.1alpha5だと大丈夫だったというので、 6.1安定版まで待つつもりだった予定を変更して6.1alpha5をインテグレート中。
こういうことが多いと、GCをGauche中に囲い込まない方がいいのかな。 もともと、パフォーマンスチューニングとか、stack GCの実験とかで GCに手を入れる可能性があったためGaucheの中に入れておいたのだが。
Boehm GC 6.1はlibtoolを使っている。Gauche本体の方では今までなんとなく libtoolを避けて来たのだが、どうせGCの方で使うならGauche本体にも 入れてしまおうか。
- (2002/12/01 19:51:16 PST) たっちん ついでに automake も使っていただけるとうれしいかも。 make dist とか make install DESTDIR=$DIR ができなくて悲しいです。 さらに欲を言えば autoconf-2.13 が使えるともっとうれしい。 RHL では 7.3 までが autoconf-2.13、8.0 でやっと 2.53 なので。
- (2002/12/01 19:53:06 PST) たっちん 私の好みですが、gc は囲い込んで正解なのでは。 iconv さえ囲い込んでほしいぐらい。(切り替えは configure オプションとかで) 外部の gc を使うかどうかを config オプションで切り替えるという手も。
(2002/06/20 22:17:35 PDT) Gauche-0.5.6までは、プロセッサがi686以上だったら Boehm GCのコンパイル時にUSE_I686_PREFETCHを定義するようにconfigure.in とMakeifle.inに手を入れていた。 Boehm GCのドキュメントに「かなり効く」みたいなことが書いてあったからだ。
Boehm GC-6.1alpha5ではautomakeを使っているので、 Makefile.inにまた手を入れるのも気がひける。そこで、 USE_I686_PREFETCHがどのくらい効いているかを簡単に調べてみた。 defaultがGC-6.1alpha5のままでconfigure+makeした場合、 prefetchがUSE_I686_PREFETCHを入れた場合。 なお、比較のためにGauche-0.5.6そのもの(GC-6.0)も示してある。
applicaton: compplot cvt -----------+----------+---------- default | 89.93 | 5.80 prefetch | 88.93 | 5.67 0.5.6 | 94.80 | 6.57
数値はtimeコマンドで測ったuser time(second)の平均。 一応ヒープの消費が多そうなスクリプトを選んだつもり。 プラットフォームはLinux (RH7.2, kernel 2.4.7, gcc 2.96, glibc2.2.4)/Pentium III 450MHz.
まあ、多少は効いているのかもしれない。 それより、0.5.6から速くなったのにちょっとびっくり。
なお、GCのコンパイルフラグはMYCFLAGSで指定できるみたいなんで、 GC本体のソースではなく、MYCFLAGS経由でフラグを渡す方が良さそうだ。
(2002/06/21 03:04:35 PDT) libtool....
現行のbuild processのだとMac OS Xでfail. GCの方がlibtoolizeされたため、 static link用のgc/*.oとdynamic link用のgc/*.loが別々に生成されるのだが、 gc/*.o が-fno-commonでコンパイルされない。libgaucheの方ではこれまで gc/*.oを-fno-commonでコンパイルしてリンクしていたので、これではまずい。 取るべき道は。
- libgauche本体の方もlibtoolizeする
- libgaucheのビルド時にgc/*.loの方をかき集めるようにする
- gc/ltconfigあたりに手を入れて、MacOS Xでは *.o も-fno-commonで コンパイルするようにする
うーん。現状でマルチプラットフォームでshared libraryをサポートするのに、 libtool以上のツールは無いとは思うんだが、libtoolの持ち込む複雑さが 嫌なんだよなあ。なんとなく本能的に避けたくなる類の複雑さなんだ。
(2002/08/02 02:04:53 PDT) コンパイルフラグ
Boehm GC 6.1alpha5に入れ換えた時に、コンパイルフラグをほぼデフォルトのまま 使うようにしたのだが、それだとDONT_ADD_BYTE_AT_ENDがdefineされていなかった。 ALL_INTERIOR_POINTERSがdefineされているので、GC_mallocは要求バイト数より 1バイトだけ多めにallocateする(現実的には1ワード余分になる)。
これだけならメモリ喰いなだけでロジック的には正しく動作するはずなのだが、 pairのアロケートに関してはGCのインラインマクロを使っており、きっちり4ワード アロケートしていた。ところがDONT_ADD_BYTE_AT_ENDをdefineしないと、 オブジェクトの最終ワードをgcがスキャンしないという。 pairの場合、最終ワードはpair attributeに使われている。 現在のところ、pair attributeはソースコード情報を格納するのにだけ 使われている。これがgcで回収されてしまっていたため、 エラー時のスタックトレースがおかしくなっていたのであった。
何でGCがこんな仕様になっているのかと言えば、Cの仕様ではオブジェクトの 配列の最終要素の「次」を指すことが許されているからなんだろうが、 Gaucheでは唯一のポインタがそういう場所を指すような使い方はしていない はずなので問題ない。Gauche-0.6.1ではDONT_ADD_BYTE_AT_ENDをdefineした。
Gauche-0.6で迷ったのは、THREAD_LOCAL_ALLOC。マルチスレッド時にこれを defineしておくと、各スレッドがメモリプールを持って、グローバルから メモリを取って来るのはメモリプールを使い切った時のみになる。 ローカルのメモリプールからmallocする際はロックする必要が無いから、 かなりスピードが速くなる可能性がある、とドキュメントにはある。
ところが、マルチスレッドでTHREAD_LOCAL_ALLOCをdefineして ビルドしたgoshでシングルスレッドアプリケーションを走らせると、 ものすごく(20%程度)速度が低下した。THREAD_LOCAL_ALLOCの元では GC内のlockが重くなる(spin lockを使わないようになる)のが原因ではないかと 睨んでいるのだが、とにかくこれでは話にならない。 goshの想定する応用範囲ではシングルスレッドのスクリプトが多いと 考えられるので、ここはそちらを優先してTHREAD_LOCAL_ALLOCはデフォルトで 使わないことにした。
もともと、シングルプロセッサマシンでgoshをマルチスレッドで走らせる 第一の意味は、ブロッキングI/Oを扱うコードが書きやすいという点だと 考えている。協調スレッドならcall/ccで書けるわけだし。 だもんで、マルチスレッド化による性能の向上というのはあまり期待していない。
マルチプロセッサマシン上でgoshをマルチスレッドで使って性能を上げたい、 という場合はTHREAD_LOCAL_ALLOCをdefineした方が良いかもしれない。 手元に環境が無いので試せないのだが。
Tag: GC