2

クイックフィックス(1.13.3)の下でブーストの fast_pool_allocator (バージョン 1.55) を使用する高度にスレッド化されたアプリケーションがあります。アプリケーションは 1 日の間に多数のオブジェクトを割り当て、シャットダウンするまで多かれ少なかれ直線的に増加し、1 日の終わりまでに 32G 程度の仮想メモリを使用します。アプリケーションの仮想メモリ フットプリントが増大するのを見ると、ほとんどの割り当ては 200MB 程度です。しかし、通常はその日の後半のある時点で、アプリケーションを介したトランザクションの流れが実質的に変化していなくても、boost は 6GB の割り当てを行うことを決定します。

アロケーターのコードを見ると、割り当て後に最初にブーストが行われ、新しいブロックがチャンクに設定されます。関数はsimple_segregated_storage<SizeType>::segregatesimple_segregated_storage.hpp:280 にあります。デバッガーをプロセスにアタッチし、巨大な割り当てが発生すると、その関数の実行に (当然のことながら) 長い時間がかかることを観察しました。具体的には、302 行目の for ループです。20 ~ 30 秒かかり、そのコードはミューテックスで保護されているため、アロケーターで何かをしようとする他のすべてのスレッドがブロックされます。これはお客様を怒らせます。

質問:

  1. その前に 1 日中常に ~200MB のブロックを要求していたのに、突然 6GB を割り当てたのはなぜですか?
  2. 割り当てを何らかの方法で制限できますか? 小さいピースをもっと頻繁に求めてもらいたいです。
  3. これは間違ったアロケーターですか?これはクイックフィックスの開発者に対する質問だと思いますが、これが彼らの好む方法のようです。アロケータを使用するオブジェクトは、主にstd::mapstd::multimapです。
4

1 に答える 1

1

上で Yakk が提案したように、ブースト プールを使用すると、テンプレートで MaxSize を指定できることがわかりました。プールの実装の内部概念である「チャンク」の単位で動作するという点で少し奇妙です。IMHOバイトの方が自然だったでしょうが、そうです。

fast_pool_allocatorすべてのテンプレート引数 (最初の引数を除く) のデフォルト値で定義されています。これらのデフォルトをコピーし、最後のものを変更しました。このアプリケーションの場合、チャンク サイズは 88 バイトですが、これはマップ内のクラスに依存していると思います。

typedef std::map <int, std::vector <FieldMap*>, std::less<int>, 
                  boost::fast_pool_allocator<std::pair<const int, std::vector<FieldMap*>>,
                                             boost::default_user_allocator_new_delete,
                                             boost::details::pool::default_mutex,
                                             32,       // NextSize (default from boost)
                                             1500000   // MaxSize, in 88 byte chunks.
                                            >> Groups;

この場合、1500000 * 88 = 132M で、現時点で割り当てを希望する大きさとほぼ同じです。

于 2015-01-26T20:44:42.973 に答える