5

Vista/Windows Server 2008 でクリティカル セクションをかなり使用すると、OS がメモリを完全に回復しないようです。Delphi アプリケーションでこの問題が見つかりましたが、これは明らかに CS API を使用しているためです。(このSOの質問を参照してください)

他の言語 (C++ など) で開発されたアプリケーションでそれを見た人はいますか?

サンプル コードは、10000000 CS を初期化してから削除するだけでした。これは XP/Win2003 では問題なく動作しますが、Vista/Win2008 ではアプリケーションが終了するまでピーク メモリをすべて解放しません。
CS を使用すればするほど、アプリケーションは無駄にメモリを保持します。

4

3 に答える 3

7

Microsoft は実際に、InitializeCriticalSectionVista、Windows Server 2008、そしておそらく Windows 7 での動作方法を変更し
ました。一連の CS を割り当てるときに、デバッグ情報に使用されるメモリを保持する「機能」を追加しました。より多く割り当てるほど、より多くのメモリが保持されます。それは漸近的であり、最終的には横ばいになる可能性があります (完全に購入されたわけではありません)。
この「機能」を回避するには、新しい API InitalizeCriticalSectionExを使用してフラグを渡す必要がありCRITICAL_SECTION_NO_DEBUG_INFOます。
これの利点は、多くの場合、実際に待機することなくスピンカウントのみが使用されるため、高速になる可能性があることです。
欠点は、古いアプリケーションに互換性がない可能性があることです、コードを変更する必要があり、現在はプラットフォームに依存しています (使用するバージョンを決定するには、バージョンを確認する必要があります)。また、必要に応じてデバッグすることもできなくなります。

Windows Server 2008 をフリーズするためのテスト キット:
- この C++ の例を CSTest.exe としてビルドします。

#include "stdafx.h" 
#include "windows.h" 
#include <iostream> 

using namespace std; 

void TestCriticalSections() 
{ 
  const unsigned int CS_MAX = 5000000; 
  CRITICAL_SECTION* csArray = new CRITICAL_SECTION[CS_MAX];  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    InitializeCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    EnterCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    LeaveCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    DeleteCriticalSection(&csArray[i]); 

  delete [] csArray; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
  TestCriticalSections(); 

  cout << "just hanging around..."; 
  cin.get(); 

  return 0; 
}

-...このバッチ ファイルを実行します (サーバー SDK の sleep.exe が必要です)。

@rem you may adapt the sleep delay depending on speed and # of CPUs 
@rem sleep 2 on a duo-core 4GB. sleep 1 on a 4CPU 8GB. 

@for /L %%i in (1,1,300) do @echo %%i & @start /min CSTest.exe & @sleep 1 
@echo still alive? 
@pause 
@taskkill /im cstest.* /f

-...そして、起動された 300 のインスタンスに到達する前に、8GB およびクアッド CPU コアを備えた Win2008 サーバーがフリーズするのを確認します。
-...Windows 2003 サーバーで繰り返し、それが魅力的に処理されることを確認します。

于 2009-05-20T19:42:25.690 に答える
2

あなたのテストはおそらく問題を代表していません。クリティカル セクションは、クリティカル セクションを初期化するときに実際のカーネル ミューテックスが作成されないため、「軽量ミューテックス」と見なされます。これは、1,000 万のクリティカル セクションが、いくつかの単純なメンバーを含む単なる構造体であることを意味します。ただし、2 つのスレッドが同時に CS にアクセスすると、それらを同期するためにミューテックスが実際に作成されます。これは別の話です。

テストアプリとは対照的に、実際のアプリスレッドは衝突すると思います。ここで、実際にクリティカル セクションを軽量ミューテックスとして扱い、それらを多数作成している場合、アプリは多数の実際のカーネル ミューテックスを割り当てている可能性があります。これは、軽量クリティカル セクション オブジェクトよりもはるかに重いものです。また、ミューテックスはカーネル オブジェクトであるため、過剰な数のミューテックスを作成すると、OS に深刻なダメージを与える可能性があります。

これが実際に当てはまる場合は、多くの衝突が予想されるクリティカル セクションの使用を減らす必要があります。これは Windows のバージョンとは関係がないため、私の推測は間違っているかもしれませんが、それでも考慮すべき点です。OS ハンドル数を監視して、アプリの動作を確認してください。

于 2009-04-30T08:31:20.033 に答える