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. Spark DataFrame vector 类型存储到Hive表

    1. 软件版本 软件 版本 Spark 1.6.0 Hive 1.2.1 2. 场景描述 在使用Spark时,有时需要存储DataFrame数据到Hive表中,一般的存储方式如下: // 注册临时表 ...

  2. PAT 1087 All Roads Lead to Rome[图论][迪杰斯特拉+dfs]

    1087 All Roads Lead to Rome (30)(30 分) Indeed there are many different tourist routes from our city ...

  3. Are you looking forward to this 11s Black Stingray

    The Derek Jeter Air Jordan 11 Navy Suede has quietly dropped a number of various colorways over the ...

  4. 浅谈Java中的初始化和清理

    引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...

  5. linux 统计wc

    说明:该命令统计给定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同时也给出所有指定文件的总统计数.字是由空格字符区分开的最大字符串. 该命令各选项含义如下: - c 统计字节 ...

  6. MySQL从删库到跑路_高级(六)——索引

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.索引简介 1.索引简介 索引(Index)是帮助MySQL高效获取数据的数据结构. 在MySQL中,索引属于存储 ...

  7. vue的双向数据绑定原理

    原理. vue是采用数据劫持结合发布者-订阅者模式的方式, 通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回 ...

  8. centos7.3上安装oracle xe 11g

    oracle -11g-xe是数据库是免费版本,支持标准版的大部分功能.oracle XE版本也称快捷版本.是个个人学习,熟悉oracle的简化版. oracle XE做为免费的Oracle数据库版本 ...

  9. 20145332 MAL_简单后门

    20145332 MAL_简单后门 用NC获取远程主机的shell 2.1.1 Windows获得Linux的权限 首先要在Windows主机下安装ncat.exe,安装完成后需要配置环境变量path ...

  10. vijos 1098 合唱队形 - 动态规划

    描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…, ...