2020年5月26日火曜日

AWS Lambda-メモリリーク対策C++

設計を大幅に変更しました。行数にして数千行程度、Editしたと思います。

サーバアプリでは、基本的にメモリリークは許されません。が、Lambdaは、毎回HotStartする訳でもないので、目標として、一回のメモリリークは、100KB程度以下としました。(1000回連続HotStartされても100MBの増加に留まる、としました。) 1000回連続で来ることはないという想定です。これが崩れることがあるとするなら、同じLambdaを複数用意すれば事足ります。

<メモリリーク対策の為の設計変更>
次の対策方法を検討しました。

A)shared_ptrの使用
shared_ptrの場合、unionで、ptrを複数定義している部分の回避が面倒。(一応C+11なら書けそうですが..) さらに、performanceの劣化、メモリ増大が懸念されます。さらに、困難なのは変更Edit量が半端ないことです。

B)独自アロケータの使用
shared_ptr使用の場合に比べて、全ての面で優れています。union ptrの変更の必要はありませんし、変更Edit量も最小で済みます。
関連するクラス(ptr参照しているクラス)は、10種以下なので、それら全てを独自アロケータを使って処理します。つまり、delete処理は、最後の一回のみです。ptrを辿ってdeleteしていくことはしません。ですのでクラスのnew ptrは、管理しません。その結果、クラス内のstd::vectorにも細工が必要になります。幸い、std::vectorは、アロケータインタフェースが定義されているので、それらを含めて関連クラスのdelete処理を一気に行う処理が書けます。shared_ptrで、ちまちま参照カウントする方式に比べて速度で10倍くらい違う気がします。(しかし、ここは、ボトルネックではないので、体感では変わりません。)

 


<メモリリーク対策検証>
1)VisualC++内蔵ヒープチェック
メモリリークをEnableします。_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); また、リンカーのDebugを 共有と公開用に最適化されたデバッグ情報の生成 (/DEBUG:FULL)に設定します。(なぜか、デバッグ出力が全くされなかったのでが、VisualStudioの修復 を行ったらデバッグ出力が出るようになりました。)

2)VisualLeakDetectorの活用
1)では、ソース行が殆ど表示されないので分かりずらいです。格段に遅くはなりますが、デバッグ初期は、VisualLeakDetectorを使いました。スタックトレースまで表示されるので、場所の特定は容易です。しかし、ある程度以上の規模になると原因不明のエラーが出ることがありました。そのときは、VisualC++のヒープチェックに頼ることになります。

3)検証
■Windows: VisualC++/Visual Leak Detectorによる検証
■Linux:         g++ -fsanitize=leak による検証
■mainを何回か廻して、取得メモリ量に変化ないことを確認(ptrのリセット処理等検証)

4)メモリリーク箇所
■旧言語制約は、deprecatedで基本使用禁止とします。なので放置です。
■algorithm4 これもAWSではサポートしません。なので放置です。
■python インタフェース: 最新版で少し改善しましたが、僅かに未だ残っているようです。こちらは、改版に期待ということで、放置しています。
■Error 解がなかった場合、原因解析処理でメモリリークします。課題です。
■未検証 TASK周り

5)Tips
 ■Windowsは、OKで、LinuxでNGな箇所がありました。g++ stringstream.str()に要注意です。
 ■new vector<...> を vector<> 形式にして、出来る限りスタック上で自動deleteとするように書き換えました。地道な作業ですが、普段から、明示deleteしなくてもよい書き方を意識して書くべきだったと、反省しています。

<結論>
■従い、Algorithm1で、pythonを使わずに,解があるのであれば、メモリリークはありません。
■pythonを使った場合、記述量に関係なく、constantに1KB以下程度がリークします。1000回呼んで1MB以下です。しかし、解がなかったときの原因解析でリークが発生します。この部分が課題です。
■大幅にいじってしまったので、regression test が必要です。







0 件のコメント:

コメントを投稿