D言語悩む

Ver0.159あたりから以前のコードがコンパイルできないほどの仕様変更が頻繁に起こったD言語も昨日ついに1.00となり、今後はコンパイルできないほどの仕様変更は2.xxbに入ることになる。
そう信じたい。
そうすると、自分のコードを同じ言語に移植するハメになったり、使っているライブラリまでコンパイルできなくなってしまって、しかもいつまでたってもオフィシャル版が更新されないものだから、自分でパッチを作るべきか待つべきかを数日間悩むことになるような事態もすべてなくなるというわけだ。
最近は自宅でC言語ばかりを使っているものだから、ああD言語は本当によかった――なんて過去を振り返ることが多く、そんなときにVer1.00リリースのニュースを聞くとつい飛びついてしまいそうだし、実際飛びつこうとしてどういう準備がいるかを昨夜考えていた。しかし、自らの過ちも含めD言語恐怖症気味なってしまった俺が、そうなった理由というのは単に言語仕様の変更だけではなかったことを思い出したので、各恐怖項目について再考する必要があった。
そんなような悩みリスト。

  1. GCの挙動が想像およびドキュメントに書かれている本当に素晴らしい感動の内容と違う
  2. 有志によるライブラリの開発が突然停滞する
  3. 連想配列がなんか怪しい(謎、定期的にrehashしていないとassertすることがある、スレッドは関係なかった)
  4. Threadクラスがなんか怪しい(たぶんstate変数でレースコンディションが発生している)

1は、かの有名な大きめのメモリが回収されないという問題。参照してないつもりでも偶然ポインタにキャストするとアドレスが一致するデータがbyte配列内にあると回収されなくなる。byte配列なんて存在ない場合でも、phobosUnicodeテーブルが参照していることになっていたりする。なので大きめのメモリを確保する場合は、明示的にdeleteすることを初めから意識してdelete用のラッパークラスなどを作っておかないと後で大変なことになる(初めにポエニーはメモリが増え続けてマシンごと止まることになり、その後のテキトウなdelete追加によってアクセス違反のバグが多発した……これは俺のせい)。ここで、「大きめってどれくらい?」という疑問が出てくるが、それは確率の問題になるのでなんともいえないのがまた怖い。ようはアドレスの範囲が広いほど参照が外れた後に偶然参照される(されている)確率が高いという理由から『大きめ』であって、少しでもその確率があるのなら実稼動三年後に偶然ヒットしてしまい永久に回収されないメモリがでてくる可能性はある。さらにMD5ハッシュ値の配列や暗号化されたデータブロックなどポインタにキャストするとランダムな数値になりがちなデータが多いと偶然参照したことになる確率がぐっと高くなる。超怖い。
また、GC#minimizeが実装されていないので、一度確保したメモリはOSに返却されることがない。たとえば、DWTでは16*16のアイコンに透明色を設定するたびに約70MBづつメモリを確保するので、アプリ起動時に二つのPNGアイコンを初期化すると、その後アプリは140MBのメモリを確保したままになる。ユーザーからの「メモリ使用量が多すぎる」という文句が超怖い(HovenではOSのalloc/freeを使うようにDWTにパッチしている)。
これらは常駐しないソフト(コマンドやCGIなど)では、気にかけなくてもいいと個人的には思っている。何日間も動くようなデーモン的なプログラムでは気にかけたほうがいい。たとえば、ウェブサーバーを作ったときは数日間は自動リクエストを投げ続けてメモリが増え続けていないかをチェックしたほうがいいだろう。
2は商用じゃないことがそもそもの原因だと思うが、今回のVer1.00のリリースによって更新停滞することは減るはずだ。そもそもバグ以外での更新が必要なくなる。切実にそう信じたい。
3と4はよくは調べていないのでGC関係や言語仕様の変更で被害妄想気味だった俺の思い違いかもしれないが、もしなにかあったときには最悪自分で作ればいいやレベルなので、あまり気にかけない。それにPhobosまだ開発中だからこれからよくなってくるに決まっている、きっと。個人的には、スレッドなんかは元が貧弱なので、std.c.linux.pthreadとWin32APIで、もっと強力なマルチスレッドライブラリを作ったほうがいいんじゃないかと思っているし、連想配列もスレッドセーフじゃないからマルチスレッド環境で使いやすいテンプレートライブラリを作ったほうがいいんじゃないかなんて思っている。スレッドはaprをメモリプールなしで移植するのが早いかななんて。
これらもVer1.00のおかげで安心して開発できるようになった。


そんなわけで、D言語は賢い言語マニアな人たちの遊び道具であってまじめにソフトを作ろうとする人たちの道具ではないと考え始めていた自称まじめにソフトを作ろうとする俺に残された課題はGC周りだけになった。そのGCもポエニーでえらい苦労したおかげでなんとなくどうすればいいか解ってきている。

  • パフォーマンスも考えてループ内で確保し続けるメモリはリソースプールをかます(自主管理)
  • それ以外の大きめのメモリは明示的にdeleteする
  • 特に巨大なメモリはOSのalloc/freeを使い自主管理する
  • 各スレッドで定期的にgc.fullCollectを呼ぶ(これが汚いか……)

以上。
これでDが自分でも使える言語として戻ってきた。Javaと比べてどうかというと、まだJavaのほうが信頼性があるしライブラリも充実しているから正直Javaかなーなんて思ってしまう。しかし、もしもDにJava並みのライブラリが充実してくるなら迷わずDを選ぶね。


でも、今はまだ悩む……。
君は勘違いしてる! という話があったら教えてください。