/* Copyright (c) 2003-2005 MySQL AB Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include extern "C" { #include } #include #include #include #include #include #include #include #undef min #undef max static const int NP_Insert = 0; static const int NP_Update = 1; static const int NP_WriteUpdate = 2; static const int NP_WriteInsert = 3; static const int NP_Delete = 4; static const int NP_BulkRead = 5; static const int NP_MAX = 5; static const char * Operations[] = { "Insert ", "Update ", "WriteUpd", "WriteIns", "Delete ", "BulkRead" }; /** * Configuration variables */ static int NoOfTransactions = 10000; static int ParallellTransactions = 1000; static int OperationsPerTransaction = 10; static int NoOfColumns = 20; static int BytesPerInsert = 300; static int BytesPerUpdate = 200; static int LoopCount = 10; /** * Global variables */ static char TableName[255]; static DBA_ColumnDesc_t * ColumnDescriptions; static DBA_ColumnBinding_t * InsertBindings; static DBA_ColumnBinding_t * UpdateBindings; static int UpdateBindingColumns; static DBA_ColumnBinding_t * DeleteBindings; static char * TestData; static DBA_Binding_t * InsertB; static DBA_Binding_t * UpdateB; static DBA_Binding_t * DeleteB; /** * Function prototypes */ static void sequence(int loops); inline void * getPtr(int rowNo) { return TestData+rowNo*BytesPerInsert;} inline void setPK(int rowNo, int pk){ * (int *)getPtr(rowNo) = pk; } static void SetupTestData(); static void CleanupTestData(); static bool CreateTable(); static bool CleanTable(); static bool CreateBindings(); static void usage(); static void usage(){ int ForceSend, Interval; DBA_GetParameter(0, &Interval); DBA_GetParameter(3, &ForceSend); ndbout << "newtonPerf" << endl << " -n Transactions per loop and operation (" << NoOfTransactions << ")" << endl << " -p parallell transactions (" << ParallellTransactions << ")" << endl << " -o operations per transaction (" << OperationsPerTransaction << ")" << endl << " -a no of columns (" << NoOfColumns << ")" << endl << " -b Table size in bytes (" << BytesPerInsert << ")" << endl << " -u Bytes per update (" << BytesPerUpdate << ")" << endl << " -l Loop count (" << LoopCount << ")" << endl << " -i Interval (" << Interval << "ms)" << endl << " -f Force send algorithm (" << ForceSend << ")" << endl << " -h Help" << endl; } static bool parseArgs(int argc, const char **argv){ bool a = false, b = false, u = false; for(int i = 1; iParallellTransactions) NdbSleep_MilliSleep(100); } while(CleanCallbacks != (NoOfTransactions * OperationsPerTransaction)) NdbSleep_SecSleep(1); ndbout << CleanRows << " rows deleted" << endl; return CleanReturnValue; } static bool CreateBindings(){ ndbout << "Creating bindings" << endl; InsertB = UpdateB = DeleteB = 0; InsertB = DBA_CreateBinding(TableName, NoOfColumns, InsertBindings, BytesPerInsert); if(InsertB == 0){ ErrorMsg("Failed to create insert bindings"); return false; } UpdateB = DBA_CreateBinding(TableName, UpdateBindingColumns, UpdateBindings, BytesPerInsert); if(UpdateB == 0){ ErrorMsg("Failed to create update bindings"); DBA_DestroyBinding(InsertB); return false; } DeleteB = DBA_CreateBinding(TableName, 1, DeleteBindings, BytesPerInsert); if(DeleteB == 0){ ErrorMsg("Failed to create delete bindings"); DBA_DestroyBinding(InsertB); DBA_DestroyBinding(UpdateB); return false; } return true; } static bool CreateTable(){ ndbout << "Creating " << TableName << endl; return DBA_CreateTable( TableName, NoOfColumns, ColumnDescriptions ) == DBA_NO_ERROR; } /** * */ static NdbTimer SequenceTimer; static int CurrentOp = NP_Insert; static int SequenceSent = 0; static int SequenceRecv = 0; static NDBT_Stats SequenceStats[NP_MAX][4]; static NDBT_Stats SequenceLatency[NP_MAX]; static int HashMax; static DBA_ReqId_t * ReqHash; // ReqId - Latency/Row static int * ReqHashPos; // (row in StartTime) static int SequenceLatencyPos; static NDB_TICKS * StartTime; static inline int computeHashMax(int elements){ HashMax = 1; while(HashMax < elements) HashMax *= 2; if(HashMax < 1024) HashMax = 1024; return HashMax; } static inline int hash(DBA_ReqId_t request){ int r = (request >> 2) & (HashMax-1); return r; } static inline void addRequest(DBA_ReqId_t request, int pos){ int i = hash(request); while(ReqHash[i] != 0) i = ((i + 1) & (HashMax-1)); ReqHash[i] = request; ReqHashPos[i] = pos; } static inline int getRequest(DBA_ReqId_t request){ int i = hash(request); while(ReqHash[i] != request) i = ((i + 1) & (HashMax-1)); ReqHash[i] = 0; return ReqHashPos[i]; } extern "C" void SequenceCallback(DBA_ReqId_t reqId, DBA_Error_t error, DBA_ErrorCode_t ec){ int p = getRequest(reqId) - 1; if(error != DBA_NO_ERROR){ ndbout << "p = " << p << endl; ndbout << "DBA_GetErrorMsg(" << error << ") = " << DBA_GetErrorMsg(error) << endl; ndbout << "DBA_GetNdbErrorMsg(" << ec << ") = " << DBA_GetNdbErrorMsg(ec) << endl; assert(error == DBA_NO_ERROR); } SequenceRecv++; if(SequenceRecv == NoOfTransactions){ SequenceTimer.doStop(); } if((p & 127) == 127){ NDB_TICKS t = NdbTick_CurrentMillisecond() - StartTime[p]; SequenceLatency[CurrentOp].addObservation(t); } } typedef DBA_ReqId_t (* DBA_ArrayFunction)( const DBA_Binding_t* pBindings, const void * pData, int NbRows, DBA_AsyncCallbackFn_t CbFunc ); inline int min(int a, int b){ return a > b ? b : a; } static void SequenceOp(DBA_ArrayFunction func, const DBA_Binding_t* pBindings, int op){ SequenceSent = 0; SequenceRecv = 0; SequenceLatencyPos = 1; CurrentOp = op; SequenceTimer.doStart(); for(int i = 0; i " << _p << "(" << p2 << ") T/s - " << _o << "(" << o2 << ") O/s - " << _b << "(" << b2 << ") Kb/s" << endl; ndbout << " Latency (ms) Avg: " << (int)SequenceLatency[op].getMean() << " min: " << (int)SequenceLatency[op].getMin() << " max: " << (int)SequenceLatency[op].getMax() << " stddev: " << (int)SequenceLatency[op].getStddev() << " n: " << SequenceLatency[op].getCount() << endl; } /** * Sequence */ static void sequence(int loops){ computeHashMax(ParallellTransactions); ReqHash = new DBA_ReqId_t[HashMax]; ReqHashPos = new int[HashMax]; StartTime = new NDB_TICKS[NoOfTransactions]; for(int i = 0; i