perf.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. extern "C" {
  15. #include <dba.h>
  16. }
  17. #include <NdbOut.hpp>
  18. #include <NdbSleep.h>
  19. #include <NdbTimer.hpp>
  20. #include <NDBT_Stats.hpp>
  21. #include <NDBT_ReturnCodes.h>
  22. #include <NdbMain.h>
  23. #include <time.h>
  24. #undef min
  25. #undef max
  26. static const int NP_Insert      = 0;
  27. static const int NP_Update      = 1;
  28. static const int NP_WriteUpdate = 2;
  29. static const int NP_WriteInsert = 3;
  30. static const int NP_Delete      = 4;
  31. static const int NP_BulkRead    = 5;
  32. static const int NP_MAX         = 5;
  33. static const char * Operations[] = {
  34.   "Insert  ",
  35.   "Update  ",
  36.   "WriteUpd",
  37.   "WriteIns",
  38.   "Delete  ",
  39.   "BulkRead"
  40. };
  41. /**
  42.  * Configuration variables
  43.  */
  44. static int NoOfTransactions         = 10000;
  45. static int ParallellTransactions    = 1000;
  46. static int OperationsPerTransaction = 10;
  47. static int NoOfColumns              = 20;
  48. static int BytesPerInsert           = 300;
  49. static int BytesPerUpdate           = 200;
  50. static int LoopCount                = 10;
  51. /**
  52.  * Global variables
  53.  */
  54. static char TableName[255];
  55. static DBA_ColumnDesc_t    * ColumnDescriptions;
  56. static DBA_ColumnBinding_t * InsertBindings;
  57. static DBA_ColumnBinding_t * UpdateBindings; static int UpdateBindingColumns;
  58. static DBA_ColumnBinding_t * DeleteBindings;
  59. static char * TestData;
  60. static DBA_Binding_t * InsertB;
  61. static DBA_Binding_t * UpdateB;
  62. static DBA_Binding_t * DeleteB;
  63. /**
  64.  * Function prototypes
  65.  */
  66. static void sequence(int loops);
  67. inline void * getPtr(int rowNo) { return TestData+rowNo*BytesPerInsert;}
  68. inline void   setPK(int rowNo, int pk){ * (int *)getPtr(rowNo) = pk; }
  69. static void SetupTestData();
  70. static void CleanupTestData();
  71. static bool CreateTable();
  72. static bool CleanTable();
  73. static bool CreateBindings();
  74. static void usage();
  75. static
  76. void
  77. usage(){
  78.   int ForceSend, Interval;
  79.   DBA_GetParameter(0, &Interval);
  80.   DBA_GetParameter(3, &ForceSend);
  81.   ndbout << "newtonPerf" << endl
  82.  << "   -n Transactions per loop and operation (" 
  83.  << NoOfTransactions << ")" << endl
  84.  << "   -p parallell transactions (" << ParallellTransactions << ")"
  85.  << endl
  86.  << "   -o operations per transaction (" << OperationsPerTransaction 
  87.  << ")" << endl
  88.  << "   -a no of columns (" << NoOfColumns << ")" << endl
  89.  << "   -b Table size in bytes (" << BytesPerInsert << ")" << endl
  90.  << "   -u Bytes per update (" << BytesPerUpdate << ")" << endl
  91.  << "   -l Loop count (" << LoopCount << ")" << endl
  92.  << "   -i Interval (" << Interval << "ms)" << endl
  93.  << "   -f Force send algorithm (" << ForceSend << ")" << endl
  94.  << "   -h Help" << endl;
  95. }
  96. static
  97. bool
  98. parseArgs(int argc, const char **argv){
  99.   bool a = false, b = false, u = false;
  100.   for(int i = 1; i<argc; i++){
  101.     if(argv[i][0] != '-'){
  102.       ndbout << "Invalid argument: " << argv[i] << endl;
  103.       return false;
  104.     }
  105.     if(argv[i][1] == 'h')
  106.       return false;
  107.     
  108.     if(i == argc-1){
  109.       ndbout << "Expecting argument to " << argv[i] << endl;
  110.       return false;
  111.     }
  112.     
  113.     switch(argv[i][1]){
  114.     case 'n':
  115.       NoOfTransactions = atoi(argv[i+1]);
  116.       break;
  117.     case 'p':
  118.       ParallellTransactions = atoi(argv[i+1]);
  119.       break;
  120.     case 'o':
  121.       OperationsPerTransaction = atoi(argv[i+1]);
  122.       break;
  123.     case 'a':
  124.       NoOfColumns = atoi(argv[i+1]);
  125.       a = true;
  126.       break;
  127.     case 'b':
  128.       BytesPerInsert = atoi(argv[i+1]);
  129.       b = true;
  130.       break;
  131.     case 'u':
  132.       BytesPerUpdate = atoi(argv[i+1]);
  133.       u = true;
  134.       break;
  135.     case 'l':
  136.       LoopCount = atoi(argv[i+1]);
  137.       break;
  138.     case 'f':
  139.       {
  140. const int val = atoi(argv[i+1]);
  141. if(DBA_SetParameter(3, val) != DBA_NO_ERROR){
  142.   ndbout << "Invalid force send algorithm: "  
  143.  << DBA_GetLatestErrorMsg()
  144.  << "(" << DBA_GetLatestError() << ")" << endl;
  145.   return false;
  146. }
  147.       }
  148.       break;
  149.     case 'i':
  150.       {
  151. const int val = atoi(argv[i+1]);
  152. if(DBA_SetParameter(0, val) != DBA_NO_ERROR){
  153.   ndbout << "Invalid NBP interval: " 
  154.  << DBA_GetLatestErrorMsg()
  155.  << "(" << DBA_GetLatestError() << ")" << endl;
  156.   return false;
  157. }
  158.       }
  159.       break;
  160.     default:
  161.       ndbout << "Invalid option: " << argv[i] << endl;
  162.       return false;
  163.     }
  164.     i++;
  165.   }
  166.   if(a && !b) BytesPerInsert = 15 * NoOfColumns;
  167.   if(!a && b) NoOfColumns = ((BytesPerInsert + 14) / 15)+1;
  168.   
  169.   if(!u)
  170.     BytesPerUpdate = (2 * BytesPerInsert) / 3;
  171.   bool t = true;
  172.   if(NoOfColumns < 2) t = false;
  173.   if(BytesPerInsert < 8) t = false;
  174.   if(BytesPerUpdate < 8) t = false;
  175.   
  176.   if(!t){
  177.     ndbout << "Invalid arguments combination of -a -b -u not working out" 
  178.    << endl;
  179.     return false;
  180.   }
  181.   return true;
  182. }
  183. NDB_COMMAND(newton_perf, "newton_perf",
  184.     "newton_perf", "newton_perf", 65535){ 
  185.   
  186.   if(!parseArgs(argc, argv)){
  187.     usage();
  188.     return NDBT_ProgramExit(NDBT_WRONGARGS);
  189.   }
  190.   
  191.   ndbout << "-----------" << endl;
  192.   usage();
  193.   ndbout << endl;
  194.   SetupTestData();
  195.   
  196.   DBA_Open();
  197.   
  198.   if(!CreateTable()){
  199.     DBA_Close();
  200.     CleanupTestData();
  201.     return 0;
  202.   }
  203.   if(!CreateBindings()){
  204.     DBA_Close();
  205.     CleanupTestData();
  206.     return 0;
  207.   }
  208.   CleanTable();
  209.   
  210.   sequence(LoopCount);
  211.   
  212.   DBA_Close();
  213.   CleanupTestData();
  214.   DBA_DestroyBinding(InsertB);
  215.   DBA_DestroyBinding(UpdateB);
  216.   DBA_DestroyBinding(DeleteB);
  217. }
  218. static
  219. void
  220. ErrorMsg(const char * s){
  221.   ndbout << s 
  222.  << ": " << DBA_GetLatestError() << "-" << DBA_GetLatestErrorMsg() 
  223.  << ", " << DBA_GetLatestNdbError()
  224.  << endl;
  225. }
  226. static
  227. int
  228. m4(int i){
  229.   const int j = i - (i & 3);
  230.   return j;
  231. }
  232. static
  233. void
  234. SetupTestData(){
  235.   ndbout << "Creating testdata" << endl;
  236.   ColumnDescriptions = new DBA_ColumnDesc_t[NoOfColumns];
  237.   InsertBindings = new DBA_ColumnBinding_t[NoOfColumns];
  238.   
  239.   const int sz = m4((BytesPerInsert - ((NoOfColumns+1)/2)*4)/(NoOfColumns/2));
  240.   int sum = 0;
  241.   UpdateBindingColumns = 0;
  242.   for(int i = 0; i<NoOfColumns; i++){
  243.     char tmp[16];
  244.     if((i % 2) == 0){
  245.       sprintf(tmp, "I%d", i);
  246.       ColumnDescriptions[i].DataType = DBA_INT;
  247.       ColumnDescriptions[i].Size = 4;
  248.       sum += 4;
  249.     } else {
  250.       sprintf(tmp, "S%d", i);
  251.       ColumnDescriptions[i].DataType = DBA_CHAR;
  252.       ColumnDescriptions[i].Size = sz;
  253.       sum += sz;
  254.     }
  255.     ColumnDescriptions[i].IsKey = 0;
  256.     ColumnDescriptions[i].Name  = strdup(tmp);
  257.     InsertBindings[i].Name     = strdup(tmp);
  258.     InsertBindings[i].DataType = ColumnDescriptions[i].DataType;
  259.     InsertBindings[i].Size     = ColumnDescriptions[i].Size;
  260.     InsertBindings[i].Offset   = sum - ColumnDescriptions[i].Size;
  261.     InsertBindings[i].Ptr      = 0;
  262.     
  263.     if(sum <= BytesPerUpdate)
  264.       UpdateBindingColumns++;
  265.   }
  266.   if(UpdateBindingColumns == 1)
  267.     UpdateBindingColumns++;
  268.   ColumnDescriptions[0].IsKey = 1;
  269.   
  270.   assert(sum <= BytesPerInsert);
  271.   sprintf(TableName, "NEWTON_%d_%d", sum, NoOfColumns);
  272.   
  273.   UpdateBindings = new DBA_ColumnBinding_t[UpdateBindingColumns];
  274.   memcpy(UpdateBindings, InsertBindings, 
  275.  UpdateBindingColumns*sizeof(DBA_ColumnBinding_t));
  276.   
  277.   DeleteBindings = new DBA_ColumnBinding_t[1];
  278.   memcpy(DeleteBindings, InsertBindings, 
  279.  1*sizeof(DBA_ColumnBinding_t));
  280.   
  281.   TestData = (char *)malloc(NoOfTransactions * 
  282.     OperationsPerTransaction * BytesPerInsert);
  283.   
  284.   assert(TestData != 0);
  285.   for(int i = 0; i<NoOfTransactions; i++)
  286.     for(int j = 0; j<OperationsPerTransaction; j++){
  287.       const int pk = i * OperationsPerTransaction + j;
  288.       setPK(pk, pk);
  289.     }
  290. }
  291. static
  292. void
  293. CleanupTestData(){
  294.   free(TestData);
  295.   for(int i = 0; i<NoOfColumns; i++){
  296.     free((char*)ColumnDescriptions[i].Name);
  297.     free((char*)InsertBindings[i].Name);
  298.   }
  299.   delete [] ColumnDescriptions;
  300.   delete [] InsertBindings;
  301.   delete [] UpdateBindings;
  302.   delete [] DeleteBindings;
  303. }
  304. static bool CleanReturnValue = true;
  305. static int  CleanCallbacks = 0;
  306. static int  CleanRows = 0;
  307. extern "C"
  308. void
  309. CleanCallback(DBA_ReqId_t reqId, DBA_Error_t error, DBA_ErrorCode_t ec){
  310.   CleanCallbacks++;
  311.   if(error == DBA_NO_ERROR)
  312.     CleanRows++;
  313. }
  314. static
  315. bool
  316. CleanTable(){
  317.   ndbout << "Cleaning table..." << flush;
  318.   CleanReturnValue = true;
  319.   CleanCallbacks = 0;
  320.   CleanRows = 0;
  321.   for(int i = 0; i<NoOfTransactions * OperationsPerTransaction; i++){
  322.     DBA_ArrayDeleteRows(DeleteB, 
  323. getPtr(i), 1,
  324. CleanCallback);
  325.     while((i-CleanCallbacks)>ParallellTransactions)
  326.       NdbSleep_MilliSleep(100);
  327.   }
  328.   while(CleanCallbacks != (NoOfTransactions * OperationsPerTransaction))
  329.     NdbSleep_SecSleep(1);
  330.   ndbout << CleanRows << " rows deleted" << endl;
  331.   
  332.   return CleanReturnValue;
  333. }
  334. static
  335. bool
  336. CreateBindings(){
  337.   ndbout << "Creating bindings" << endl;
  338.   InsertB = UpdateB = DeleteB = 0;
  339.   
  340.   InsertB = DBA_CreateBinding(TableName, NoOfColumns, 
  341.        InsertBindings, BytesPerInsert);
  342.   if(InsertB == 0){
  343.     ErrorMsg("Failed to create insert bindings");
  344.     return false;
  345.   }
  346.   UpdateB = DBA_CreateBinding(TableName, UpdateBindingColumns,
  347.        UpdateBindings, BytesPerInsert);
  348.   if(UpdateB == 0){
  349.     ErrorMsg("Failed to create update bindings");
  350.     DBA_DestroyBinding(InsertB);
  351.     return false;
  352.   }
  353.   DeleteB = DBA_CreateBinding(TableName, 1, 
  354.        DeleteBindings, BytesPerInsert);
  355.   if(DeleteB == 0){
  356.     ErrorMsg("Failed to create delete bindings");
  357.     DBA_DestroyBinding(InsertB);
  358.     DBA_DestroyBinding(UpdateB);
  359.     return false;
  360.   }
  361.   return true;
  362. }
  363. static
  364. bool
  365. CreateTable(){
  366.   ndbout << "Creating " << TableName << endl;
  367.   return DBA_CreateTable( TableName, 
  368.   NoOfColumns, 
  369.   ColumnDescriptions ) == DBA_NO_ERROR;
  370. }
  371. /**
  372.  * 
  373.  */
  374. static NdbTimer SequenceTimer;
  375. static int CurrentOp    = NP_Insert;
  376. static int SequenceSent = 0;
  377. static int SequenceRecv = 0;
  378. static NDBT_Stats SequenceStats[NP_MAX][4];
  379. static NDBT_Stats SequenceLatency[NP_MAX];
  380. static int           HashMax;
  381. static DBA_ReqId_t * ReqHash;    // ReqId - Latency/Row 
  382. static int         * ReqHashPos; // (row in StartTime)
  383. static int SequenceLatencyPos;
  384. static NDB_TICKS   * StartTime; 
  385. static
  386. inline
  387. int
  388. computeHashMax(int elements){
  389.   HashMax = 1;
  390.   while(HashMax < elements)
  391.     HashMax *= 2;
  392.   
  393.   if(HashMax < 1024)
  394.     HashMax = 1024;
  395.   
  396.   return HashMax;
  397. }
  398. static 
  399. inline
  400. int
  401. hash(DBA_ReqId_t request){
  402.   int r = (request >> 2) & (HashMax-1);
  403.   return r;
  404. }
  405.  
  406. static
  407. inline
  408. void
  409. addRequest(DBA_ReqId_t request, int pos){
  410.   
  411.   int i = hash(request);
  412.   
  413.   while(ReqHash[i] != 0)
  414.     i = ((i + 1) & (HashMax-1));
  415.   
  416.   ReqHash[i] = request;
  417.   ReqHashPos[i] = pos;
  418. }
  419.  
  420. static
  421. inline
  422. int
  423. getRequest(DBA_ReqId_t request){
  424.   
  425.   int i = hash(request);
  426.   
  427.   while(ReqHash[i] != request)
  428.     i = ((i + 1) & (HashMax-1));
  429.   
  430.   ReqHash[i] = 0;
  431.   
  432.   return ReqHashPos[i];
  433. }
  434. extern "C"
  435. void
  436. SequenceCallback(DBA_ReqId_t reqId, DBA_Error_t error, DBA_ErrorCode_t ec){
  437.   int p = getRequest(reqId) - 1;
  438.   
  439.   if(error != DBA_NO_ERROR){
  440.     ndbout << "p = " << p << endl;
  441.     ndbout << "DBA_GetErrorMsg(" << error << ") = " 
  442.    << DBA_GetErrorMsg(error) << endl;
  443.     ndbout << "DBA_GetNdbErrorMsg(" << ec << ") = " 
  444.    << DBA_GetNdbErrorMsg(ec) << endl;
  445.     
  446.     assert(error == DBA_NO_ERROR);
  447.   }
  448.   
  449.   SequenceRecv++;
  450.   if(SequenceRecv == NoOfTransactions){
  451.     SequenceTimer.doStop();
  452.   }
  453.   if((p & 127) == 127){
  454.     NDB_TICKS t = NdbTick_CurrentMillisecond() - StartTime[p];
  455.     SequenceLatency[CurrentOp].addObservation(t);
  456.   }
  457. }
  458. typedef DBA_ReqId_t (* DBA_ArrayFunction)( const DBA_Binding_t* pBindings, 
  459.    const void * pData,
  460.    int NbRows,
  461.    DBA_AsyncCallbackFn_t CbFunc );
  462. inline
  463. int
  464. min(int a, int b){
  465.   return a > b ? b : a;
  466. }
  467. static
  468. void
  469. SequenceOp(DBA_ArrayFunction func, const DBA_Binding_t* pBindings, int op){
  470.   SequenceSent = 0;
  471.   SequenceRecv = 0;
  472.   SequenceLatencyPos = 1;
  473.   CurrentOp = op;
  474.   SequenceTimer.doStart();
  475.   for(int i = 0; i<NoOfTransactions; ){
  476.     const int l1 = ParallellTransactions - (SequenceSent - SequenceRecv);
  477.     const int l2 = min(NoOfTransactions - i, l1);
  478.     for(int j = 0; j<l2; j++){
  479.       const DBA_ReqId_t r = func(pBindings, 
  480.  getPtr(i*OperationsPerTransaction),
  481.  OperationsPerTransaction,
  482.  SequenceCallback);
  483.       assert(r != 0);
  484.       SequenceSent++;
  485.       addRequest(r, i + 1);
  486.       i++;
  487.       
  488.       if((SequenceSent & 127) == 127){
  489. NDB_TICKS t = NdbTick_CurrentMillisecond();
  490. StartTime[i] = t;
  491.       } 
  492.     }
  493.     if(l2 == 0)
  494.       NdbSleep_MilliSleep(10);
  495.   }
  496.   while(SequenceRecv != SequenceSent)
  497.     NdbSleep_SecSleep(1);
  498.   
  499.   ndbout << "Performed " << NoOfTransactions << " " << Operations[op]
  500.  << " in ";
  501.   
  502.   double p = NoOfTransactions * 1000;
  503.   double t = SequenceTimer.elapsedTime();
  504.   double o = p * OperationsPerTransaction;
  505.   
  506.   p /= t;
  507.   o /= t;
  508.   int _p = p;
  509.   int _o = o;
  510.   double b = 0;
  511.   switch(op){
  512.   case NP_Insert:
  513.   case NP_WriteInsert:
  514.   case NP_WriteUpdate:
  515.   case NP_BulkRead:
  516.     b = BytesPerInsert;
  517.     break;
  518.   case NP_Update:
  519.     b = BytesPerUpdate;
  520.     break;
  521.   case NP_Delete:
  522.     b = 4;
  523.     break;
  524.   default:
  525.     b = 0;
  526.   }
  527.   b *= NoOfTransactions * OperationsPerTransaction;
  528.   b /= t;
  529.   int _b = b;
  530.   SequenceStats[op][0].addObservation(t);
  531.   SequenceStats[op][1].addObservation(p);
  532.   SequenceStats[op][2].addObservation(o);
  533.   SequenceStats[op][3].addObservation(b);
  534.   
  535.   int t2 = SequenceStats[op][0].getMean();
  536.   int p2 = SequenceStats[op][1].getMean();
  537.   int o2 = SequenceStats[op][2].getMean();
  538.   int b2 = SequenceStats[op][3].getMean();
  539.   ndbout << SequenceTimer.elapsedTime() << "(" << t2 << ")ms";
  540.   ndbout << " -> " << _p << "(" << p2 << ") T/s - " << _o 
  541.  << "(" << o2 << ") O/s - " << _b << "(" << b2 << ") Kb/s" << endl;
  542.   ndbout << "  Latency (ms) Avg: " << (int)SequenceLatency[op].getMean()
  543.  << " min: " << (int)SequenceLatency[op].getMin() 
  544.  << " max: " << (int)SequenceLatency[op].getMax()
  545.  << " stddev: " << (int)SequenceLatency[op].getStddev() 
  546.  << " n: " << SequenceLatency[op].getCount() << endl;
  547. }
  548. /**
  549.  * Sequence 
  550.  */
  551. static
  552. void
  553. sequence(int loops){
  554.   computeHashMax(ParallellTransactions);
  555.   ReqHash    = new DBA_ReqId_t[HashMax];
  556.   ReqHashPos = new int[HashMax];
  557.   StartTime  = new NDB_TICKS[NoOfTransactions];
  558.   
  559.   for(int i = 0; i<NP_MAX; i++){
  560.     SequenceLatency[i].reset();
  561.     for(int j = 0; j<4; j++)
  562.       SequenceStats[i][j].reset();
  563.   }
  564.   for(int i = 0; i<loops; i++){
  565.     ndbout << "Loop #" << (i+1) << endl;
  566.     SequenceOp(DBA_ArrayInsertRows, InsertB, NP_Insert);
  567.     // BulkRead
  568.     
  569.     SequenceOp(DBA_ArrayUpdateRows, UpdateB, NP_Update);
  570.     SequenceOp(DBA_ArrayWriteRows,  InsertB, NP_WriteUpdate);
  571.     SequenceOp(DBA_ArrayDeleteRows, DeleteB, NP_Delete);
  572.     SequenceOp(DBA_ArrayWriteRows,  InsertB, NP_WriteInsert);
  573.     SequenceOp(DBA_ArrayDeleteRows, DeleteB, NP_Delete);
  574.     ndbout << "-------------------" << endl << endl;
  575.   }
  576.   delete [] ReqHash;
  577.   delete [] ReqHashPos;
  578.   delete [] StartTime;
  579. }