在 Linux 内核代码中有一个宏用于测试位(Linux 版本 2.6.2):
我知道
更新:以下主函数用于测试性能:
常量,调用constant_test_bit:
#define test_bit(nr, addr) \
(__builtin_constant_p((nr)) \
? constant_test_bit((nr), (addr)) \
: variable_test_bit((nr), (addr)))
其中constant_test_bit
和variable_test_bit
的定义如下:
static inline int constant_test_bit(int nr, const volatile unsigned long *addr )
{
return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
}
static __inline__ int variable_test_bit(int nr, const volatile unsigned long *addr)
{
int oldbit;
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"Ir" (nr));
return oldbit;
}
我知道
__builtin_constant_p
用于检测变量是否为编译时常量或未知。我的问题是:当参数是编译时常量或非编译时常量时,这两个函数之间是否存在性能差异?为什么在参数为编译时常量时使用C版本,在参数不是编译时常量时使用汇编版本?更新:以下主函数用于测试性能:
常量,调用constant_test_bit:
int main(void) {
unsigned long i, j = 21;
unsigned long cnt = 0;
srand(111)
//j = rand() % 31;
for (i = 1; i < (1 << 30); i++) {
j = (j + 1) % 28;
if (constant_test_bit(j, &i))
cnt++;
}
if (__builtin_constant_p(j))
printf("j is a compile time constant\n");
return 0;
}
这段代码可以正确输出句子j is a...
对于其他情况,请取消注释将随机数赋给j
的那一行,并相应更改函数名称。取消注释后,输出结果将为空,这是正常现象。
我使用gcc test.c -O1
进行编译,以下是结果:
constant、constant_test_bit:
$ time ./a.out
j is compile time constant
real 0m0.454s
user 0m0.450s
sys 0m0.000s
常量,变量_test_bit(省略time ./a.out
,以下同):
j is compile time constant
real 0m0.885s
user 0m0.883s
sys 0m0.000s
变量,常量_test_bit:
real 0m0.485s
user 0m0.477s
sys 0m0.007s
变量,变量测试位:
real 0m3.471s
user 0m3.467s
sys 0m0.000s
我运行了每个版本多次,上面的结果是它们的典型值。似乎无论参数是否为编译时常量,constant_test_bit
函数始终比variable_test_bit
函数更快...对于最后两个结果(当j
不是常量时),变量版本甚至比常量版本慢得多。
我错过了什么吗?