Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile times with boost::signals2 very slow

We have a large codebase which has successfully used boost::signals for years. We recently moved to boost v1.54 and decided that since boost::signals was deprecated we would switch to boost::signals2.

The issue we are seeing is that compile times are horrendous. For example, a small .cpp file will now take 20+ seconds where it used to take 4.

Similarly, one of our libraries (large) that used to take roughly 10 minutes to generate now takes up to an hour. I have searched all around for documentation on how to improve this through precompiled headers, macros, etc but have yet to find anything that improves the situation greatly.

Viewing cl.exe in procmon reveals a massive amount of IO into the boost::signals2 and mpl libraries.

We don't need the thread safety that signals2 provides at at this point we are close to pulling the plug on the 'upgrade' and reverting back to signals. Does anyone have any suggestions or experience with this before we give up?

We are using VS2012 with plenty of RAM/disk/etc.

like image 722
pennyowe Avatar asked Aug 01 '13 21:08

pennyowe


1 Answers

In a project I worked on, all boost signals usages were pimpled such that forward declarations are sufficient. This reduces compile time significantly as the signals2 definitions are only parsed when actually needed. Instead of providing a public boost::signals2::signal member, the class has a private std::unique_pointer member and provides a public connectToX function which returns a std::unique_pointer object.

class Subject {
public:
    boost::signals2::signal<void (int)> valueChanged;
    void setValue(int x) {
        valueChanged(x);
    }
};

class A {
public:
    A(Subject& subject): conn( subject.sig.connect( [&](int x) {this->onChange(x);} ) {}
    ~A() {conn.disconnect();}
private:
    void onChange(x) {}

    boost::signals2::connection conn;
};

then becomes a header with only forward declarations and no includes of boost signals2 headers:

// Header file
class Subject {
public:
    std::unique_ptr<boost::signals2::connection> connect(std::function<void (int)> observer);

private:
    class Impl;
    std::unique_ptr<Impl> mImpl;
};

Classes not interested in signals now do not need to parse signals2 headers. It is worth noting that in my experience most time is not spent parsing in the compiler, but in the linker. every compilation unit using boost signals contains a lot of instantiated functions which generate debug information and have to be eliminated by the linker at the end. And given that the MS linker is single-threaded and really slow, this is where the time is spent doing IO. A SSD provided a nice speed-up here.

like image 103
Jens Avatar answered Oct 18 '22 23:10

Jens