C++:几种callable实现方式的性能对比
C++中几种callable实现方式的性能对比
前言
C++中想实现一个callable的对象,通常有四种方式:
std::function:最common的方式,一般会配合std::bind使用。- function pointer:最C的方式,但没办法实现有状态的callable object。
 - function object:就是重载了
operator()的类,C++98的STL中经常用。 - lambda expression:不会污染namespace,一般来说编译器内部会实现为一个匿名的function object。
 
从原理上性能最好的应该是3和4,其次是2,最差的是std::function。下面我们用一小段代码来测试它们的性能。
测试结果
- 测试机器:15' rMBP。
 - 编译器:Apple LLVM version 8.1.0 (clang-802.0.42)。
 - 编译方式:g++ test.cpp -std=c++14 -O2。
 
./a.out "std::function"  0.15s user 0.20s system 98% cpu 0.358 total
./a.out "function_pointer"  0.10s user 0.11s system 98% cpu 0.209 total
./a.out "function_object"  0.03s user 0.01s system 92% cpu 0.042 total
./a.out "lambda"  0.03s user 0.01s system 93% cpu 0.042 total
可以看到3和4只要42ms,而相对应的2需要209ms,1需要358ms。这个顺序符合我们的预期,但相差这么多还是比较意外的。
测试程序
#include <iostream>
#include <functional>
#include <vector>
#include <string>
#include <utility>
using namespace std;
template <typename HandlerT = std::function<void (int)>>
class Worker{
public:
    explicit Worker(const HandlerT& handler): mHandler(handler) {}
    void Run(int x) {
        mHandler(x);
    }
private:
    HandlerT mHandler;
};
template <typename HandlerT>
void Test(HandlerT&& h) {
    using WorkerT = Worker<HandlerT>;
    vector<WorkerT> v;
    for (int i = 0; i < 10000000; ++i) {
        v.emplace_back(std::forward<HandlerT>(h));
    }
    int j = 0;
    for (auto& w: v) {
        w.Run(++j);
    }
}
void Func(int x) {
    int y = x + 5;
    y += 3;
}
struct Functor {
    void operator()(int x) const {
        int y = x + 5;
        y += 3;
    }
};
int main(int argc, char** argv) {
    if (argc != 2) {
        cerr << "error input" << endl;
        exit(1);
    }
    string mode{argv[1]};
    if (mode == "std::function") {
        Test(bind(Func, placeholders::_1));
    } else if (mode == "function_pointer") {
        Test(Func);
    } else if (mode == "function_object") {
        Test(Functor{});
    } else if (mode == "lambda") {
        Test([](int x) -> void {int y = x + 5; y += 3;});
    } else {
        cerr << "error mode:" << mode << endl;
        exit(1);
    }
}
												
											C++:几种callable实现方式的性能对比的更多相关文章
- ArrayList和LinkedList的几种循环遍历方式及性能对比分析
		
最新最准确内容建议直接访问原文:ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性 ...
 - Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]
		
Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...
 - ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)
		
主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...
 - ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转载)
		
原文地址: http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 原文地址: http://www.trinea.cn ...
 - 【转】ArrayList和LinkedList的几种循环遍历方式及性能对比分析
		
原文网址:http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 主要介绍ArrayList和LinkedList这两种 ...
 - (转)ArrayList和LinkedList的几种循环遍历方式及性能对比分析
		
主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...
 - python中两种栈实现方式的性能对比
		
在计算机的世界中,同一个问题,使用不同的数据结构和算法实现,所使用的资源有很大差别 为了方便量化python中算法的资源消耗,对性能做测试非常有必要,这里针对stack做了python语言 下的性能分 ...
 - HashMap循环遍历方式及其性能对比(zhuan)
		
http://www.trinea.cn/android/hashmap-loop-performance/ ********************************************* ...
 - ArrayList和LinkedList遍历方式及性能对比分析
		
ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayLis ...
 
随机推荐
- [sh]sh最佳实战(含grep)
			
sh虐我千百遍,我待sh如初恋. sh复习资料 http://www.cnblogs.com/iiiiher/p/5385108.html http://blog.csdn.net/iiiiher/a ...
 - [LeetCode] 605. Can Place Flowers_Easy
			
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...
 - Vagrant配置虚拟机
			
慕课上学习.需要安装 vagrant VirtualBox .box文件和.iso文件一样都是镜像文件.可以在官网下载https://www.vagrantup.com/docs/ 点击boxs之后 ...
 - DirectShow SDK下载
			
http://blog.csdn.net/zx3517288/article/details/50547243 Q : GRMSDK_EN_DVD.iso 5 67.3MBGRMSDKIAI_EN_D ...
 - centos 专题-各种配置应有尽有
			
你想要的在这里都能得到解决: http://www.linuxidc.com/topicnews.aspx?tid=14
 - YUV编码格式
			
YUV是被欧洲电视系统采用的一种颜色编码方法.在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄像机取像,然后把取 得的彩色图像信号经过分色,分别放大校正后得到RGB,在经过矩阵变换电路,得到 ...
 - SV中的Interface和Program
			
Interface:SV中新定义的接口方式,用来简化接口连接,使用时注意在module或program之外定义interface,然后通过'include来添加进工程. interface arb_ ...
 - zookeeper 详解
			
是 分布式 协调 服务. ZK的工作:注册:所有节点向ZK争抢注册,注册成功会建立一套节点目录树,先注册的节点为Active节点,后注册节点成为standby;监听事件:节点在ZK集群里注册监听动作: ...
 - python 元组 序列上使用enumerate()函数
			
不能直接for n,x,y in enumerate(data)
 - iOS开发-OpenGL ES入门教程1
			
http://www.jianshu.com/p/750fde1d8b6a 这里是一篇新手教程,环境是Xcode7+OpenGL ES 2.0,目标写一个OpenGL ES的hello world.O ...