C++ VS2012“;“生成代码”;使用大型硬编码阵列时速度较慢

C++ VS2012“;“生成代码”;使用大型硬编码阵列时速度较慢,c++,arrays,performance,visual-studio-2012,C++,Arrays,Performance,Visual Studio 2012,我们有一个工具,可以在头文件中生成一个类,头文件是用硬编码数组生成的。自动生成的值由使用自动生成值的实际实现继承 自动生成的示例: class MyTestAutoGen { std::vector<int> m_my_parameter1; std::vector<int> m_my_parameter2; ... public: MyTestAutoGen() { SetDefaultValueFor_

我们有一个工具,可以在头文件中生成一个类,头文件是用硬编码数组生成的。自动生成的值由使用自动生成值的实际实现继承

自动生成的示例:

class MyTestAutoGen
{
    std::vector<int> m_my_parameter1;
    std::vector<int> m_my_parameter2;
    ...

public:
    MyTestAutoGen()    
    {
        SetDefaultValueFor_my_parameter1();
        SetDefaultValueFor_my_parameter2();
        ...
    }

    void SetDefaultValueFor_my_parameter1()
    {
        int tmp[] = {121,221,333,411,225,556,227,.......};
        m_my_parameter1.assign(tmp, tmp + 65025);
    }

    void SetDefaultValueFor_my_parameter2()
    {
        int tmp[] = {333,444,333,987,327,16728,227,.......};
        m_my_parameter2.assign(tmp, tmp + 65025);
    }

    ...
 };
类MyTestAutoGen
{
std::向量m_my_参数1;
std::向量m_my_参数2;
...
公众:
MyTestAutoGen()
{
设置_my_参数1()的默认值;
设置_my_参数2()的默认值;
...
}
void SetDefaultValueFor_my_参数1()
{
int tmp[]={121221334111225556227,…};
m_my_参数1.分配(tmp,tmp+65025);
}
void SetDefaultValueFor_my_参数2()
{
int tmp[]={33344433398732716728227,…};
m_my_参数2.分配(tmp,tmp+65025);
}
...
};
编译这需要很多时间,在VS的输出窗口中,我可以看到它挂起在编译的“生成代码”阶段,但它将在大约15-30分钟后完成编译,除非编译器因堆栈溢出而崩溃

我曾尝试启用“多处理编译”和“并行代码生成”标志,但没有显示任何改进。禁用“整个程序优化”不是一个选项,因为在应用程序初始化之后,它应该尽可能执行优化

我解决这个问题的方法是修改自动生成的模板,将值保存在编码的二进制字符串中,这样数据可能会存储在库/可执行文件的文本区域而不是静态区域。现在,自动生成的代码如下所示(字符串十六进制值仅用于显示):

类MyTestAutoGen
{
std::向量m_my_参数1;
std::向量m_my_参数2;
...
公众:
MyTestAutoGen()
{
设置_my_参数1()的默认值;
设置_my_参数2()的默认值;
...
}
void SetDefaultValueFor_my_参数1()
{
std::string codedDefaultValue=“\x079\0\0\0…”;
std::stringstream str(codedDefaultValue);
int tmp;
对于(int i=0;i
该文件编译速度快,但不易读取(不应手动编辑此文件,也不应仔细查看)


有没有更好的方法来做到这一点,而不破坏它作为跨平台,不禁用优化和保持它的头文件

我的直觉是,您正在堆栈上推送一个未指定大小的大数组。因为堆栈缓冲区溢出是一个特别的安全问题。MSVC对他们很小心。但是在堆栈上使用该数组没有意义

相反,在全局范围内执行

const int count = 65025;
int param1_initializer[count] = {121,221,333,411,225,556,227, ... }
请注意,您已经对数组长度进行了硬编码,因此强烈建议给编译器一个检查的机会。此外,这使编译器更容易知道需要多少初始值设定项,因此compiel时间也可能会受益

[编辑]
因为这还不够,而且我们知道我们正在使用MSVC,所以请使用
#pragma optimize
关闭所有数组定义的优化。无论如何,它们都不可能被优化。

如果必须保留解决方法:为了提高可读性,您可能需要提取解码字符串的函数

void fill(std::vector<int>& dest, const std::string& src)
{
  std::stringstream str(src);
  const size_t size = src.length() / sizeof(int);
  int tmp;
  dest.clear();
  dest.reserve(size);
  for (int i = 0; i < size; i++)
  {
    str.read((char*) &tmp, sizeof(int));
    dest.push_back(tmp);
  }
}

void SetDefaultValueFor_my_parameter1()
{
  fill(m_my_parameter1, "\x079\0\0\0.......");
}
void fill(std::vector和dest,const std::string和src)
{
std::stringstream str(src);
const size\u t size=src.length()/sizeof(int);
int tmp;
目标清除();
目的地储备(规模);
对于(int i=0;i
看起来自动生成的数字应该是常量。这用静态常数表示:

static const int tmp[] = {121,221,333,411,225,556,227,.......};
对于“大型”数组,有一条模糊的规则,即不应使用自动存储(即正常的局部变量);改为使用
静态
(或者,使用动态分配,但此处不需要)。此外,由于您的号码不会更改,请也使用
const


顺便说一句,打破这个“规则”会影响编译时间,这是相当令人惊讶的

为什么不能禁用LTO?我认为,如果开发可执行文件没有那么快,那也没关系,在开发阶段,快速编译更重要。您仍然可以在产品构建中使用LTO。其他开发人员正在使用此autogen文件,他们需要在运行时测试“繁重”的实现,因此对他们来说,它既是开发又是生产。创建2个构建配置(带和不带)对所有相关方来说都会很麻烦。为什么必须将其保存在头文件中?您不能在@TripeHound中自动生成带有
SetDefaultValueFor_my_参数1
定义的CPP文件吗?@TripeHound我在单个文件中执行此操作以简化外部集成。我曾尝试将代码手动提取到cpp文件并将其添加到项目中,但这对速度没有任何影响“我们有一个在头文件中生成类的工具”,您可以使用直接生成目标文件的工具。感谢您指出这一点。我曾尝试修改代码生成器,以按照您的建议生成代码,但编译时间仍然很长,尽管所需时间比以前少
static const int tmp[] = {121,221,333,411,225,556,227,.......};