函数手工多态: 表驱动、缓存函数指针、和switch性能

编译环境:VS2022/gcc最新版

结论

switch(各种可能性) 转而调用具体函数的,性能最高,因为编译器会将各函数内联在这里。关键是,编译期可能会将所有分支的共性提取到公共部分,并能省略对寄存器的保护等。


【表驱动】

对于函数指针数组,即使使用了const修饰指针值,
只要下标是非常量入参,即使在循环期间下标是固定值,

	uint32_t i = 编译期不确定入参
    for (int j = 0; j < 10000; ++j)
        constFuncPtrArr[i].fpCall();

循环调用时,都会重新读取指针

		.L11
	   	……
	    call    [QWORD PTR constFuncPtrArr[rbp]]
        cmp     ebx, 10000
        jne     .L11

【缓存函数指针】

	uint32_t i = 编译期不确定入参
	auto pf =  constFuncPtrArr[i].fpCall;
    for (int j = 0; j < 10000; ++j)
       pf();
		.L11
	   	……
	    call    esi
        cmp     ebx, 10000
        jne     .L11

但性能和前者一致。


###【Switch case】
然而使用

FP GetFunc(int i) {
switch (i)
{
case 0:
	return &Call1;
case 1:
	return &Call2;
default:
	std::unreachable();
}
}
    for (int j = 0; j < 10000; ++j)
        GetFunc(i)();

编译出

		.L11
		如果是0……
		{
			……
		}
	   	如果是1……
	   	{
	   		……
	    }
        cmp     ebx, 10000
        jne     .L11

也就是编译器实际上把多态的所有可能性内联到这里了。
性能几乎是前两者的两倍


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值