Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS2012 "Generating Code" slow with large hardcoded arrays

We have a tool that generates a class in a header file which is generated with hardcoded arrays. That autogenerated is inherited by a real implementation which uses the autogenerated values.

Autogenerated example:

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);
    }

    ...
 };

Compiling this takes a lot of time and in the Output windows of VS I can see that it hangs on the "Generating Code" phase of the compilation, but it will finish the compile after about 15-30min unless the compiler crashes with a stack overflow.

I have tried to enable the "Multiprocessing Compilation" and the "Parallel Code Generation" flags but it did not show any improvements. Disabling the "Whole Program Optimization" is not an option as after the application initialization it should perform as optimized as possible.

My workaround to this issue was to modify the autogenerated template to save the values in encoded binary string so that maybe the data will be stored in the TEXT area instead of the STATIC area of the library/executable. So now the autogenerated code looks like (the stringed hex values are just for show):

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()
    {
        std::string codedDefaultValue = "\x079\0\0\0.......";
        std::stringstream str(codedDefaultValue);

        int tmp;
        for (int i = 0; i < codedDefaultValue.length() / sizeof(int); i++)
        {
            str.read((char*) &tmp, sizeof(int));
            m_my_parameter1.push_back(tmp);
        }
    }

    void SetDefaultValueFor_my_parameter2()
    {
        std::string codedDefaultValue = "\x04d\x001.......";
        std::stringstream str(codedDefaultValue);

        int tmp;
        for (int i = 0; i < codedDefaultValue.length() / sizeof(int); i++)
        {
            str.read((char*) &tmp, sizeof(int));
            m_my_parameter2.push_back(tmp);
        }
    }

    ...
 };

This compiles fast but is not easily readable (this file should not be edited manually and is not causally looked at).

Is there a better way to do this without breaking it as cross-platform, without disabling optimizations and keeping it a header file?

like image 423
damagedspline Avatar asked Mar 14 '23 17:03

damagedspline


1 Answers

It looks like your auto-generated numbers are meant to be constant. This is expressed by static const:

static const int tmp[] = {121,221,333,411,225,556,227,.......};

There is a vague rule that for "large" arrays, automatic storage (i.e. normal local variables) should not be used; use static instead (alternatively, use dynamic allocation, but this is not needed here). In addition, since your numbers will not be changed, use const too.

BTW it's pretty surprising that breaking this "rule" affects compilation time!

like image 60
anatolyg Avatar answered Mar 24 '23 08:03

anatolyg