4
4
#include < stdlib.h>
5
5
#include < inttypes.h>
6
6
#include < sys/time.h>
7
+ #include < unistd.h>
7
8
#include < pthread.h>
8
9
9
10
#include < string>
@@ -22,7 +23,7 @@ template<class T>
22
23
class my_unique_ptr
23
24
{
24
25
T* ptr;
25
-
26
+
26
27
public:
27
28
my_unique_ptr (T* p = NULL ) : ptr(p) {}
28
29
~my_unique_ptr () { delete ptr; }
@@ -32,7 +33,7 @@ class my_unique_ptr
32
33
void operator =(my_unique_ptr& other) {
33
34
ptr = other.ptr ;
34
35
other.ptr = NULL ;
35
- }
36
+ }
36
37
};
37
38
38
39
typedef void * (*thread_proc_t )(void *);
@@ -47,7 +48,7 @@ struct thread
47
48
size_t aborts;
48
49
int id;
49
50
50
- void start (int tid, thread_proc_t proc) {
51
+ void start (int tid, thread_proc_t proc) {
51
52
id = tid;
52
53
updates = 0 ;
53
54
selects = 0 ;
@@ -56,7 +57,7 @@ struct thread
56
57
pthread_create (&t, NULL , proc, this );
57
58
}
58
59
59
- void wait () {
60
+ void wait () {
60
61
pthread_join (t, NULL );
61
62
}
62
63
};
@@ -72,7 +73,7 @@ struct config
72
73
bool scatter;
73
74
bool avoidDeadlocks;
74
75
bool subtransactions;
75
-
76
+
76
77
config () {
77
78
nReaders = 1 ;
78
79
nWriters = 10 ;
@@ -118,7 +119,7 @@ T execQuery( transaction_base& txn, char const* sql, ...)
118
119
va_end (args);
119
120
result r = txn.exec (buf);
120
121
return r[0 ][0 ].as (T ());
121
- }
122
+ }
122
123
123
124
void * reader (void * arg)
124
125
{
@@ -134,7 +135,7 @@ void* reader(void* arg)
134
135
result r = txn.exec (" select sum(v) from t" );
135
136
int64_t sum = r[0 ][0 ].as (int64_t ());
136
137
if (sum != prevSum) {
137
- r = txn.exec (" select mtm.get_snapshot()" );
138
+ r = txn.exec (" select mtm.get_snapshot()" );
138
139
printf (" Total=%ld, snapshot=%ld\n " , sum, r[0 ][0 ].as (int64_t ()));
139
140
prevSum = sum;
140
141
}
@@ -144,7 +145,7 @@ void* reader(void* arg)
144
145
}
145
146
return NULL ;
146
147
}
147
-
148
+
148
149
void * writer (void * arg)
149
150
{
150
151
thread& t = *(thread*)arg;
@@ -153,17 +154,17 @@ void* writer(void* arg)
153
154
conns[i] = new connection (cfg.connections [i]);
154
155
}
155
156
for (int i = 0 ; i < cfg.nIterations ; i++)
156
- {
157
- // work
157
+ {
158
+ // work
158
159
// transaction<repeatable_read> txn(*conns[random() % conns.size()]);
159
160
transaction<read_committed> txn (*conns[random () % conns.size ()]);
160
161
int srcAcc = random () % cfg.nAccounts ;
161
162
int dstAcc = random () % cfg.nAccounts ;
162
- if (cfg.scatter ) {
163
+ if (cfg.scatter ) {
163
164
srcAcc = srcAcc/cfg.nWriters *cfg.nWriters + t.id ;
164
165
dstAcc = dstAcc/cfg.nWriters *cfg.nWriters + t.id ;
165
- } else if (cfg.subtransactions ) {
166
- if (dstAcc < srcAcc) {
166
+ } else if (cfg.subtransactions ) {
167
+ if (dstAcc < srcAcc) {
167
168
int tmp = srcAcc;
168
169
srcAcc = dstAcc;
169
170
dstAcc = tmp;
@@ -173,7 +174,7 @@ void* writer(void* arg)
173
174
subtransaction subtxn (txn, " withdraw" );
174
175
exec (subtxn, " update t set v = v - 1 where u=%d" , srcAcc);
175
176
break ;
176
- } catch (pqxx_exception const & x) {
177
+ } catch (pqxx_exception const & x) {
177
178
t.aborts += 1 ;
178
179
}
179
180
}
@@ -182,36 +183,36 @@ void* writer(void* arg)
182
183
subtransaction subtxn (txn, " deposit" );
183
184
exec (subtxn, " update t set v = v + 1 where u=%d" , dstAcc);
184
185
break ;
185
- } catch (pqxx_exception const & x) {
186
+ } catch (pqxx_exception const & x) {
186
187
t.aborts += 1 ;
187
188
}
188
189
}
189
- txn.commit ();
190
+ txn.commit ();
190
191
t.transactions += 1 ;
191
192
continue ;
192
- } else if (cfg.avoidDeadlocks ) {
193
- if (dstAcc < srcAcc) {
193
+ } else if (cfg.avoidDeadlocks ) {
194
+ if (dstAcc < srcAcc) {
194
195
int tmp = srcAcc;
195
196
srcAcc = dstAcc;
196
197
dstAcc = tmp;
197
198
}
198
199
}
199
- try {
200
- if (random () % 100 < cfg.updatePercent ) {
200
+ try {
201
+ if (random () % 100 < cfg.updatePercent ) {
201
202
exec (txn, " update t set v = v - 1 where u=%d" , srcAcc);
202
203
exec (txn, " update t set v = v + 1 where u=%d" , dstAcc);
203
204
t.updates += 2 ;
204
- } else {
205
+ } else {
205
206
int64_t sum = execQuery<int64_t >(txn, " select v from t where u=%d" , srcAcc)
206
207
+ execQuery<int64_t >(txn, " select v from t where u=%d" , dstAcc);
207
- if (sum > cfg.nIterations *cfg.nWriters || sum < -cfg.nIterations *cfg.nWriters ) {
208
+ if (sum > cfg.nIterations *cfg.nWriters || sum < -cfg.nIterations *cfg.nWriters ) {
208
209
printf (" Wrong sum=%ld\n " , sum);
209
210
}
210
211
t.selects += 2 ;
211
212
}
212
- txn.commit ();
213
+ txn.commit ();
213
214
t.transactions += 1 ;
214
- } catch (pqxx_exception const & x) {
215
+ } catch (pqxx_exception const & x) {
215
216
txn.abort ();
216
217
t.aborts += 1 ;
217
218
i -= 1 ;
@@ -220,7 +221,24 @@ void* writer(void* arg)
220
221
}
221
222
return NULL ;
222
223
}
223
-
224
+
225
+ void * monitor (void * arg)
226
+ {
227
+ vector<thread>& writers = *(vector<thread>*)arg;
228
+ time_t start = time (NULL );
229
+ size_t elapsed = 0 ;
230
+ while (running) {
231
+ sleep (1 );
232
+ long total = 0 ;
233
+ for (int i = 0 ; i < cfg.nWriters ; i++) {
234
+ total += writers[i].transactions ;
235
+ }
236
+ printf (" %d: %5ld TPS\n " , int (time (NULL ) - start), long (total - elapsed));
237
+ elapsed = total;
238
+ }
239
+ return NULL ;
240
+ }
241
+
224
242
void initializeDatabase ()
225
243
{
226
244
connection conn (cfg.connections [0 ]);
@@ -251,15 +269,15 @@ int main (int argc, char* argv[])
251
269
return 1 ;
252
270
}
253
271
254
- for (int i = 1 ; i < argc; i++) {
255
- if (argv[i][0 ] == ' -' ) {
256
- switch (argv[i][1 ]) {
272
+ for (int i = 1 ; i < argc; i++) {
273
+ if (argv[i][0 ] == ' -' ) {
274
+ switch (argv[i][1 ]) {
257
275
case ' r' :
258
276
cfg.nReaders = atoi (argv[++i]);
259
277
continue ;
260
278
case ' w' :
261
279
cfg.nWriters = atoi (argv[++i]);
262
- continue ;
280
+ continue ;
263
281
case ' a' :
264
282
cfg.nAccounts = atoi (argv[++i]);
265
283
continue ;
@@ -300,7 +318,7 @@ int main (int argc, char* argv[])
300
318
return 1 ;
301
319
}
302
320
303
- if (initialize) {
321
+ if (initialize) {
304
322
initializeDatabase ();
305
323
printf (" %d accounts inserted\n " , cfg.nAccounts );
306
324
return 0 ;
@@ -311,34 +329,38 @@ int main (int argc, char* argv[])
311
329
312
330
vector<thread> readers (cfg.nReaders );
313
331
vector<thread> writers (cfg.nWriters );
332
+ pthread_t logger;
333
+
314
334
size_t nAborts = 0 ;
315
335
size_t nUpdates = 0 ;
316
336
size_t nSelects = 0 ;
317
337
size_t nTransactions = 0 ;
318
338
319
- for (int i = 0 ; i < cfg.nReaders ; i++) {
339
+ for (int i = 0 ; i < cfg.nReaders ; i++) {
320
340
readers[i].start (i, reader);
321
341
}
322
- for (int i = 0 ; i < cfg.nWriters ; i++) {
342
+ for (int i = 0 ; i < cfg.nWriters ; i++) {
323
343
writers[i].start (i, writer);
324
344
}
325
-
326
- for (int i = 0 ; i < cfg.nWriters ; i++) {
345
+ pthread_create (&logger, NULL , monitor, &writers);
346
+
347
+ for (int i = 0 ; i < cfg.nWriters ; i++) {
327
348
writers[i].wait ();
328
349
nUpdates += writers[i].updates ;
329
350
nSelects += writers[i].selects ;
330
351
nAborts += writers[i].aborts ;
331
352
nTransactions += writers[i].transactions ;
332
353
}
333
-
354
+
334
355
running = false ;
335
356
336
- for (int i = 0 ; i < cfg.nReaders ; i++) {
357
+ for (int i = 0 ; i < cfg.nReaders ; i++) {
337
358
readers[i].wait ();
338
359
nSelects += readers[i].selects ;
339
360
nTransactions += writers[i].transactions ;
340
361
}
341
-
362
+ pthread_join (logger, NULL );
363
+
342
364
time_t elapsed = getCurrentTime () - start;
343
365
344
366
printf (
@@ -347,10 +369,10 @@ int main (int argc, char* argv[])
347
369
" \" readers\" :%d, \" writers\" :%d, \" update_percent\" :%d, \" accounts\" :%d, \" iterations\" :%d, \" hosts\" :%ld}\n " ,
348
370
(double )(nTransactions*USEC)/elapsed,
349
371
nTransactions,
350
- nSelects,
372
+ nSelects,
351
373
nUpdates,
352
374
nAborts,
353
- (int )(nAborts*100 /nTransactions),
375
+ (int )(nAborts*100 /nTransactions),
354
376
cfg.nReaders ,
355
377
cfg.nWriters ,
356
378
cfg.updatePercent ,
0 commit comments