MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testReadPerf.cpp
1 /*
2  Copyright (C) 2004-2006 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <NDBT.hpp>
20 #include <NDBT_Test.hpp>
21 #include <HugoTransactions.hpp>
22 #include <UtilTransactions.hpp>
23 #include <random.h>
24 #include <getarg.h>
25 
26 struct Parameter {
27  const char * name;
28  unsigned value;
29  unsigned min;
30  unsigned max;
31 };
32 
33 #define P_OPER 0
34 #define P_RANGE 1
35 #define P_ROWS 2
36 #define P_LOOPS 3
37 #define P_CREATE 4
38 #define P_LOAD 5
39 
40 #define P_MAX 6
41 
53 static const char * g_ops[] = {
54  "serial pk",
55  "batch pk",
56  "serial uniq index access",
57  "batch uniq index access",
58  "index eq-bound",
59  "index range",
60  "index ordered",
61  "interpreted scan"
62 };
63 
64 #define P_OP_TYPES 8
65 static Uint64 g_times[P_OP_TYPES];
66 
67 static
68 Parameter
69 g_paramters[] = {
70  { "operation", 0, 0, 6 }, // 0
71  { "range", 1000, 1, ~0 },// 1 no of rows to read
72  { "size", 1000000, 1, ~0 },// 2 rows in tables
73  { "iterations", 3, 1, ~0 },// 3
74  { "create_drop", 0, 0, 1 }, // 4
75  { "data", 0, 0, 1 } // 5
76 };
77 
78 static Ndb* g_ndb = 0;
79 static const NdbDictionary::Table * g_tab;
80 static const NdbDictionary::Index * g_i_unique;
81 static const NdbDictionary::Index * g_i_ordered;
82 static char g_table[256];
83 static char g_unique[256];
84 static char g_ordered[256];
85 
86 int create_table();
87 int load_table();
88 int run_read();
89 int clear_table();
90 int drop_table();
91 void print_result();
92 
93 int
94 main(int argc, const char** argv){
95  ndb_init();
96  int verbose = 1;
97  int optind = 0;
98 
99  struct getargs args[1+P_MAX] = {
100  { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
101  };
102  const int num_args = 1 + P_MAX;
103  int i;
104  for(i = 0; i<P_MAX; i++){
105  args[i+1].long_name = g_paramters[i].name;
106  args[i+1].short_name = * g_paramters[i].name;
107  args[i+1].type = arg_integer;
108  args[i+1].value = &g_paramters[i].value;
109  BaseString tmp;
110  tmp.assfmt("min: %d max: %d", g_paramters[i].min, g_paramters[i].max);
111  args[i+1].help = strdup(tmp.c_str());
112  args[i+1].arg_help = 0;
113  }
114 
115  if(getarg(args, num_args, argc, argv, &optind)) {
116  arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ...");
117  return NDBT_WRONGARGS;
118  }
119 
120  myRandom48Init((long)NdbTick_CurrentMillisecond());
121  memset(g_times, 0, sizeof(g_times));
122 
124  if(con.connect(12, 5, 1))
125  {
126  return NDBT_ProgramExit(NDBT_FAILED);
127  }
128 
129  g_ndb = new Ndb(&con, "TEST_DB");
130  if(g_ndb->init() != 0){
131  g_err << "init() failed" << endl;
132  goto error;
133  }
134  if(g_ndb->waitUntilReady() != 0){
135  g_err << "Wait until ready failed" << endl;
136  goto error;
137  }
138  for(i = optind; i<argc; i++){
139  const char * T = argv[i];
140  g_info << "Testing " << T << endl;
141  BaseString::snprintf(g_table, sizeof(g_table), "%s", T);
142  BaseString::snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
143  BaseString::snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
144  if(create_table())
145  goto error;
146  if(load_table())
147  goto error;
148  for(int l = 0; l<(int)g_paramters[P_LOOPS].value; l++){
149  for(int j = 0; j<P_OP_TYPES; j++){
150  g_paramters[P_OPER].value = j;
151  if(run_read())
152  goto error;
153  }
154  }
155  print_result();
156  }
157 
158  if(g_ndb) delete g_ndb;
159  return NDBT_OK;
160 error:
161  if(g_ndb) delete g_ndb;
162  return NDBT_FAILED;
163 }
164 
165 int
166 create_table(){
167  NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
168  assert(dict);
169  if(g_paramters[P_CREATE].value){
170  const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_table);
171  assert(pTab);
172  NdbDictionary::Table copy = * pTab;
173  copy.setLogging(false);
174  if(dict->createTable(copy) != 0){
175  g_err << "Failed to create table: " << g_table << endl;
176  return -1;
177  }
178 
179  NdbDictionary::Index x(g_ordered);
180  x.setTable(g_table);
182  x.setLogging(false);
183  for (unsigned k = 0; k < (unsigned)copy.getNoOfColumns(); k++){
184  if(copy.getColumn(k)->getPrimaryKey()){
185  x.addColumn(copy.getColumn(k)->getName());
186  }
187  }
188 
189  if(dict->createIndex(x) != 0){
190  g_err << "Failed to create index: " << endl;
191  return -1;
192  }
193 
194  x.setName(g_unique);
196  if(dict->createIndex(x) != 0){
197  g_err << "Failed to create index: " << endl;
198  return -1;
199  }
200  }
201  g_tab = dict->getTable(g_table);
202  g_i_unique = dict->getIndex(g_unique, g_table);
203  g_i_ordered = dict->getIndex(g_ordered, g_table);
204  assert(g_tab);
205  assert(g_i_unique);
206  assert(g_i_ordered);
207  return 0;
208 }
209 
210 int
211 drop_table(){
212  if(!g_paramters[P_CREATE].value)
213  return 0;
214  if(g_ndb->getDictionary()->dropTable(g_tab->getName()) != 0){
215  g_err << "Failed to drop table: " << g_tab->getName() << endl;
216  return -1;
217  }
218  g_tab = 0;
219  return 0;
220 }
221 
222 int
223 load_table(){
224  if(!g_paramters[P_LOAD].value)
225  return 0;
226 
227  int rows = g_paramters[P_ROWS].value;
228  HugoTransactions hugoTrans(* g_tab);
229  if (hugoTrans.loadTable(g_ndb, rows)){
230  g_err.println("Failed to load %s with %d rows", g_tab->getName(), rows);
231  return -1;
232  }
233  return 0;
234 }
235 
236 int
237 clear_table(){
238  if(!g_paramters[P_LOAD].value)
239  return 0;
240  int rows = g_paramters[P_ROWS].value;
241 
242  UtilTransactions utilTrans(* g_tab);
243  if (utilTrans.clearTable(g_ndb, rows) != 0){
244  g_err.println("Failed to clear table %s", g_tab->getName());
245  return -1;
246  }
247  return 0;
248 }
249 
250 inline
251 void err(NdbError e){
252  ndbout << e << endl;
253 }
254 
255 int
256 run_read(){
257  //int iter = g_paramters[P_LOOPS].value;
258  NDB_TICKS start1, stop;
259  //int sum_time= 0;
260 
261  const Uint32 rows = g_paramters[P_ROWS].value;
262  const Uint32 range = g_paramters[P_RANGE].value;
263 
264  start1 = NdbTick_CurrentMillisecond();
265  NdbConnection * pTrans = g_ndb->startTransaction();
266  if(!pTrans){
267  g_err << "Failed to start transaction" << endl;
268  err(g_ndb->getNdbError());
269  return -1;
270  }
271 
272  NdbOperation * pOp;
273  NdbScanOperation * pSp;
274  NdbIndexScanOperation * pIp;
275 
276  Uint32 start_row = rand() % (rows - range);
277  Uint32 stop_row = start_row + range;
278 
288  int check = 0;
289  void* res = (void*)~0;
290  const Uint32 pk = 0;
291  Uint32 cnt = 0;
292  for(; start_row < stop_row; start_row++){
293  switch(g_paramters[P_OPER].value){
294  case 0:
295  pOp = pTrans->getNdbOperation(g_table);
296  check = pOp->readTuple();
297  check = pOp->equal(pk, start_row);
298  break;
299  case 1:
300  for(; start_row<stop_row; start_row++){
301  pOp = pTrans->getNdbOperation(g_table);
302  check = pOp->readTuple();
303  check = pOp->equal(pk, start_row);
304  for(int j = 0; j<g_tab->getNoOfColumns(); j++){
305  res = pOp->getValue(j);
306  assert(res);
307  }
308  }
309  break;
310  case 2:
311  pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
312  check = pOp->readTuple();
313  check = pOp->equal(pk, start_row);
314  break;
315  case 3:
316  for(; start_row<stop_row; start_row++){
317  pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
318  check = pOp->readTuple();
319  check = pOp->equal(pk, start_row);
320  for(int j = 0; j<g_tab->getNoOfColumns(); j++){
321  res = pOp->getValue(j);
322  assert(res);
323  }
324  }
325  break;
326  case 4:
327  pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
329  check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
330  break;
331  case 5:
332  pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
334  check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
335  check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
336  start_row = stop_row;
337  break;
338  case 6:
339  pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
341  check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
342  check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
343  start_row = stop_row;
344  break;
345  case 7:
346  pOp = pSp = pTrans->getNdbScanOperation(g_table);
348  NdbScanFilter filter(pOp) ;
349  filter.begin(NdbScanFilter::AND);
350  filter.ge(pk, start_row);
351  filter.lt(pk, stop_row);
352  filter.end();
353  start_row = stop_row;
354  break;
355  }
356 
357  assert(res);
358  if(check != 0){
359  ndbout << pOp->getNdbError() << endl;
360  ndbout << pTrans->getNdbError() << endl;
361  }
362  assert(check == 0);
363 
364  for(int j = 0; j<g_tab->getNoOfColumns(); j++){
365  res = pOp->getValue(j);
366  assert(res);
367  }
368 
369  check = pTrans->execute(NoCommit);
370  if(check != 0){
371  ndbout << pTrans->getNdbError() << endl;
372  }
373  assert(check == 0);
374  if(g_paramters[P_OPER].value >= 4){
375  while((check = pSp->nextResult(true)) == 0){
376  cnt++;
377  }
378 
379  if(check == -1){
380  err(pTrans->getNdbError());
381  return -1;
382  }
383  assert(check == 1);
384  pSp->close();
385  }
386  }
387  assert(g_paramters[P_OPER].value < 4 || (cnt == range));
388 
389  pTrans->close();
390 
391  stop = NdbTick_CurrentMillisecond();
392  g_times[g_paramters[P_OPER].value] += (stop - start1);
393  return 0;
394 }
395 
396 void
397 print_result(){
398  int tmp = 1;
399  tmp *= g_paramters[P_RANGE].value;
400  tmp *= g_paramters[P_LOOPS].value;
401 
402  for(int i = 0; i<P_OP_TYPES; i++){
403  g_err << g_ops[i] << " avg: "
404  << (int)((1000*g_times[i])/tmp)
405  << " us/row ("
406  << (1000 * tmp)/g_times[i] << " rows / sec)" << endl;
407  }
408 }