malloc/newにタグを付ければよい

  • 投稿日:
  • by



かというとそうでもない気がします。


メモリ使用量の調査をするためにmalloc/newを独自バージョンに上書きして、プロセスやレイヤーごとのタグを付けて管理し、集計して眺めるという方法があります。


out of memoryになってから、あるいはヒープ不足になってから、タグごとのメモリ消費量を調べたりして。


前提条件が違えばヒープ不足となるタスクや関数の場所は毎回変わります。メモリ不足はそれが発生した部分の担当者が一次解析をすることになるわけですが、なんかおかしいですよね。


10MBのメモリを100KBしか使わないタスクが、たまたま最後の100KBを確保しようとしたときにメモリ不足になるからといって、よほど間抜けなバグでもない限りそのタスクが原因ではないので。


プロセスやタスクごとのメモリ使用量の大小ではなく、確保する順序によって、メモリ不足を発生させる箇所が変わるということです。


もちろん定期的にメモリを確保し続けるようなプロセスがあれば、そこでメモリ不足となる可能性は高くなるでしょうが、確保/解放をただしく繰り返していても、冤罪の謂れを受ける可能性が高いということです。


先の例のように100KBしか使わないタスクがあるとして、担当者は冤罪のそしりを受けて、


うちは100KBの固定長のメモリしか使用していないのに、なんでメモリリークの調査をしなきゃいけないんですか!*1




とプチ切れるのも日常的風景かと思います。しかもこの冤罪はメモリブロックにタグを付けても完全には解消できないのです。だれかが一次解析でタグごとの集計をしなければいけないので。


というわけでベタにやるならタスクやレイヤごとにmallocを独自実装して、quota制限できるようにするのがたぶん正解です。rtosによってはそういう機能が提供されています。ここでヒープはプロセスごとに別々だから、そんなのいらないという人が沸いてきます。mallocの実装(あるいはメモリ管理)についてはrtosであればマニュアルにくどいくらい説明がありますから、よく読んでから反応しないと恥をかくことになるかもしれません。


さて、そういう事情を分かっていない人がmallocやnewを直接書いてしまうと、quota制限が効かなかったりします。undefしても、勝手に#includeされておわりです。あるいは手書きのプロトタイプ宣言で回避されてしまいます。


この手の問題は、「実装ルール」やら「コーディング規約」で徹底するはずのものですが、そんなことが徹底できるなら、メモリを使いすぎる間抜けなタスクなんて発生しないわけでして。


運用的には、リンカで特定のシンボルをリンク禁止にできれば、いいんじゃないですかね。具体的にそんな方法が可能かどうかはわかりませんが。


どうせベテランさんはMakefileまでいじくってリンクを通してしまうと思います。Makefileに「使ってはいけない関数!」とかコメントしておけば、雰囲気で理解してくれるかもしれませんが。



メモリにクォータ制限をかけると何が良いかというと、あらかじめ設定した量をこえるメモリを使用したタスクやプロセスが必ずメモリ不足になるということです。タスク間通信でシステムが出来ている場合、そのタスクだけ死んでもらって再起動することも可能になります。そんな夢のようなシステムにはなかなかお目にかかれませんがね。



CPUを2個以上つんで、それぞれGPOSとRTOSを別々に動作させたりするのが、何がメリットかというと、この辺の話だったりします。それを把握していないとCPU間通信が面倒なだけに見えてしまいます。仮想化技術の応用では、メモリquotaに加えてCPUパワーのquota制御がなければメリットはないでしょうね。


メモリのquotaを独自実装すらしていないなら、CPUを2個積んでもあまり意味がないかもしれません。





*1:じゃぁmallocで確保すんなよ、と思ったりもする