Commit 5acec5f8 authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

Measure some more locking primitives.

git-svn-id: file:///svn/tokudb@5497 c7de825b-a66e-492c-adef-691d508d4ae1
parent 13bcda76
...@@ -41,91 +41,106 @@ static inline void brwl_rlock_xchg (struct brwl *l) { ...@@ -41,91 +41,106 @@ static inline void brwl_rlock_xchg (struct brwl *l) {
xchg(&l->mutex, 0); xchg(&l->mutex, 0);
} }
// Something wrong with the compiler for longs
static inline long
fetch_and_add (volatile long *p, long incr)
{
long result = incr;
__asm__ __volatile__ ("lock; xaddl %0, %1" :
"+r" (result), "+m" (*p) : : "memory");
return result;
}
static inline int
fetch_and_add_i (volatile int *p, int incr)
{
int result = incr;
__asm__ __volatile__ ("lock; xadd %0, %1" :
"+r" (result), "+m" (*p) : : "memory");
return result;
}
// Something wrong with the compiler for longs
/* Returns nonzero if the comparison succeeded. */
static inline long
compare_and_swap_full(volatile long *addr,
long old, long new_val)
{
char result;
__asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
: "+m"(*(addr)), "=q"(result)
: "r" (new_val), "a"(old) : "memory");
return (int) result;
}
/* Returns nonzero if the comparison succeeded. */
// Atomically compare *addr to old_val, and replace *addr by new_val
// if the first comparison succeeds. Returns nonzero if the comparison
// succeeded and *addr was updated.
static inline int
compare_and_swap_full_i(volatile int *addr,
int old, int new_val)
{
char result;
__asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
: "+m"(*(addr)), "=q"(result)
: "r" (new_val), "a"(old) : "memory");
return (int) result;
}
enum {K=100000}; enum {K=100000};
pthread_rwlock_t rwlocks[K]; pthread_rwlock_t rwlocks[K];
struct brwl blocks[K]; struct brwl blocks[K];
pthread_mutex_t mlocks[K]; pthread_mutex_t mlocks[K];
long lvals[K];
int ivals[K];
#define TIME(s, i, init, body) ({ \
int j_tmp; \
printf("%-24s", s); \
for (j_tmp=0; j_tmp<3; j_tmp++) { \
struct timeval start,end; \
int i; \
for (i=0; i<K; i++) { \
init; \
} \
gettimeofday(&start, 0); \
for (i=0; i<K; i++) { \
body; \
} \
gettimeofday(&end, 0); \
printf(" %9.3fus", tdiff(&start,&end)/K); \
} \
printf("\n"); \
})
int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) { int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
int j; TIME("pthread_mutex_lock", i,
int i; ({ int r = pthread_mutex_init(&mlocks[i], NULL); assert(r==0); }),
int r; ({ int r = pthread_mutex_lock(&mlocks[i]); assert(r==0); }));
struct timeval start, end; TIME("pthread_mutex_unlock", i,
for (j=0; j<3; j++) { ({ int r = pthread_mutex_init(&mlocks[i], NULL); assert(r==0); r = pthread_mutex_lock(&mlocks[i]); assert(r==0); }),
for (i=0; i<K; i++) { ({ int r = pthread_mutex_unlock(&mlocks[i]); assert(r==0); }));
r=pthread_mutex_init(&mlocks[i], NULL); TIME("pthread_rwlock_tryrdlock", i,
assert(r==0); ({ int r = pthread_rwlock_init(&rwlocks[i], NULL); assert(r==0); }),
} ({ int r = pthread_rwlock_tryrdlock(&rwlocks[i]); assert(r==0); }));
gettimeofday(&start, 0); TIME("pthread_rwlock_rdlock", i,
for (i=0; i<K; i++) { ({ int r = pthread_rwlock_init(&rwlocks[i], NULL); assert(r==0); }),
r = pthread_mutex_lock(&mlocks[i]); ({ int r = pthread_rwlock_rdlock(&rwlocks[i]); assert(r==0); }));
assert(r==0); TIME("brwl_rlock_xchg", i,
} (blocks[i].state=0, blocks[i].mutex=0),
gettimeofday(&end, 0); brwl_rlock_xchg(&blocks[i]));
printf("pthread_mutex_lock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end)); TIME("brwl_rlock_fence", i,
(blocks[i].state=0, blocks[i].mutex=0),
gettimeofday(&start, 0); brwl_rlock_fence(&blocks[i]));
for (i=0; i<K; i++) { int fa=0;
r = pthread_mutex_unlock(&mlocks[i]); TIME("fetchadd", i,
assert(r==0); (void)0,
} fetch_and_add_i(&fa, i));
gettimeofday(&end, 0); TIME("compare_and_swap", i,
printf("pthread_mutex_unlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end)); ivals[i]=0,
} ({ int r=compare_and_swap_full_i(&ivals[i], 0, 1); assert(r==1); }));
for (j=0; j<3; j++) {
for (i=0; i<K; i++) {
r=pthread_rwlock_init(&rwlocks[i], NULL);
assert(r==0);
}
gettimeofday(&start, 0);
for (i=0; i<K; i++) {
r = pthread_rwlock_tryrdlock(&rwlocks[i]);
assert(r==0);
}
gettimeofday(&end, 0);
printf("pthread_rwlock_tryrdlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
}
for (j=0; j<3; j++) {
for (i=0; i<K; i++) {
r=pthread_rwlock_init(&rwlocks[i], NULL);
assert(r==0);
}
gettimeofday(&start, 0);
for (i=0; i<K; i++) {
r = pthread_rwlock_rdlock(&rwlocks[i]);
assert(r==0);
}
gettimeofday(&end, 0);
printf("pthread_rwlock_rdlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
}
for (j=0; j<3; j++) {
for (i=0; i<K; i++) {
blocks[i].state=0;
blocks[i].mutex=0;
}
gettimeofday(&start, 0);
for (i=0; i<K; i++) {
brwl_rlock_xchg(&blocks[i]);
}
gettimeofday(&end, 0);
printf("brwl_rlock_xchg took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
}
for (j=0; j<3; j++) {
for (i=0; i<K; i++) {
blocks[i].state=0;
blocks[i].mutex=0;
}
gettimeofday(&start, 0);
for (i=0; i<K; i++) {
brwl_rlock_fence(&blocks[i]);
}
gettimeofday(&end, 0);
printf("brwl_rlock_fence took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
}
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment