C++中几种callable实现方式的性能对比

前言

C++中想实现一个callable的对象,通常有四种方式:

  1. std::function:最common的方式,一般会配合std::bind使用。
  2. function pointer:最C的方式,但没办法实现有状态的callable object。
  3. function object:就是重载了operator()的类,C++98的STL中经常用。
  4. 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实现方式的性能对比的更多相关文章

  1. ArrayList和LinkedList的几种循环遍历方式及性能对比分析

    最新最准确内容建议直接访问原文:ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性 ...

  2. Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]

    Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...

  3. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

    主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...

  4. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转载)

    原文地址: http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 原文地址: http://www.trinea.cn ...

  5. 【转】ArrayList和LinkedList的几种循环遍历方式及性能对比分析

    原文网址:http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 主要介绍ArrayList和LinkedList这两种 ...

  6. (转)ArrayList和LinkedList的几种循环遍历方式及性能对比分析

    主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...

  7. python中两种栈实现方式的性能对比

    在计算机的世界中,同一个问题,使用不同的数据结构和算法实现,所使用的资源有很大差别 为了方便量化python中算法的资源消耗,对性能做测试非常有必要,这里针对stack做了python语言 下的性能分 ...

  8. HashMap循环遍历方式及其性能对比(zhuan)

    http://www.trinea.cn/android/hashmap-loop-performance/ ********************************************* ...

  9. ArrayList和LinkedList遍历方式及性能对比分析

    ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayLis ...

随机推荐

  1. EXTJS 4.2.1.883 Summary 合计栏宽度bug

    EXTJS 4.2.1.883中改进了summary插件,使合计栏能够在grid最底部显示,但是列宽和表格对不上,解决方法: 找到以下样式 .x-docked-summary .x-grid-tabl ...

  2. jmeter 测试websocket接口(二)

    1.到https://github.com/maciejzaleski/JMeter-WebSocketSampler下载Jmeter的WebSocket协议的支持插件:JMeterWebSocket ...

  3. dxf cad dwg 文件读写,支持跨平台移植 库

    http://www.pudn.com/Download/item/id/3096684.html 联合开发网 --->绘图程序

  4. liferay中如何获取实例的id和portletId

    在Portlet中request分为两种renderRequet和actionRequest而portlet需要取得实例Id的时候都在renderRequest的时候才可以取到,如下例子 Portle ...

  5. c#string为传值模式

    闲的无聊,记忆中好像是在c/c++语言中string为传址模式(函数修改参数时会影响原来的string参数值),比较好奇c#下对于string参数到底是传值还是传址有些疑问,便亲自测试. 1.结果aa ...

  6. Spring,Struts2,MyBatis,Activiti,Maven,H2,Tomcat集成(二)——Struts2集成

    1. pom.xml文件添struts2依赖jar包: <!-- 与Struts2集成必须使用 --> <dependency> <groupId>org.spri ...

  7. 用rewrite把旧域名直接跳转到新域名的nginx配置

    用rewrite把旧域名直接跳转到新域名的nginx配置 把下面代码保存到daziran.com.conf 放在nginx配置目录下 /etc/nginx/conf.d/ #把旧域名zdz8207直接 ...

  8. 开启你的kali linux DIY之旅

    更新源 首先 是kali2016.2更新源的问题,网上找了好久,都不是很满意.后来把kali 2016.2安装到实体机中才发现,里面自带了更新源.下面我把这个官方自带更新源分享出来(速度蛮快的) de ...

  9. SNMP学习笔记之SNMP 原理与实战详解

    原文地址:http://freeloda.blog.51cto.com/2033581/1306743 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...

  10. Python3.x:抓取百事糗科段子

    Python3.x:抓取百事糗科段子 实现代码: #Python3.6 获取糗事百科的段子 import urllib.request #导入各类要用到的包 import urllib import ...