OK. I took your advice and have implemented the following ring buffer. However, after running it through some timing tests I don't really see the performance gain I am going to need. Do you know any way to make the ring buffer faster? I am only seeing speed increases of about 4% when using buffer vs. malloc(). What do you guys think? I apologize in advance for the spacing.
main.c
Code:
#include "ring_buffer.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static int ring_buffer_size = 2000000;
static int block_size = 1600;
ring_buffer_t mem_ring_buffer;
void time_test(void);
int main()
{
time_test();
//thread_test();
return 0;
}
void time_test(void)
{
int i;
clock_t t1,t2;
float f1, f2;
float ratio;
ratio = 1./CLOCKS_PER_SEC;
ring_buffer_init(&mem_ring_buffer, ring_buffer_size, block_size, 0);
t1 = clock();
for(i=0; i<ring_buffer_size; i++)
{
void* memory_chunk = ring_buffer_remove(&mem_ring_buffer);
ring_buffer_add(&mem_ring_buffer, memory_chunk, block_size);
}
t2 = clock();
f1 = ratio*(long)t1 + ratio*(long)t2;
printf("Ring Buffer Time = %f \n", f1);
t1 = clock();
for(i=0; i<ring_buffer_size; i++)
{
void* memory_chunk = malloc(block_size);
free(memory_chunk);
}
t2 = clock();
f2 = ratio*(long)t1 + ratio*(long)t2;
printf("Malloc() Time = %f \n", f2);
printf("Difference of %f. Malloc() is %f # slower than ring buffer.\n", f2-f1, 100-(100* (f1/f2)));
}
ring_buffer.h
Code:
#ifndef RING_BUFFER_H
#define RING_BUFFER_H
#include <pthread.h>
typedef struct ring_buffer_item
{
void* item;
int size;
}ring_buffer_item_t;
typedef struct ring_buffer
{
ring_buffer_item_t* buffer;
unsigned int size;
unsigned int getindex;
unsigned int putindex;
unsigned int num_items;
int use_locks;
pthread_mutex_t rb_mutex;
}ring_buffer_t;
int ring_buffer_init(ring_buffer_t* rb, unsigned int num_blocks, int block_size, int use_locks);
int ring_buffer_add(ring_buffer_t* rb, void* item, int size);
void* ring_buffer_remove(ring_buffer_t* rb);
#endif
ring_buffer.c
Code:
#include "ring_buffer.h"
#include <stdlib.h>
#include <stdio.h>
int ring_buffer_init(ring_buffer_t* rb, unsigned int size, int block_size, int use_locks)
{
int success = 1;
rb->use_locks = use_locks;
pthread_mutex_init(&rb->rb_mutex, NULL);
rb->buffer = calloc(size, sizeof(ring_buffer_item_t));
if(rb->buffer)
{
rb->size = size;
rb->num_items = 0;
rb->getindex = 0;
rb->putindex = 0;
if(block_size)
{
int x;
for(x =0; x<size; x++)
{
rb->buffer[x].item = malloc(block_size);
rb->buffer[x].size = block_size;
if(!rb->buffer[x].item)
{
printf("Could not allocate ring buffer block.\n");
success = 0;
break;
}
}
}
}
else
{
printf("Could not initialize ring buffer.\n");
success = 0;
}
return success;
}
int ring_buffer_add(ring_buffer_t* rb, void* item, int size)
{
if(rb->use_locks)
pthread_mutex_lock(&rb->rb_mutex);
if (rb->num_items >= rb->size)
{
if(rb->use_locks)
pthread_mutex_unlock(&rb->rb_mutex);
return -1;
}
rb->buffer[rb->putindex].item = item;
rb->buffer[rb->putindex].size = size;
rb->putindex = (rb->putindex + 1) % rb->size;
rb->num_items++;
if(rb->use_locks)
pthread_mutex_unlock(&rb->rb_mutex);
return 0;
}
void* ring_buffer_remove(ring_buffer_t* rb)
{
if(rb->use_locks)
pthread_mutex_lock(&rb->rb_mutex);
if ( !rb->num_items )
{
if(rb->use_locks)
pthread_mutex_unlock(&rb->rb_mutex);
return NULL;
}
void* item;
rb->num_items--;
item = rb->buffer[rb->getindex].item;
rb->getindex = (rb->getindex + 1) % rb->size;
if(rb->use_locks)
pthread_mutex_unlock(&rb->rb_mutex);
return item;
}