关于 null 与 null 对象性能的分支

Branch on null vs null object performance

哪个最有效:使用空对象,或 nullptr 上的分支。 C++ 中的示例:

void (*callback)() = [](){}; // Could be a class member

void doDoStuff()
    {
    // Some code
    callback();  // Always OK. Defaults to nop
    // More code
    }

void (*callback)() = nullptr; // Could be a class member

void doDoStuff()
    {
    // Some code
    if(callback != nullptr)  // Check if we should do something or not
        {callback();}
    // More code
    }

null 对象将始终进行间接函数调用,假设编译器无法内联它。使用nullptr,总会​​做branch,如果有事做,也会做间接函数调用。

将回调替换为指向抽象基的指针 class 会影响决策吗?

callback 设置为 nullptr 以外的东西的可能性如何。我想如果 callback 很可能是 nullptr,那么使用附加分支会更快,对吗?

您必须测试代码并找出答案

如果不进行测试,根本无法确定此代码是更快还是更慢——并且该测试的结果可能不适用于您的特定应用程序或环境,即使测试具有相同的编译器和目标作为您的构建。

编译器非常擅长优化代码,尤其是在半可预测的行为方面,并且 CPU 通常使用分支预测或其他类似技术构建,以降低必须分支代码的成本。因此,答案完全取决于代码的具体用例、代码的目标设备以及代码的运行条件。

None 这些问题可以先验回答。它们将取决于无数因素,包括但不限于硬件的细节、调用时缓存的细节、围绕此类调用的各种代码(可能隐藏任何引入的延迟)、质量编译器的 inlining/devirtualization 能力(同样取决于所有代码的具体细节)等等。

只有当您拥有要优化的确切代码,以及某些知识所讨论的代码是性能问题时,才应尝试进行此类微优化值得这样的优化。

Which is most efficient: using a null object, or a branch on nullptr.

假设给定的代码生成解决方案,它将取决于您的目标。而且,如果你不假设,它也将取决于你的代码、编译器和可能的月相。

Would replacing callback with a pointer to an abstract base class affect the decision?

在大多数情况下,最终也是动态调度。

What about the likelihood of callback set to something other than nullptr. I guess that if callback is most likely nullptr, then it is faster with the additional branch, right?

这取决于比率和硬件(与间接函数调用相比,分支是否更快;这也取决于比率)。


只是为了让您了解事情的微妙之处:假设您正在谈论现代 x86_64 桌面处理器,其中调用未被内联并且可能有 99% 的时间 nullptr.人家叫你测量。

你做到了,在这种情况下,我们假设你发现分支似乎更快。伟大的!所以我们应该开始到处使用分支,对吧?

不是真的,因为你的分支预测器很可能使代码有效地释放(分支从未被采用),这意味着你甚至根本没有比较分支与间接调用。