关于 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
.人家叫你测量。
你做到了,在这种情况下,我们假设你发现分支似乎更快。伟大的!所以我们应该开始到处使用分支,对吧?
不是真的,因为你的分支预测器很可能使代码有效地释放(分支从未被采用),这意味着你甚至根本没有比较分支与间接调用。
哪个最有效:使用空对象,或 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
.人家叫你测量。
你做到了,在这种情况下,我们假设你发现分支似乎更快。伟大的!所以我们应该开始到处使用分支,对吧?
不是真的,因为你的分支预测器很可能使代码有效地释放(分支从未被采用),这意味着你甚至根本没有比较分支与间接调用。