Messages in this thread | | | Date | Sat, 30 Oct 1999 21:58:32 +0200 | From | Manfred Spraul <> | Subject | benchmark of the new buffer hash |
| |
I've read your benchmark program for the hash function, and noticed that you use SCHED_FIFO.
Have you thought about using a simple "sleep(1)"? This will synchonize your program with the timer interrupt, and (at least on my computer) I get a reproducable, exact value.
I've attached a modified version: (Pentium II/350 and Amd K6/200 (*)) * hash13: 16 / 13 cpu ticks * hash14pre: 46 / 33 cpu ticks
(*) the K6 values vary, it seems the benchmark cannot force all cpu caches into the 'hot' state. These are the lowest values.
-- Manfred/* * timetest.cpp: RDTSC based performance tester. * * Copyright (C) 1999 by Manfred Spraul. * * Redistribution of this file is permitted under the terms of the GNU * Public License (GPL) * $Header: /pub/cvs/ms/hashbench/hashbench.cpp,v 1.1 1999/10/30 19:45:05 manfreds Exp $ */
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
typedef unsigned short kdev_t; #define HASHDEV(dev) ((unsigned int) (dev))
// Intel recommends that a serializing instruction // should be called before and after rdtsc. // CPUID is a serializing instruction. // ".align 64:" the atlon has a 64 byte cache line size. #define read_rdtsc_before(time) \ __asm__ __volatile__( \ ".align 64\n\t" \ "cpuid\n\t" \ "rdtsc\n\t" \ "mov %%eax,(%0)\n\t" \ "mov %%edx,4(%0)\n\t" \ "cpuid\n\t" \ : /* no output */ \ : "S"(&time) \ : "eax", "ebx", "ecx", "edx", "memory")
#define read_rdtsc_after(time) \ __asm__ __volatile__( \ "cpuid\n\t" \ "rdtsc\n\t" \ "mov %%eax,(%0)\n\t" \ "mov %%edx,4(%0)\n\t" \ "cpuid\n\t" \ : /* no output */ \ : "S"(&time) \ : "eax", "ebx", "ecx", "edx", "memory") #define BUILD_TESTFNC(name, text, instructions) \ static void name(int show) \ { \ unsigned long long time; \ unsigned long long time2; \ \ read_rdtsc_before(time); \ instructions; \ read_rdtsc_after(time2); \ if(show) \ printf("total time for " text ": %Ld ticks.\n", \ time2-time); \ } \
#define _hashfn_13(dev,block) (((unsigned)(HASHDEV(dev)^block)) & bh_hash_mask)
#define __hashfn_14pre(dev,block) \ ((((dev)<<(bh_hash_shift - 6)) ^ ((dev)<<(bh_hash_shift - 9))) ^ \ (((block)<<(bh_hash_shift - 6)) ^ ((block) >> 13) ^ ((block) << (bh_hash_shift - 12)))) #define _hashfn_14pre(dev,block) (__hashfn_14pre(dev,block) & bh_hash_mask)
unsigned long bh_hash_mask = 0x7ffff, bh_hash_shift = 19;
unsigned long hashfn_13(kdev_t dev, int block) { return _hashfn_13(dev, block); }
unsigned long hashfn_14pre(kdev_t dev, int block) { return _hashfn_14pre(dev, block); } unsigned long out;
void tt_13(void) { kdev_t dev = 0x0801; int block = 28976; out = _hashfn_13(dev,block); }
void tt_14(void) { kdev_t dev = 0x0801; int block = 28976; out = _hashfn_14pre(dev,block); } //////////////////////////////////////////////////////////////////////////////
BUILD_TESTFNC(zerotest,"zerotest", (void)0)
#define CLC __asm__ __volatile__ ("clc\n\t" : : : "memory") #define TESTL __asm__ __volatile__ ("testl %%eax, %%eax \n\t" : : : "eax", "memory") #define DUMMY __asm__ __volatile__ ("movl %%edx, %%ecx \n\t" : : : "ecx", "edx", "memory") #define DUMMY2 __asm__ __volatile__ ("movl %%esi, %%edi \n\t" : : : "esi", "edi", "memory")
BUILD_TESTFNC(hash13test, "hashfn_13", tt_13()); BUILD_TESTFNC(hash14test, "testl-test", tt_14());
int main() {
if(geteuid() == 0) { int res = nice(-20); if(res < 0) { perror("nice(-20)"); return 1; } printf("TIMETEST, reniced to (-20).\n"); } else { printf("TIMETEST called by non-superuser, running with normal priority.\n"); } sleep(1); zerotest(0); zerotest(1); sleep(1); zerotest(0); zerotest(1); sleep(1); zerotest(0); zerotest(1);
sleep(1); hash13test(0); hash13test(1);
sleep(1); hash13test(0); hash13test(1);
sleep(1); hash13test(0); hash13test(1);
sleep(1); hash14test(0); hash14test(1);
sleep(1); hash14test(0); hash14test(1);
sleep(1); hash14test(0); hash14test(1);
return 0; }
| |