Port it to use the new Linux perf_event API rather than the old perfmon patch.
[beedb.git] / perf / lffifo.cc
blob3d957274155c9402a877de8d86fe293721c81fd8
1 /*
2 Copyright 2009 Kristian Nielsen
4 This file is part of BeeDB.
6 Foobar is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Foobar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Foobar. If not, see <http://www.gnu.org/licenses/>.
22 Performance test for lffifo classes, experimenting with memory barrier
23 performance.
26 #include "port/format_macros.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
32 #include <pthread.h>
34 #include "beedb.h"
35 #include "perftest.h"
38 /* Yeah, would be better with proper lffifo.h interface file. */
39 #include "../exp/lffifo.cc"
43 Run a performance test on some variant of a lock-free fifo.
45 Use a template, as overhead of virtual function call etc. could potentially
46 dwarf what we are measuring.
48 Run a loop writing or reading a lffifo, with a (non-measured) thread
49 handling the other end of the lffifo.
51 template<class LF>
52 class pf_lffifo : public perftest::test {
53 public:
54 /* Which end are we testing: writer or reader? */
55 enum enum_tested_end
57 TEST_WRITER,
58 TEST_READER
61 pf_lffifo(perftest *tester, const char *variant, enum_tested_end _what_tested,
62 uint64_t fifo_size, uint64_t _batch_size) :
63 test(tester,
64 (_what_tested == TEST_WRITER ? "lffifo_writer" : "lffifo_reader"),
65 variant, param1_buf, param2_buf, _batch_size),
66 what_tested(_what_tested),
67 batch_size(_batch_size),
68 my_lffifo(fifo_size)
70 memset(param1_buf, 0, sizeof(param1_buf));
71 snprintf(param1_buf, sizeof(param1_buf) - 1,
72 "batch=%" PRIu64, batch_size);
73 memset(param2_buf, 0, sizeof(param2_buf));
74 snprintf(param2_buf, sizeof(param2_buf) - 1,
75 "fifosize=%" PRIu64, fifo_size);
78 void run(uint64_t loops);
79 void *other_end_thread_func();
81 private:
82 enum_tested_end what_tested;
83 uint64_t batch_size;
84 char param1_buf[100];
85 char param2_buf[100];
86 uint64_t loops;
87 LF my_lffifo;
90 template<class LF>
91 static void *
92 lffifo_other_end(void *arg)
94 pf_lffifo<LF> *test= static_cast<pf_lffifo<LF> *>(arg);
95 return test->other_end_thread_func();
98 template<class LF>
99 void
100 pf_lffifo<LF>::run(uint64_t loops)
102 int err;
103 pthread_t my_thread;
105 this->loops= loops;
107 err= pthread_create(&my_thread, NULL, lffifo_other_end<LF>, this);
108 if (err)
109 fatal_error("Error: could not create thread: %d\n", err);
111 my_lffifo.reset_stats();
113 start();
115 uint64_t v= 1;
116 uint64_t count= loops;
117 uint64_t sum= 0;
118 uint64_t flush_count= batch_size;
119 while (count--)
121 my_lffifo.put(v);
122 if (!(flush_count--))
124 my_lffifo.write_flush();
125 flush_count= batch_size;
127 sum+= v;
128 v++;
131 record_time(text);
132 /* Make sure other end will get the last bits. */
133 my_lffifo.write_flush();
135 printf("Producer: cpu=%d sum=%" PRIu64 " spins=%" PRIu64 " buf=%p\n",
136 sched_getcpu(), sum, my_lffifo.wr_spin_loops, my_lffifo.buffer);
138 void *dummy_result;
139 err= pthread_join(my_thread, &dummy_result);
140 if (err)
141 fprintf(stderr, "Warning: pthread_join() failed: %d\n", err);
144 template<class LF>
145 void *
146 pf_lffifo<LF>::other_end_thread_func()
148 uint64_t count= loops;
149 uint64_t sum= 0;
151 while (count--)
153 uint64_t v= my_lffifo.get();
154 sum+= v;
157 printf(" Consumer: cpu=%d sum=%" PRIu64 " spins=%" PRIu64 "\n",
158 sched_getcpu(), sum, my_lffifo.rd_spin_loops);
159 return NULL;
163 main(int argc, char *argv[])
165 perftest tester;
167 pf_lffifo<lffifo> t1(&tester, "lffifo", pf_lffifo<lffifo>::TEST_WRITER, 1024, 16);
168 tester.run_test(&t1, 100000000);
170 return 0;