我在一个论坛上听到使用std::function<>
原因导致性能下降。是真的吗 如果为真,性能会大大下降吗?
我在一个论坛上听到使用std::function<>
原因导致性能下降。是真的吗 如果为真,性能会大大下降吗?
Answers:
您可以从boost的参考资料中找到信息:通过boost :: function进行调用会产生多少开销?和表现
这不能确定增强功能的“是或否”。考虑到程序的要求,性能下降可能是可以接受的。通常,程序的某些部分不是关键性能。即使那样也可以接受。这只是您可以确定的事情。
对于标准库版本,该标准仅定义一个接口。使它起作用完全取决于各个实现。我想将使用类似的实现来增强功能。
实际上,std:function
在使用它时必须考虑到性能问题。它的主要优势(std::function
即类型擦除机制)并非免费提供,我们可能(但不一定必须)为此付出代价。
std::function
是包装可调用类型的模板类。但是,它不是可调用类型本身的参数,而是仅在其返回和参数类型上的参数。可调用类型仅在构造时才知道,因此,std::function
不能具有此类型的预先声明的成员来保存提供给其构造函数的对象的副本。
粗略地说(实际上,事情要复杂得多)std::function
只能持有指向传递给其构造函数的对象的指针,这会引起生命周期问题。如果指针指向寿命小于该对象寿命的std::function
对象,则内部指针将悬空。为防止此问题,std::function
可以通过调用operator new
(或自定义分配器)在堆上复制对象。人们最常将动态内存分配称为性能暗示std::function
。
我最近写了一篇文章,提供了更多详细信息,并说明了如何(以及在何处)避免付出内存分配的代价。
std::function
。boost::function
声明有关调用性能的信息:“使用适当的内联编译器,对函数对象的调用需要通过函数指针进行一次调用。如果该调用是对自由函数指针的调用,则必须对该函数指针进行额外的调用(除非编译器具有非常强大的过程间分析)。”
这在很大程度上取决于是否要传递不带任何参数(不分配堆空间)的函数。
还取决于其他因素,但这是主要因素。
的确,您需要比较的东西,不能简单地说,与根本不使用它相比,它“减少了开销”,您需要将它与使用替代方法传递函数进行比较。如果您完全不需要使用它,那么从一开始就不需要它
std::function
实例中,并且所传递的可调用对象在SBO的合适大小之内,则即使是绑定参数也可能不会导致动态分配。
首先,函数内部的开销变小了;工作负载越高,开销越小。
其次:与虚拟函数相比,g ++ 4.5没有任何区别:
main.cc
#include <functional>
#include <iostream>
// Interface for virtual function test.
struct Virtual {
virtual ~Virtual() {}
virtual int operator() () const = 0;
};
// Factory functions to steal g++ the insight and prevent some optimizations.
Virtual *create_virt();
std::function<int ()> create_fun();
std::function<int ()> create_fun_with_state();
// The test. Generates actual output to prevent some optimizations.
template <typename T>
int test (T const& fun) {
int ret = 0;
for (int i=0; i<1024*1024*1024; ++i) {
ret += fun();
}
return ret;
}
// Executing the tests and outputting their values to prevent some optimizations.
int main () {
{
const clock_t start = clock();
std::cout << test(*create_virt()) << '\n';
const double secs = (clock()-start) / double(CLOCKS_PER_SEC);
std::cout << "virtual: " << secs << " secs.\n";
}
{
const clock_t start = clock();
std::cout << test(create_fun()) << '\n';
const double secs = (clock()-start) / double(CLOCKS_PER_SEC);
std::cout << "std::function: " << secs << " secs.\n";
}
{
const clock_t start = clock();
std::cout << test(create_fun_with_state()) << '\n';
const double secs = (clock()-start) / double(CLOCKS_PER_SEC);
std::cout << "std::function with bindings: " << secs << " secs.\n";
}
}
隐含cc
#include <functional>
struct Virtual {
virtual ~Virtual() {}
virtual int operator() () const = 0;
};
struct Impl : Virtual {
virtual ~Impl() {}
virtual int operator() () const { return 1; }
};
Virtual *create_virt() { return new Impl; }
std::function<int ()> create_fun() {
return []() { return 1; };
}
std::function<int ()> create_fun_with_state() {
int x,y,z;
return [=]() { return 1; };
}
输出g++ --std=c++0x -O3 impl.cc main.cc && ./a.out
:
1073741824
virtual: 2.9 secs.
1073741824
std::function: 2.9 secs.
1073741824
std::function with bindings: 2.9 secs.
所以,不要害怕。如果您的设计/可维护性可以通过优先std::function
于虚拟调用而得到改善,请尝试使用它们。就个人而言,我真的很喜欢在类的客户端上不强制接口和继承的想法。
std::function
,因此该测试并非完全没有道理。
-flto
它们全部变为3.3。我的完全疯狂的猜测是,GCC实际上试图进行优化std::function
(类似于-flto
虚拟函数所获得的功能),但是这种优化实际上却有害。