/* * $ taskset -c 3 ./nops * Running 600 times, 10000000 loops per run. * nop_0x90 average: 439.805220 * nop_3_byte average: 442.412915 * * How to run: * * taskset -c argv0 */ #include #include #include #include typedef unsigned long long u64; #define TWO(a) a; a; #define FOUR(a) TWO(TWO(a)) #define SIXTEEN(a) FOUR(FOUR(a)) #define TWOFIVESIX(a) SIXTEEN(SIXTEEN(a)) #define DECLARE_ARGS(val, low, high) unsigned low, high #define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32)) #define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high) #define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high) static __always_inline unsigned long long rdtsc(void) { DECLARE_ARGS(val, low, high); asm volatile("rdtsc" : EAX_EDX_RET(val, low, high)); return EAX_EDX_VAL(val, low, high); } static inline u64 read_tsc(void) { u64 ret; asm volatile("mfence"); ret = rdtsc(); asm volatile("mfence"); return ret; } static void nop_0x90(void) { TWOFIVESIX(asm volatile(".byte 0x66, 0x66, 0x90")) } static void nop_3_byte(void) { TWOFIVESIX(asm volatile(".byte 0x0f, 0x1f, 0x00")) } int main() { int i, j; u64 p1, p2; u64 r, min; #define TIMES 60 #define LOOPS 1000000ULL printf("Running %d times, %lld loops per run.\n", TIMES, LOOPS); min = 100000000; for (r = 0, j = 0; j < TIMES; j++) { p1 = read_tsc(); for (i = 0; i < LOOPS; i++) { nop_0x90(); } p2 = read_tsc(); r = (p2 - p1); if (r < min) min = r; } printf("nop_0x90 average: %f\n", min / (double) LOOPS / 256); min = 100000000; for (r = 0, j = 0; j < TIMES; j++) { p1 = read_tsc(); for (i = 0; i < LOOPS; i++) { nop_3_byte(); } p2 = read_tsc(); r = (p2 - p1); if (r < min) min = r; } printf("nop_3_byte average: %f\n", min / (double) LOOPS / 256); return 0; }