使用 boost::signals2 的编译时间非常慢

Posted

技术标签:

【中文标题】使用 boost::signals2 的编译时间非常慢【英文标题】:Compile times with boost::signals2 very slow 【发布时间】:2013-08-01 21:44:33 【问题描述】:

我们有一个庞大的代码库,多年来已成功使用 boost::signals。我们最近迁移到 boost v1.54,并决定由于 boost::signals 已被弃用,我们将切换到 boost::signals2。

我们看到的问题是编译时间非常可怕。例如,一个小的 .cpp 文件现在需要 20 多秒,而过去需要 4 秒。

同样,我们的一个库(大型)过去需要大约 10 分钟才能生成,现在需要长达一个小时。我到处搜索有关如何通过预编译的头文件、宏等来改进这一点的文档,但还没有找到任何可以大大改善这种情况的东西。

在 procmon 中查看 cl.exe 会发现 boost::signals2 和 mpl 库中有大量 IO。

此时我们不需要信号2 提供的线程安全性,我们即将拔掉“升级”的插头并恢复为信号。在我们放弃之前,是否有人对此有任何建议或经验?

我们正在使用具有大量 RAM/磁盘/等的 VS2012。

【问题讨论】:

你使用的是预编译头文件吗? Signals2 使用可变参数模板,它们在 VS2012 中以高成本进行仿真。已在 VS2013 中修复。从 Boost 适应到 VS2013 登陆你的桌面,给它几个月的时间。 @HansPassant 感谢您提供的信息,我没有考虑过。鉴于我们等待 VS2013 是不可行的,您认为恢复信号库的最佳做法是什么?就像现在一样,由于编译速度慢,代码无法使用。 你已经知道答案了,问我也没用。我的建议物有所值。 您能否提供一些代码来说明您如何使用信号?我们的项目使用 boost::signals2 并且我们被困在 VS2005 上,我还没有遇到这个问题。我们正在使用预编译的头文件。 【参考方案1】:

在我从事的一个项目中,所有升压信号的使用都被压缩了,因此前向声明就足够了。这显着减少了编译时间,因为仅在实际需要时才解析信号 2 定义。该类没有提供公共的boost::signals2::signal 成员,而是有一个私有的std::unique_pointer 成员并提供了一个返回std::unique_pointer 对象的公共connectToX 函数。

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

然后变成一个只有前向声明并且不包含boost信号2头的头:

// 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;
;

对信号不感兴趣的类现在不需要解析信号2 标头。值得注意的是,根据我的经验,大部分时间不是在编译器中解析,而是在链接器中。每个使用 boost 信号的编译单元都包含许多实例化函数,这些函数会生成调试信息,最后必须由链接器消除。鉴于 MS 链接器是单线程的并且非常慢,这就是花时间做 IO 的地方。 SSD 在这里提供了很好的加速。

【讨论】:

感谢您的反馈。这是一个非常好的主意(尽管不幸的是这种舞蹈是必要的)。我们没有考虑在我们的案例中使用 pimpl,主要是因为使用非常广泛,以至于变化会很大。另一个问题是信号的客户端有时会使用 scoped_connection 范例。我们目前正在将我们的项目文件升级到 VS2013,所以我有兴趣看看上面@Hans Passant 的 cmets 是否属实。 是的,pimpl 使得使用信号变得相当复杂,特别是因为您必须返回 unique_ptrs 与连接。我对 VS2013 的结果非常感兴趣,尽管我目前不在 Windows 平台上工作。我不会期望有太大的改进,因为链接器没有得到很大的改进,这就是我们花费构建时间的地方(以及编写具有大量增强信号实例化的 pdb 文件)。您可以使用 cl /Bt+ 或 link /time+ 来获取一些构建时间测量值。

以上是关于使用 boost::signals2 的编译时间非常慢的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 boost::signals2 存储和转发插槽?

如何比较 boost::signals2 中的插槽类型

从 boost::signals2 安全断开

boost--signal

boost::signals2::signal 输出错误?

在地图中存储 boost::signals2 信号?