summaryrefslogtreecommitdiffstats
path: root/lf_ringbuffer_test.c
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2010-01-12 12:53:12 +0100
committerJérémy Zurcher <jeremy@asynk.ch>2010-01-12 12:53:12 +0100
commited364de0e13fcb70d890ffa3763e7c7ec5a5797b (patch)
tree5e47e7a20f396bfd7c6b08ceaab09adc414e21b3 /lf_ringbuffer_test.c
parent3bb0657778d620919f13e087ad05fbb6aadc63e5 (diff)
downloadlock_free-ed364de0e13fcb70d890ffa3763e7c7ec5a5797b.zip
lock_free-ed364de0e13fcb70d890ffa3763e7c7ec5a5797b.tar.gz
rename ring_buffer to ringbuffer and remove previous attempt
Diffstat (limited to 'lf_ringbuffer_test.c')
-rw-r--r--lf_ringbuffer_test.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/lf_ringbuffer_test.c b/lf_ringbuffer_test.c
new file mode 100644
index 0000000..8c41b97
--- /dev/null
+++ b/lf_ringbuffer_test.c
@@ -0,0 +1,191 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "lf_ringbuffer.h"
+
+#define BUFFER_LEN 65000
+
+//static rb_data_t data[BUFFER_LEN][RB_DATA_LEN];
+
+static int64_t time_diff(struct timespec *t0, struct timespec *t1)
+{
+ return ((t1->tv_sec * 1000000000) + t1->tv_nsec) - ((t0->tv_sec * 1000000000) + t0->tv_nsec);
+}
+
+/*
+static void print_now(char* s) {
+ fprintf(stdout,s);
+ fflush(stdout);
+}
+*/
+
+static void report( char* op, int n, uint64_t dt, int redo ) {
+ fprintf(stdout,"\t%9d %s operations in %4d [ms] => %7d [us] => %10d [ns]\t >>> %6d [ns/op]\t%4d redone operations\n",
+ n, op, (int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/n), redo );
+}
+
+struct thread_params {
+ lf_ring_buffer_t *ring;
+ int n;
+ int flags;
+ uint64_t dt;
+};
+
+/*
+static void feed_data( int n){
+ int i;
+ for(i=0; i<n; i++){
+ sprintf(data[i],"hello world %04d\n",i);
+ }
+}
+*/
+
+static uint64_t sequential_writes( lf_ring_buffer_t *ring, int n, int flags ) {
+ int i, redo=0;
+ rb_data_t data[RB_DATA_LEN];
+ struct timespec start, end;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ if(flags==0) {
+ for(i=0; i<n; i++) lf_ring_buffer_write( ring, data, flags );
+ } else {
+ for(i=0; i<n;) {
+ if(lf_ring_buffer_write( ring, data, flags )==0) { i++; } else { redo+=1; }
+ }
+ }
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ report( "write", n, time_diff( &start, &end ), redo );
+ return time_diff( &start, &end );
+}
+
+static uint64_t sequential_reads( lf_ring_buffer_t *ring, int n, int flags ) {
+ int i,redo=0;
+ rb_data_t data[RB_DATA_LEN];
+ struct timespec start, end;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ if(flags==0) {
+ for(i=0; i<n; i++) lf_ring_buffer_read( ring, data, flags );
+ } else {
+ for(i=0; i<n;) {
+ if(lf_ring_buffer_read( ring, data, flags )==0) { i++; } else { redo+=1; }
+ }
+ }
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ report( "read ", n, time_diff( &start, &end ), redo );
+ return time_diff( &start, &end );
+}
+
+void* writer_thread( void* param ) {
+ struct thread_params *params = (struct thread_params*)param;
+ //report( "write", params->n, sequential_writes( params->ring, params->n, params->flags ) );
+ params->dt = sequential_writes( params->ring, params->n, params->flags );
+ return NULL;
+}
+
+void* reader_thread( void* param ) {
+ struct thread_params *params = (struct thread_params*)param;
+ //report( "read ", params->n, sequential_reads( params->ring, params->n, params->flags ) );
+ params->dt = sequential_reads( params->ring, params->n, params->flags );
+ return NULL;
+}
+
+static void parallel_op( int op, int nt, lf_ring_buffer_t *ring, int n, int flags ) {
+ int i;
+ uint64_t dt;
+
+ pthread_t *threads = malloc( sizeof(pthread_t)*nt);
+ struct thread_params *params = malloc( sizeof(struct thread_params)*nt);
+
+ for(i=0; i<nt; i++) {
+ params[i].ring = ring;
+ params[i].n = n/nt;
+ params[i].flags = flags;
+ if(op==0) {
+ if (pthread_create( &threads[i], NULL, writer_thread, &params[i])) {
+ fprintf(stderr,"Failed to create writer thread[%d]\n",i);
+ exit(1);
+ }
+ } else if(op==1) {
+ if (pthread_create( &threads[i], NULL, reader_thread, &params[i])) {
+ fprintf(stderr,"Failed to create reader thread[%d]\n",i);
+ exit(1);
+ }
+ } else {
+ params[i].n /=2;
+ if (pthread_create( &threads[i], NULL, writer_thread, &params[i])) {
+ fprintf(stderr,"Failed to create writer thread[%d]\n",i);
+ exit(1);
+ }
+ if (pthread_create( &threads[i], NULL, reader_thread, &params[i])) {
+ fprintf(stderr,"Failed to create reader thread[%d]\n",i);
+ exit(1);
+ }
+ }
+ }
+ dt = 0;
+ for(i=0; i<nt; i++) {
+ pthread_join( threads[i], NULL );
+ dt += params[i].dt;
+ }
+ dt/=nt;
+ fprintf(stdout,"\t\t\t Mean : %4d [ms] => %7d [us] => %10d [ns]\t >>> %6d [ns/op]\n",(int)(dt/1000000), (int)(dt/1000), (int)dt, (int)(dt/(n/nt)) );
+ /* empty the ring */
+ free(threads);
+ free(params);
+}
+
+int main( int argc, char** argv ) {
+
+ int i;
+ int b_len = BUFFER_LEN;
+ lf_ring_buffer_t *ring;
+
+ ring = lf_ring_buffer_create( b_len );
+ if(ring==NULL){
+ fprintf(stderr,"ERROR : lf_ring_buffer_create( %d );\n",b_len);
+ exit( EXIT_FAILURE );
+ }
+
+ /*
+ print_now("feed the data ... ");
+ feed_data(b_len);
+ printf("done.\n");
+ */
+
+ printf("sequential non blocking write operations ...\n");
+ sequential_writes( ring, b_len, 0 );
+ printf("sequential non blocking read operations ...\n");
+ sequential_reads( ring, b_len, 0 );
+ if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); }
+ printf("sequential blocking write operations ...\n");
+ sequential_writes( ring, b_len, LFRB_NO_BLOCK );
+ printf("sequential blocking read operations ...\n");
+ sequential_reads( ring, b_len, LFRB_NO_BLOCK );
+ if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); }
+
+ for(i=5; i<=50;i*=2) {
+ printf("%d parallel blocking with backoff inc write operations .... \n",i);
+ parallel_op( 0, i, ring, b_len, 0 );
+ printf("parallel blocking read operations ...\n");
+ sequential_reads( ring, b_len, 0 );
+ if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); }
+ }
+ for(i=5; i<=50;i*=2) {
+ printf("%d parallel non blocking write operations .... \n",i);
+ parallel_op( 0, i, ring, b_len, LFRB_NO_BLOCK );
+ printf("non blocking read operations ...\n");
+ sequential_reads( ring, b_len, LFRB_NO_BLOCK );
+ if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); }
+ }
+ for(i=10; i<=50;i*=2) {
+ printf("%d parallel blocking write and read operations .... \n",i*2);
+ parallel_op( 3, i, ring, b_len, 0 );
+ if(!lf_ring_buffer_empty(ring)) { fprintf(stderr,"ring should be empty but is not\n"); exit( EXIT_FAILURE ); }
+ }
+
+ lf_ring_buffer_destroy( ring );
+
+ return EXIT_SUCCESS;
+}
+