lambda 是语言层面的 feature,功能强大,性能高,而 bind 在很多时候使用起来更简洁。
在现实中,至少有一种情况,一定 不要使用 bind: 把 lambda 当作 std::function 使用时!
在 MySQL 源码中,有这样一段代码:
void handler::ha_statistic_increment(ulonglong System_status_var::*offset) const {
if (table && table->in_use) {
(table->in_use->status_var.*offset)++;
table->in_use->check_limit_rows_examined();
table->in_use->update_sql_stats_periodic();
table->in_use->check_yield(std::bind(yield_condition, table));
}
}
注意其中使用的
std::bind:
table->in_use->check_yield(std::bind(yield_condition, table));
这个 bind 以最简洁的方式,非常准确直观地表达了程序意图,我们看 yield_condition 的原型:
static bool yield_condition(TABLE*);
它只有一个参数,而 check_yield 函数是这样的:
void THD::check_yield(std::function<bool()> cond) {...}
上面的 std::bind 会生成一个 class,其实现了 operator(),仅针对这个例子,实例化之后大致会是这样:
struct BindType {
bool (*m_yield_condition)(TABLE*); // = &yield_condition
TABLE* m_table; // = table;
bool operator() const { return m_yield_condition(m_table); }
};
可以看到,BindType 至少需要占用两个指针的空间,记住这一点!std::function 的实现,一般(g++ 的 libstdc++)占用四个指针的空间,如果用来初始化 std::function 的 Functor 对象(包括函数指针、lambda……)尺寸过大,就需要通过 new 在堆上申请内存,用来保存 Functor。MySQL 的这个 std::bind,就生成了一个让 std::function 必须 new 内存的 Functor!这个额外的消耗,在 中虽然占比不多,但还是清晰可见的:
虽然这个总耗时不多,但是看看 new/delete 占了多大比例!当然,这个问题,只要意识到了,改进修复还是非常简单的,使用 lambda 即可:

这个 lambda 仅捕获了 handler::table,当然也可以改成这样:
[this]() { return yield_condition(this->table); }
但是捕获 table 性能要更高,因为此刻编译器早已把 table 成员加载到某个寄存器中了,从而需要的后续操作更少。这个 lambda 的尺寸只有一个指针大小,用它来构造 std::function,不需要 new/delete!
如果 lambda 的尺寸无论如何都超过一个指针大小呢?
使用 std::ref,这样写:
auto lambda = [...](...) {...}; // 超过一个指针大小的 lambda
std::function<...> func(std::ref(lambda));
// ...
但这个前提是 必须保证 lambda 的生命周期覆盖 func。
编辑推荐:
- C++11有了lambda后bind还有多大意义?03-01
- 啥?分库分表会带来读扩散问题?怎么解决???03-01
- 为什么mysql的count()方法这么慢?03-01
- 多线程fork,子进程执行哪些函数是安全的?03-01
- 详谈 MySQL 8.0 原子 DDL 原理03-01
- 《MySQL 8.x从入门到精通(视频教学版)》简介03-01
- MySQL 5.7配置SSL连接03-01
- 一句SQL,我的数据库crash了03-01
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- C++11有了lambda后bind还有多大意义?
C++11有了lambda后bind还有多大意义?
26-03-01 - 啥?分库分表会带来读扩散问题?怎么解决???
啥?分库分表会带来读扩散问题?怎么解决???
26-03-01 - 为什么mysql的count()方法这么慢?
为什么mysql的count()方法这么慢?
26-03-01 - 多线程fork,子进程执行哪些函数是安全的?
多线程fork,子进程执行哪些函数是安全的?
26-03-01 - 详谈 MySQL 8.0 原子 DDL 原理
详谈 MySQL 8.0 原子 DDL 原理
26-03-01 - 《MySQL 8.x从入门到精通(视频教学版)》简介
《MySQL 8.x从入门到精通(视频教学版)》简介
26-03-01 - 一句SQL,我的数据库crash了
一句SQL,我的数据库crash了
26-03-01 - 创业是走向破产的最佳途径
创业是走向破产的最佳途径
26-03-01 - ordered_commit流程梳理
ordered_commit流程梳理
26-03-01 - 对话MySQL之父Monty:代码要写到100岁
对话MySQL之父Monty:代码要写到100岁
26-03-01
