10

前処理ツールによって生成され、プロジェクトにコンパイルされたいくつかの大きな静的データ テーブル (構造体の配列) がある C++ プロジェクトがあります。今まで VC++ 2008 を使用していましたが、2010 に移行する準備をしていて、これらのデータ テーブルのコンパイルに突然非常に長い時間がかかっています。

例として、そのようなテーブルの 1 つには約 3,000 のエントリがあり、それぞれがいくつかの int とポインタを含む構造体であり、すべて静的に初期化されています。この 1 つのファイルは、VC++ 2008 ではコンパイルに約 15 秒かかりましたが、VC++ 2010 では 30分かかります!

実験として、このテーブルを 8 つのテーブルに均等に分割し、それぞれを独自の .cpp ファイルに分割してみました。それぞれ 20 ~ 30 秒でコンパイルされます。これは、コンパイラ内の何かがこれらのテーブルの長さで O(n^2) であると私に思わせます。

cl.exe のメモリ使用量は約 400 MB で横ばいになり (私のマシンには 12 GB の RAM が搭載されています)、いったん横ばいになると I/O アクティビティが見られないため、これはディスク キャッシュの問題ではないと思います。

ここで何が起こっているのか誰にも分かりますか? 正常なコンパイル時間に戻すために無効にできるコンパイラ機能はありますか?

以下は、テーブル内のデータのサンプルです。

//  cid (0 = 0x0)
{
    OID_cid,
    OTYP_Cid,
    0 | FOPTI_GetFn,
    NULL,
    0,
    NULL,
    (PFNGET_VOID) static_cast<PFNGET_CID>(&CBasic::Cid),
    NULL,
    CID_Basic,
    "cid",
    OID_Identity,
    0,
    NULL,
},

//  IS_DERIVED_FROM (1 = 0x1)
{
    OID_IS_DERIVED_FROM,
    OTYP_Bool,
    0 | FOPTI_Fn,
    COptThunkMgr::ThunkOptBasicIS_DERIVED_FROM,
    false,
    NULL,
    NULL,
    NULL,
    CID_Basic,
    "IS_DERIVED_FROM",
    OID_Nil,
    0,
    &COptionInfoMgr::s_aFnsig[0],
},

//  FIRE_TRIGGER_EVENT (2 = 0x2)
{
    OID_FIRE_TRIGGER_EVENT,
    OTYP_Void,
    0 | FOPTI_Fn,
    COptThunkMgr::ThunkOptBasicFIRE_TRIGGER_EVENT,
    false,
    NULL,
    NULL,
    NULL,
    CID_Basic,
    "FIRE_TRIGGER_EVENT",
    OID_Nil,
    0,
    NULL,
},

//  FIRE_UNTRIGGER_EVENT (3 = 0x3)
{
    OID_FIRE_UNTRIGGER_EVENT,
    OTYP_Void,
    0 | FOPTI_Fn,
    COptThunkMgr::ThunkOptBasicFIRE_UNTRIGGER_EVENT,
    false,
    NULL,
    NULL,
    NULL,
    CID_Basic,
    "FIRE_UNTRIGGER_EVENT",
    OID_Nil,
    0,
    NULL,
},

ご覧のとおり、さまざまな int と enum に加えて、いくつかのリテラル文字列、関数ポインター、および他の静的データ テーブルへのポインターが含まれています。

4

5 に答える 5

6

N^2 になっているオプティマイザーの場合は、このファイルのすべての最適化をオフにする価値があるかもしれません (とにかく何も購入することはありません)。

于 2011-10-25T20:54:27.867 に答える
5

私はこれとまったく同じ問題を抱えていました。約 40'000 要素を持つデータの const 配列がありました。コンパイル時間は約 15 秒でした。「const uint8_t pData[] = { ... }」から「static const uint8_t pData[] = { ... }」に変更すると、コンパイル時間が 1 秒未満になりました。

于 2013-07-09T07:44:44.353 に答える
1

C /C++設定でPureMISLCLRサポートをオフにしてみることができます。私のために働いた。

于 2011-11-11T04:40:02.537 に答える
1

大きな静的データをオブジェクトファイルに直接変換する手法を見てきました(どこにあるのか思い出せません)。次に、C ++コードは配列をとして宣言しextern、リンカーは2つを一致させます。そうすれば、配列データはコンパイルステップをまったく受けません。

Microsoft C / C ++ツールCVTRES.exeは同様の原則で機能しましたが、シンボルは生成されませんでしたが、アクセスするために特別なAPIを必要とする別のリソースセクション(、、、FindResource)。LoadResourceLockResource

ああ、これが私が見つけたことを思い出したツールの1つです:bin2coff 著者は関連するツールをたくさん持っています


または、依存関係を減らして、特定のソースファイルを再コンパイルする必要がないようにすることもできます。次に、最小限の再構築で既存の.objファイルが自動的に使用されます。たぶん、その.objファイルをソース管理にチェックインすることさえできます。

于 2011-10-25T18:20:01.860 に答える
0

配列を static const にするようにしてください。これにより、コンパイル時間が短縮されます (ただし、ファイルサイズは短縮されません)。

于 2012-05-11T08:41:02.110 に答える