我需要使用经常调用的开关优化函数:(这个函数的想法非常简单)
StringTable<T> *FastTableOf2( const char &seek ) {
switch ( Count ) {
case 256:
return *( Children + *( byte* )&seek );
case 10:
if ( seek != Keys[ 9 ] )
...
case 2:
if ( seek != Keys[ 1 ] )
case 1:
if ( seek == Keys[ 0 ] )
return Children[ 0 ];
else {
}
else
return Children[ 1 ];
else
return Children[ 2 ];
...
else
return Children[ 9 ];
}
return 0;
}
我考虑过检查Count
是否为256然后执行return *( Children + *( byte* )&seek );
如果没有,则执行goto case[Count]
而不检查该值是否在10-1范围内。 (Count
只能是256或1到10之间)
有没有办法告诉编译器只需要jmp
在switch中标记,而不是检查它是否在范围内?
我知道这种优化很小,但每个百分比都很重要。
答案 0 :(得分:0)
对于高度关键的代码部分,我根本不会使用switch
,而是使用跳转表。
在跳转表中,您可以设置一个函数指针数组。这些函数可以做一些非常简单的事情,比如返回一个直接的值,或做一些更复杂的事情。您的数组中将包含N个元素,其中N是您switch
上可能的最高值。
在设置跳转表时,您将提前填充数组,可能是在程序启动时。每个条目都指向一个真正的功能或某种“未处理”处理程序。
更换switch
并不简单:
StringTable<T> *FastTableOf2( const char &seek ) {
return (mJumpTable[Count])(seek);
}
你不会比这更快。
答案 1 :(得分:0)
我认为交换机实现已经尝试优化, 因为代码似乎等同于:
StringTable<T> *FastTableOf2(const char& seek)
{
if (Count == 256) {
return *(Children + *(byte*)&seek);
}
assert(1 <= Count && Count <= 10);
for (auto c = Count; c != 0; --c) {
if (seek == Keys[c - 1]) {
return Children[c - 1];
}
}
return nullptr;
}
我会尽量避免switch
default
中的“差距”。
default
目前为{0,[11; 255],257 +}。
由于未达到default
,您可以将其与任何其他label
合并。
我注意到char(256) == '\0'
所以所有有效值都在[0; 10]
中,
所以default
= 11+
使用与10+
相同的标签成为case 11
或者,您可以使用Count - 1
并将default
与case 256
合并,
所以default
在这两种情况下都只有11+
。
完全删除特例default
。
所以,也许以下可能会更快:
StringTable<T> *FastTableOf2(const char &seek ) {
switch (char(Count)) {
default: // Count >= 10
case 10: if (seek != Keys[9]) {
...
case 2: if (seek != Keys[1]) {
case 1:
if (seek != Keys[0]) { return nullptr; } else { return Children[0]; }
} else { return Children[1]; } // Count == 2
} else { return Children[2]; } // Count == 3
...
} else { return Children[9]; } // Count == 10
// char(256) == '\0'
case char(256): return *(Children + *(byte*)&seek);
}
}