web-dev-qa-db-ja.com

std :: unordered_mapのメモリ使用量を測定する方法

std::unordered_mapは大量のメモリを使用します のようなハッシュテーブルベースのコンテナ実装は知っていますが、いくらかわかりません。

スペースの複雑さの表記とは別に、コンテナ要素がより大きなオブジェクトへのポインタであるかどうかを考慮していません。

実行時にそのようなコンテナによって使用されているバイトの数を把握する方法はありますか?

実行時に、コンテナが使用しているメモリanyの量を知る方法はありますか?

17
rahman

大まかなサイズを取得したい場合は、bucket_count()max_load_factor()で十分だと思います。これにより、バケットの現在の数と負荷率がわかります。

合理的な:

  • _load_factor_ <= 1の場合、それはbucket_count()> =マップ内のアイテムを示し、bucket_count()はメモリ使用量のサイズです。

  • _load_factor_> 1の場合、bucket_count() * _load_factor_はマップ内の最大アイテムを示します。これは最大サイズであり、実際のサイズではないことに注意してください。

したがって、大まかなメモリ使用量は次のようになります。

_  unsigned n = mymap.bucket_count();
  float m = mymap.max_load_factor();
  if (m > 1.0) {
    return n * m;
  }
  else {
    return n;
  }
_

正確なメモリ使用量を取得したい場合は、すべてのバケットをカウントして、その中の要素の数を確認する必要があります。

_  size_t count = 0;
  for (unsigned i = 0; i < mymap.bucket_count(); ++i) {
    size_t bucket_size = mymap.bucket_size(i);
    if (bucket_size == 0) {
      count++;
    }
    else {
      count += bucket_size;
    }
  }
_
8
Mine

使用中のバイト数を知るための移植可能な方法はありません。あなたが見つけることができるのは:

  • size()は、コンテナに挿入されたデータ要素の数を示します
  • bucket_count()は、基になるハッシュテーブルに含まれるバケットの数を示します。各バケットは、関連する要素へのリンクリストをホストすることが期待できます。

今:

  • 要素の保存に実際に使用されるバイトはm.size() * sizeof(M::value_type)になります

  • ハッシュテーブルバケットに使用されるバイトは、内部リストの格納方法によって異なります-_std::unordered_map::bucket_size_は一定の複雑さを持っているため、バケットごとにsize()とヘッドポインタがあると合理的に推測できます。 m.bucket_count() * (sizeof(size_t) + sizeof(void*))は妥当な推測ですが、load_factor()が制限されており、sizeが格納されていないため、定数償却複雑さしかない場合があります。バケットごと(自分でこの方法で実装したい)

  • 挿入された各要素がリストの一部である場合、それらにはnextポインターが必要になるため、別のm.size() * sizeof(void*)を追加できます。

  • 各メモリ割り当てmayメモリ割り当てライブラリの管理に便利なサイズに切り上げられます-例:次の2の累乗は、100%の最悪の場合の非効率性と50%の平均に近づきます。したがって、バケットは_size_t_とポインターが与えられた2の累乗である可能性が高いため、リストノードについてのみ50%を追加しましょう:50%* size() * (sizeof(void*) + sizeof((M::value_type))

  • 特にデバッグモードでは、実装固有のハウスキーピングおよびエラー検出データがいくらでも存在する可能性があります

多数の大きなテーブルを作成し、topまたはProcessManagerがさまざまなメモリ使用量をどのように報告するかを確認することで、これをさらに詳しく調べることができます。

15
Tony Delroy