今天發現一個奇怪的現象,用linux核心的bitops.h裡面的bit_set和test_bit居然沒有不用彙編的代碼快。記錄下來,備忘。 下面是可執行程式,THUIRDB暫時沒有bitops裡面的實現,改用我自己寫的實現了。當然bitops裡的實現,nr可以很大,而My Codenr只能是0-63之間的一個數,對THUIRDB的應用來說,足夠了。#include "stdint.h"#include <iostream>using namespace std;#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))#define ADDR BITOP_ADDR(addr)#ifdef CONFIG_SMP#define LOCK_PREFIX / ".section .smp_locks,/"a/"/n" / _ASM_ALIGN "/n" / _ASM_PTR "661f/n" / ".previous/n" / "661:/n/tlock; "#else#define LOCK_PREFIX ""#endifstatic inline voidset_bit(unsigned int nr, volatile unsigned long *addr){ __asm__ volatile(LOCK_PREFIX "bts %1,%0" : BITOP_ADDR(addr) : "Ir" (nr) : "memory");}static inline bool test_bit(int nr, volatile const unsigned long *addr){ int oldbit; asm volatile("bt %2,%1/n/t" "sbb %0,%0" : "=r" (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr)); return oldbit!=0;}static void _set_bit(int nr, uint64_t* addr){ addr[0] |= ( 1UL << nr);};static bool _test_bit(int nr,uint64_t* addr){ return (0 < (addr[0] & (1UL<<nr)));};int main(void){ uint64_t bit_arr=0; #ifdef T1 for(int i = 0; i<1000000;++i) { _set_bit(id,&bit_arr); } #endif #ifdef T2 for(int i = 0; i<1000000;++i) { set_bit(id,&bit_arr); } #endif #ifdef T3 for(int i = 0; i<1000000;++i) { _test_bit(id,&bit_arr); } #endif #ifdef T4 for(int i = 0; i<1000000;++i) { test_bit(id,&bit_arr); } #endif return 0;}以下是反組譯碼的結果,可以看出用核心的方法,代碼短小,但效率較低,用移位與或的方法代碼多,但效率高。000000000040067c <_ZL7set_bitjPVm>: //set_bit 40067c: 55 push %rbp 40067d: 48 89 e5 mov %rsp,%rbp 400680: 89 7d fc mov % edi,-0x4(%rbp) 400683: 48 89 75 f0 mov %rsi,-0x10(%rbp) 400687: 48 8b 45 f0 mov -0x10(%rbp),%rax 40068b: 8b 55 fc mov -0x4(%rbp),% edx 40068e: 0f ab 10 bts % edx,(%rax) 400691: c9 leaveq 400692: c3 retq 0000000000400693 <_ZL8test_bitiPVKm>://test_bit 400693: 55 push %rbp 400694: 48 89 e5 mov %rsp,%rbp 400697: 89 7d ec mov % edi,-0x14(%rbp) 40069a: 48 89 75 e0 mov %rsi,-0x20(%rbp) 40069e: 48 8b 45 e0 mov -0x20(%rbp),%rax 4006a2: 8b 55 ec mov -0x14(%rbp),% edx 4006a5: 0f a3 10 bt % edx,(%rax) 4006a8: 19 c0 sbb % eax,% eax 4006aa: 89 45 fc mov % eax,-0x4(%rbp) 4006ad: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) 4006b1: 0f 95 c0 setne %al 4006b4: c9 leaveq 4006b5: c3 retq 00000000004006b6 <_ZL8_set_bitiPm>://_set_bit 4006b6: 55 push %rbp 4006b7: 48 89 e5 mov %rsp,%rbp 4006ba: 53 push %rbx 4006bb: 89 7d f4 mov % edi,-0xc(%rbp) 4006be: 48 89 75 e8 mov %rsi,-0x18(%rbp) 4006c2: 48 8b 45 e8 mov -0x18(%rbp),%rax 4006c6: 48 8b 10 mov (%rax),%rdx 4006c9: 8b 45 f4 mov -0xc(%rbp),% eax 4006cc: bb 01 00 00 00 mov $0x1,% ebx 4006d1: 48 89 de mov %rbx,%rsi 4006d4: 89 c1 mov % eax,% ecx 4006d6: 48 d3 e6 shl %cl,%rsi 4006d9: 48 89 f0 mov %rsi,%rax 4006dc: 48 09 c2 or %rax,%rdx 4006df: 48 8b 45 e8 mov -0x18(%rbp),%rax 4006e3: 48 89 10 mov %rdx,(%rax) 4006e6: 5b pop %rbx 4006e7: c9 leaveq 4006e8: c3 retq 00000000004006e9 <_ZL9_test_bitiPm>://_test_bit 4006e9: 55 push %rbp 4006ea: 48 89 e5 mov %rsp,%rbp 4006ed: 53 push %rbx 4006ee: 89 7d f4 mov % edi,-0xc(%rbp) 4006f1: 48 89 75 e8 mov %rsi,-0x18(%rbp) 4006f5: 48 8b 45 e8 mov -0x18(%rbp),%rax 4006f9: 48 8b 10 mov (%rax),%rdx 4006fc: 8b 45 f4 mov -0xc(%rbp),% eax 4006ff: 48 89 d3 mov %rdx,%rbx 400702: 89 c1 mov % eax,% ecx 400704: 48 d3 eb shr %cl,%rbx 400707: 48 89 d8 mov %rbx,%rax 40070a: 83 e0 01 and $0x1,% eax 40070d: 5b pop %rbx 40070e: c9 leaveq 40070f: c3 retq T2用-O2最佳化後的代碼,內聯到main裡面從400910到40093b00000000004008f0 <main>:<br /> 4008f0: 55 push %rbp<br /> 4008f1: 31 c0 xor %eax,%eax<br /> 4008f3: 53 push %rbx<br /> 4008f4: 48 83 ec 18 sub $0x18,%rsp<br /> 4008f8: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx<br /> 4008fd: 48 c7 44 24 08 00 00 movq $0x0,0x8(%rsp)<br /> 400904: 00 00<br /> 400906: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)<br /> 40090d: 00 00 00<br /> 400910: 89 c2 mov %eax,%edx<br /> 400912: 83 e2 3f and $0x3f,%edx<br /> 400915: 0f ab 11 bts %edx,(%rcx)<br /> 400918: 83 c0 01 add $0x1,%eax<br /> 40091b: 3d 40 42 0f 00 cmp $0xf4240,%eax<br /> 400920: 75 ee jne 400910 <main+0x20><br /> 400922: 48 8b 74 24 08 mov 0x8(%rsp),%rsi<br /> 400927: bf e0 0d 60 00 mov $0x600de0,%edi<br /> 40092c: e8 67 fe ff ff callq 400798 <_ZNSo9_M_insertImEERSoT_@plt><br /> 400931: 48 89 c3 mov %rax,%rbx<br /> 400934: 48 8b 00 mov (%rax),%rax<br /> 400937: 48 8b 40 e8 mov -0x18(%rax),%rax<br /> 40093b: 48 8b ac 03 f0 00 00 mov 0xf0(%rbx,%rax,1),%rbp<br /> 400942: 00<br /> 400943: 48 85 ed test %rbp,%rbp<br /> 400946: 74 3f je 400987 <main+0x97><br /> 400948: 80 7d 38 00 cmpb $0x0,0x38(%rbp)<br /> 40094c: 74 20 je 40096e <main+0x7e><br /> 40094e: 0f b6 45 43 movzbl 0x43(%rbp),%eax<br /> 400952: 48 89 df mov %rbx,%rdi<br /> 400955: 0f be f0 movsbl %al,%esi<br /> 400958: e8 5b fe ff ff callq 4007b8 <_ZNSo3putEc@plt><br /> 40095d: 48 89 c7 mov %rax,%rdi<br /> 400960: e8 23 fe ff ff callq 400788 <_ZNSo5flushEv@plt><br /> 400965: 48 83 c4 18 add $0x18,%rsp<br /> 400969: 31 c0 xor %eax,%eax<br /> 40096b: 5b pop %rbx<br /> 40096c: 5d pop %rbp<br /> 40096d: c3 retq<br /> 40096e: 48 89 ef mov %rbp,%rdi<br /> 400971: e8 c2 fd ff ff callq 400738 <_ZNKSt5ctypeIcE13_M_widen_initEv@plt><br /> 400976: 48 8b 45 00 mov 0x0(%rbp),%rax<br /> 40097a: be 0a 00 00 00 mov $0xa,%esi<br /> 40097f: 48 89 ef mov %rbp,%rdi<br /> 400982: ff 50 30 callq *0x30(%rax)<br /> 400985: eb cb jmp 400952 <main+0x62><br /> 400987: e8 9c fd ff ff callq 400728 <_ZSt16__throw_bad_castv@plt><br /> 40098c: 90 nop<br /> 40098d: 90 nop<br /> 40098e: 90 nop<br /> 40098f: 90 nop