小对象优化在使用 std::function 中无用
small object optimization useless in using std::function
很多话题都告诉我们在使用std::function
时使用像lambda表达式这样的小对象可以避免堆分配。但我的研究表明并非如此。
这是我的实验代码,很简单
#include <iostream>
#include <functional>
using namespace std;
typedef std::function<int(int, int)> FUNC_PROTO;
class Test
{
public:
int Add(int x, int y) { return x + y; }
};
int main()
{
Test test;
FUNC_PROTO functor = [&test](int a, int b) {return test.Add(a, b); };
cout << functor(1, 2) << endl;
}
我是在centos7上编译的,gcc版本4.8.5 20150623
但是 valgrind 显示了这个:
==22903== HEAP SUMMARY:
==22903== in use at exit: 0 bytes in 0 blocks
==22903== total heap usage: 1 allocs, 1 frees, 8 bytes allocated
即使我删除了引用捕获,也只是一个普通的 lambda 函数。它仍然需要 1 字节的堆分配。
我做小对象优化有什么问题吗
更新:
感谢您的回复。我想我应该添加更多实验细节。
为了排除引用捕获的可能原因。我删除了捕获,代码如下:
FUNC_PROTO functor = [](int a, int b) {return a + b; };
Valgrind 显示:
==16691== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
还有 1 字节的堆分配。
我也试过这个来消除 lambda 本身的可能影响(我认为不是)
FUNC_PROTO functor = [](int a, int b) {return a + b; };
FUNC_PROTO functor2 = [](int a, int b) {return a * b; };
FUNC_PROTO test = nullptr;
for ( int i = 0; i < 10; ++i)
{
if (i % 2 == 0)
{
test = functor;
}
else
{
test = functor2;
}
}
Valgrind 显示:
==17414== total heap usage: 12 allocs, 12 frees, 12 bytes allocated
这可以证明仿函数不是完全基于堆栈的对象。
这是我的构建脚本:
g++ test.cpp -o test -std=c++11 -g -O3 -DNDEBUG
这是我的 valgrind 脚本:
valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
旧版本的 libstdc++,例如 gcc 4.8.5 发布的版本,似乎只优化函数指针而不分配(如 here 所示)。
由于 std::function
实现没有您想要的小对象优化,您将不得不使用替代实现。升级您的编译器或使用 boost::function
,这与 std::function
.
基本相同
很多话题都告诉我们在使用std::function
时使用像lambda表达式这样的小对象可以避免堆分配。但我的研究表明并非如此。
这是我的实验代码,很简单
#include <iostream>
#include <functional>
using namespace std;
typedef std::function<int(int, int)> FUNC_PROTO;
class Test
{
public:
int Add(int x, int y) { return x + y; }
};
int main()
{
Test test;
FUNC_PROTO functor = [&test](int a, int b) {return test.Add(a, b); };
cout << functor(1, 2) << endl;
}
我是在centos7上编译的,gcc版本4.8.5 20150623 但是 valgrind 显示了这个:
==22903== HEAP SUMMARY:
==22903== in use at exit: 0 bytes in 0 blocks
==22903== total heap usage: 1 allocs, 1 frees, 8 bytes allocated
即使我删除了引用捕获,也只是一个普通的 lambda 函数。它仍然需要 1 字节的堆分配。
我做小对象优化有什么问题吗
更新:
感谢您的回复。我想我应该添加更多实验细节。
为了排除引用捕获的可能原因。我删除了捕获,代码如下:
FUNC_PROTO functor = [](int a, int b) {return a + b; };
Valgrind 显示:
==16691== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
还有 1 字节的堆分配。
我也试过这个来消除 lambda 本身的可能影响(我认为不是)
FUNC_PROTO functor = [](int a, int b) {return a + b; };
FUNC_PROTO functor2 = [](int a, int b) {return a * b; };
FUNC_PROTO test = nullptr;
for ( int i = 0; i < 10; ++i)
{
if (i % 2 == 0)
{
test = functor;
}
else
{
test = functor2;
}
}
Valgrind 显示:
==17414== total heap usage: 12 allocs, 12 frees, 12 bytes allocated
这可以证明仿函数不是完全基于堆栈的对象。
这是我的构建脚本:
g++ test.cpp -o test -std=c++11 -g -O3 -DNDEBUG
这是我的 valgrind 脚本:
valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
旧版本的 libstdc++,例如 gcc 4.8.5 发布的版本,似乎只优化函数指针而不分配(如 here 所示)。
由于 std::function
实现没有您想要的小对象优化,您将不得不使用替代实现。升级您的编译器或使用 boost::function
,这与 std::function
.