问题背景:
阅读PHP内核代码期间,发现有大量的宏:EXPECTED(condition)、UNEXPECTED(condition),比如在HashTable的相关实现中就有如下代码片段:
if (nSize < HT_MIN_SIZE) {
nSize = HT_MIN_SIZE;
} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
}
那么这两个宏到底是干啥的?有什么意义呢?
问题追踪:
通过代码跟踪,不难发现这两个宏调用的是如下两个LINUX指令:
# define EXPECTED(condition) __builtin_expect(!!(condition), 1)
# define UNEXPECTED(condition) __builtin_expect(!!(condition), 0)
问题说明:
__builtin_expect是Linux 内核中最常用的性能优化技术之一。在码农编写有条件代码时,通常知道哪个分支最有可能被执行,而哪个分支很少被执行,如果编译器知道这种预测信息,就可以围绕最可能执行的分支生成最优的代码。如果一个条件标上了“EXPECTED”,那么编译器可以把代码的 True 部分直接放在分支指令后面(这样就不需要执行分支指令)。
宏的含义:
(1)EXPECTED(condition) 代表大概率 condition 成立;
(2)UNEXPECTED(condition) 代表大概率 condition 不成立;
问题补充:
关于涉及到的性能优化细节需要从汇编层面加以理解,待补充~