queue.c (2920B)
1 #define HEADER_IMPL 2 #include "queue.h" 3 4 #include <assert.h> 5 #include <pthread.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <time.h> 9 10 static const size_t limit = 1000000000; 11 static const size_t qsize = PAGESZ_2M; 12 13 static void * 14 writer(void *data) 15 { 16 struct spsc_queue *queue = data; 17 18 size_t *ptr; 19 for (size_t i = 0; i < limit; i++) { 20 do { 21 ptr = spsc_queue_write(queue, sizeof *ptr); 22 } while (!ptr); 23 24 *ptr = i; 25 26 spsc_queue_write_commit(queue, sizeof *ptr); 27 } 28 29 return (void *) (sizeof *ptr * limit); // return bytes written 30 } 31 32 static void * 33 reader(void *data) 34 { 35 struct spsc_queue *queue = data; 36 37 size_t *ptr; 38 for (size_t i = 0; i < limit; i++) { 39 do { 40 ptr = spsc_queue_read(queue, sizeof *ptr); 41 } while (!ptr); 42 43 ASSERT(*ptr == i); 44 45 spsc_queue_read_commit(queue, sizeof *ptr); 46 } 47 48 return (void *) (sizeof *ptr * limit); // return bytes read 49 } 50 51 static void 52 benchmark(void) 53 { 54 struct spsc_queue queue; 55 int res = spsc_queue_init(&queue, qsize, qsize); 56 assert(res == 0); 57 58 const uint64_t nsecs = 1000000000, usecs = 1000000, msecs = 1000; 59 struct timespec start, end; 60 61 pthread_t writer_thread, reader_thread; 62 pthread_create(&reader_thread, NULL, reader, &queue); 63 pthread_create(&writer_thread, NULL, writer, &queue); 64 65 clock_gettime(CLOCK_MONOTONIC_RAW, &start); 66 67 void *nbytes_written; 68 pthread_join(writer_thread, &nbytes_written); 69 70 void *nbytes_read; 71 pthread_join(reader_thread, &nbytes_read); 72 73 clock_gettime(CLOCK_MONOTONIC_RAW, &end); 74 75 uint64_t ns = ((end.tv_sec - start.tv_sec) * nsecs) + (end.tv_nsec - start.tv_nsec); 76 uint64_t bytes = (uint64_t) nbytes_written + (uint64_t) nbytes_read; 77 double gigs = bytes / (double) GiB(1); 78 79 printf("Iters: %zu\n", limit); 80 printf("Elapsed time: ms: %lu, ns: %lu, avg. ns per iter: %lu\n", 81 ns / usecs, ns, ns / limit); 82 83 printf("Ops/sec: %lu, bytes written: %lu, bytes read: %lu, total GiBps: %.03f\n", 84 (limit * nsecs) / ns, (uint64_t) nbytes_written, (uint64_t) nbytes_read, 85 (float) ((gigs * nsecs) / ns)); 86 } 87 88 int 89 main(void) 90 { 91 benchmark(); 92 93 return 0; 94 95 int *foo = mirrormap(NULL, PAGESZ_4K, PAGESZ_4K, 2, PROT_READ | PROT_WRITE); 96 int *bar = (void *) ((uintptr_t) foo + PAGESZ_4K); 97 98 *foo = 42; 99 assert(*bar == 42); 100 101 munmap(foo, 0); 102 103 struct queue queue; 104 int res = queue_init(&queue, PAGESZ_4K, PAGESZ_4K); 105 assert(res == 0); 106 107 assert(queue_length(&queue) == 0); 108 assert(queue_capacity(&queue) == PAGESZ_4K); 109 110 char buf[] = "Hello, World!"; 111 112 char *mydst = queue_write(&queue, sizeof buf); 113 assert(mydst); 114 queue_write_commit(&queue, sizeof buf); 115 116 strcpy(mydst, buf); 117 118 assert(queue_length(&queue) == sizeof buf); 119 assert(queue_capacity(&queue) == (PAGESZ_4K - sizeof buf)); 120 121 char *mysrc = queue_read(&queue, sizeof buf); 122 assert(mysrc); 123 queue_read_commit(&queue, sizeof buf); 124 125 printf("%s\n", mysrc); 126 127 assert(queue_length(&queue) == 0); 128 assert(queue_capacity(&queue) == PAGESZ_4K); 129 130 queue_free(&queue); 131 132 return 0; 133 }