diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp clean_dolphin_sched/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp --- mysql-5.1.12/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp 2006-05-18 02:50:46 -04:00 +++ clean_dolphin_sched/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp 2006-11-09 09:17:50 -05:00 @@ -72,6 +72,8 @@ NdbfsDumpAllFiles = 401, NdbfsDumpOpenFiles = 402, NdbfsDumpIdleFiles = 403, + CmvmiSchedulerExecutionTimer = 502, + CmvmiSchedulerSpinTimer = 506, // 1222-1225 DICT LqhDumpAllDefinedTabs = 1332, LqhDumpNoLogPages = 1333, diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/include/mgmapi/mgmapi_config_parameters.h clean_dolphin_sched/storage/ndb/include/mgmapi/mgmapi_config_parameters.h --- mysql-5.1.12/storage/ndb/include/mgmapi/mgmapi_config_parameters.h 2006-08-31 18:09:09 -04:00 +++ clean_dolphin_sched/storage/ndb/include/mgmapi/mgmapi_config_parameters.h 2006-10-03 08:55:11 -04:00 @@ -96,6 +96,9 @@ #define CFG_DB_CHECKPOINT_SPEED 164 #define CFG_DB_CHECKPOINT_SPEED_SR 165 +#define CFG_DB_SCHED_EXEC_TIME 166 +#define CFG_DB_SCHED_SPIN_TIME 167 + #define CFG_DB_SGA 198 /* super pool mem */ #define CFG_DB_DATA_MEM_2 199 /* used in special build in 5.1 */ diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/include/mgmapi/ndb_logevent.h clean_dolphin_sched/storage/ndb/include/mgmapi/ndb_logevent.h --- mysql-5.1.12/storage/ndb/include/mgmapi/ndb_logevent.h 2006-04-06 07:18:10 -04:00 +++ clean_dolphin_sched/storage/ndb/include/mgmapi/ndb_logevent.h 2006-10-03 05:45:29 -04:00 @@ -133,6 +133,8 @@ NDB_LE_ReceiveBytesStatistic = 41, /** NDB_MGM_EVENT_CATEGORY_STATISTIC */ NDB_LE_MemoryUsage = 50, + /** NDB_MGM_EVENT_CATEGORY_STATISTIC */ + NDB_LE_ThreadConfigLoop = 61, /** NDB_MGM_EVENT_CATEGORY_ERROR */ NDB_LE_TransporterError = 42, @@ -176,8 +178,8 @@ /** NDB_MGM_EVENT_CATEGORY_STARTUP */ NDB_LE_StartReport = 60 - /* 60 unused */ - /* 61 unused */ + /* 60 used */ + /* 61 used */ /* 62 unused */ }; diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/include/portlib/NdbTick.h clean_dolphin_sched/storage/ndb/include/portlib/NdbTick.h --- mysql-5.1.12/storage/ndb/include/portlib/NdbTick.h 2005-04-07 20:43:54 -04:00 +++ clean_dolphin_sched/storage/ndb/include/portlib/NdbTick.h 2006-09-25 06:39:00 -04:00 @@ -42,7 +42,7 @@ */ int NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros); - /*#define TIME_MEASUREMENT*/ +#define TIME_MEASUREMENT #ifdef TIME_MEASUREMENT struct MicroSecondTimer { diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/common/debugger/EventLogger.cpp clean_dolphin_sched/storage/ndb/src/common/debugger/EventLogger.cpp --- mysql-5.1.12/storage/ndb/src/common/debugger/EventLogger.cpp 2006-04-06 06:24:09 -04:00 +++ clean_dolphin_sched/storage/ndb/src/common/debugger/EventLogger.cpp 2006-10-03 05:45:29 -04:00 @@ -558,6 +558,12 @@ "Mean loop Counter in doJob last 8192 times = %u", theData[1]); } +void getTextThreadConfigLoop(QQQQ) { + BaseString::snprintf(m_text, m_text_len, + "8192 loops,tot %u usec,exec %u extra:loops = %u,time %u,const %u", + theData[1], theData[3], theData[4], theData[5], + theData[2]); +} void getTextSendBytesStatistic(QQQQ) { BaseString::snprintf(m_text, m_text_len, "Mean send size to Node = %d last 4096 sends = %u bytes", @@ -898,6 +904,7 @@ ROW(OperationReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO ), ROW(TableCreated, LogLevel::llStatistic, 7, Logger::LL_INFO ), ROW(JobStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ), + ROW(ThreadConfigLoop, LogLevel::llStatistic, 9, Logger::LL_INFO ), ROW(SendBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ), ROW(ReceiveBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ), ROW(MemoryUsage, LogLevel::llStatistic, 5, Logger::LL_INFO ), diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp clean_dolphin_sched/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp --- mysql-5.1.12/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2006-06-09 06:40:01 -04:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2006-11-09 09:17:50 -05:00 @@ -1147,7 +1147,16 @@ } return; } - + if (arg == DumpStateOrd::CmvmiSchedulerExecutionTimer) + { + Uint32 exec_time = signal->theData[1]; + globalEmulatorData.theConfiguration->schedulerExecutionTimer(exec_time); + } + if (arg == DumpStateOrd::CmvmiSchedulerSpinTimer) + { + Uint32 spin_time = signal->theData[1]; + globalEmulatorData.theConfiguration->schedulerSpinTimer(spin_time); + } if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert) { if(signal->getLength() == 1) diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/vm/Configuration.cpp clean_dolphin_sched/storage/ndb/src/kernel/vm/Configuration.cpp --- mysql-5.1.12/storage/ndb/src/kernel/vm/Configuration.cpp 2006-10-16 15:33:30 -04:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/vm/Configuration.cpp 2006-10-21 13:23:41 -04:00 @@ -444,6 +444,15 @@ "TimeBetweenWatchDogCheck missing"); } + if(iter.get(CFG_DB_SCHED_EXEC_TIME, &_schedulerExecutionTimer)){ + ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", + "SchedulerExecutionTimer missing"); + } + if(iter.get(CFG_DB_SCHED_SPIN_TIME, &_schedulerSpinTimer)){ + ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", + "SchedulerSpinTimer missing"); + } + /** * Get paths */ @@ -483,6 +492,28 @@ bool Configuration::lockPagesInMainMemory() const { return _lockPagesInMainMemory; +} + +int +Configuration::schedulerExecutionTimer() const { + return _schedulerExecutionTimer; +} + +void +Configuration::schedulerExecutionTimer(int value) { + if (value < 11000) + _schedulerExecutionTimer = value; +} + +int +Configuration::schedulerSpinTimer() const { + return _schedulerSpinTimer; +} + +void +Configuration::schedulerSpinTimer(int value) { + if (value < 11000) + _schedulerSpinTimer = value; } int diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/vm/Configuration.hpp clean_dolphin_sched/storage/ndb/src/kernel/vm/Configuration.hpp --- mysql-5.1.12/storage/ndb/src/kernel/vm/Configuration.hpp 2006-02-09 05:34:38 -05:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/vm/Configuration.hpp 2006-10-03 08:55:11 -04:00 @@ -38,7 +38,13 @@ void closeConfiguration(bool end_session= true); bool lockPagesInMainMemory() const; - + + int schedulerExecutionTimer() const; + void schedulerExecutionTimer(int value); + + int schedulerSpinTimer() const; + void schedulerSpinTimer(int value); + int timeBetweenWatchDogCheck() const ; void timeBetweenWatchDogCheck(int value); @@ -85,6 +91,8 @@ Uint32 _maxErrorLogs; Uint32 _lockPagesInMainMemory; Uint32 _timeBetweenWatchDogCheck; + Uint32 _schedulerExecutionTimer; + Uint32 _schedulerSpinTimer; ndb_mgm_configuration * m_ownConfig; ndb_mgm_configuration * m_clusterConfig; diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/vm/FastScheduler.cpp clean_dolphin_sched/storage/ndb/src/kernel/vm/FastScheduler.cpp --- mysql-5.1.12/storage/ndb/src/kernel/vm/FastScheduler.cpp 2005-11-04 15:09:59 -05:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/vm/FastScheduler.cpp 2006-10-03 07:46:23 -04:00 @@ -498,3 +498,37 @@ execute(&signal, JBA, CMVMI, GSN_EVENT_REP); } +void +FastScheduler::reportThreadConfigLoop(Uint32 expired_time, + Uint32 extra_constant, + Uint32 *no_exec_loops, + Uint32 *tot_exec_time, + Uint32 *no_extra_loops, + Uint32 *tot_extra_time) +{ + SignalT<6> signalT; + Signal &signal= *(Signal*)&signalT; + + memset(&signal.header, 0, sizeof(signal.header)); + signal.header.theLength = 6; + signal.header.theSendersSignalId = 0; + signal.header.theSendersBlockRef = numberToRef(0, 0); + + signal.theData[0] = NDB_LE_ThreadConfigLoop; + signal.theData[1] = expired_time; + signal.theData[2] = extra_constant; + signal.theData[3] = (*tot_exec_time)/(*no_exec_loops); + signal.theData[4] = *no_extra_loops; + if (*no_extra_loops > 0) + signal.theData[5] = (*tot_extra_time)/(*no_extra_loops); + else + signal.theData[5] = 0; + + *no_exec_loops = 0; + *tot_exec_time = 0; + *no_extra_loops = 0; + *tot_extra_time = 0; + + execute(&signal, JBA, CMVMI, GSN_EVENT_REP); +} + diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/vm/FastScheduler.hpp clean_dolphin_sched/storage/ndb/src/kernel/vm/FastScheduler.hpp --- mysql-5.1.12/storage/ndb/src/kernel/vm/FastScheduler.hpp 2005-04-07 20:44:07 -04:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/vm/FastScheduler.hpp 2006-10-03 05:45:29 -04:00 @@ -116,7 +116,10 @@ void insertTimeQueue(Signal* aSignal, BlockNumber bnr, GlobalSignalNumber gsn, Uint32 aIndex); void scheduleTimeQueue(Uint32 aIndex); - + void reportThreadConfigLoop(Uint32 expired_time, Uint32 extra_constant, + Uint32 *no_exec_loops, Uint32 *tot_exec_time, + Uint32 *no_extra_loops, Uint32 *tot_extra_time); + private: void highestAvailablePrio(Priority prio); void reportJob(Priority aPriority); diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/kernel/vm/ThreadConfig.cpp clean_dolphin_sched/storage/ndb/src/kernel/vm/ThreadConfig.cpp --- mysql-5.1.12/storage/ndb/src/kernel/vm/ThreadConfig.cpp 2005-04-07 20:44:07 -04:00 +++ clean_dolphin_sched/storage/ndb/src/kernel/vm/ThreadConfig.cpp 2006-10-03 08:55:11 -04:00 @@ -100,7 +100,17 @@ //-------------------------------------------------------------------- void ThreadConfig::ipControlLoop() { - + Uint32 execute_loop_constant = + globalEmulatorData.theConfiguration->schedulerExecutionTimer(); + Uint32 min_spin_time = + globalEmulatorData.theConfiguration->schedulerSpinTimer(); + struct MicroSecondTimer start_micro, end_micro, statistics_start_micro; + Uint32 no_exec_loops = 0; + Uint32 no_extra_loops = 0; + Uint32 tot_exec_time = 0; + Uint32 tot_extra_time = 0; + Uint32 micros_passed; + bool spinning; #if defined NDB_OSE || defined NDB_SOFTOSE //-------------------------------------------------------------------- // To let the Cello Watchdog do it's work NDB must sleep a short @@ -109,14 +119,20 @@ //-------------------------------------------------------------------- int loopCounter = 0; #endif - + int res1 = 0; + int res2 = 0; + Uint32 i = 0; //-------------------------------------------------------------------- // initialise the counter that keeps track of the current millisecond //-------------------------------------------------------------------- globalData.internalMillisecCounter = NdbTick_CurrentMillisecond(); - Uint32 i = 0; - while (globalData.theRestartFlag != perform_stop) { + res1 = NdbTick_getMicroTimer(&start_micro); + end_micro = start_micro; + res2 = res1; + statistics_start_micro = start_micro; + + while (globalData.theRestartFlag != perform_stop) { #if defined NDB_OSE || defined NDB_SOFTOSE loopCounter++; if(loopCounter > 1000){ @@ -130,54 +146,137 @@ #endif Uint32 timeOutMillis = 0; - if (LEVEL_IDLE == globalData.highestAvailablePrio) { -//-------------------------------------------------------------------- -// The buffers are empty, we need to wait for a while until we continue. -// We cannot wait forever since we can also have timed events. //-------------------------------------------------------------------- +// We send all messages buffered during execution of job buffers //-------------------------------------------------------------------- -// Set the time we will sleep on the sockets before waking up -// unconditionally to 10 ms. Will never sleep more than 10 milliseconds -// on a socket. -//-------------------------------------------------------------------- - timeOutMillis = 10; - }//if + globalData.incrementWatchDogCounter(6); + globalTransporterRegistry.performSend(); + //-------------------------------------------------------------------- // Now it is time to check all interfaces. We will send all buffers // plus checking for any received messages. //-------------------------------------------------------------------- if (i++ >= 20) { + execute_loop_constant = + globalEmulatorData.theConfiguration->schedulerExecutionTimer(); + min_spin_time = + globalEmulatorData.theConfiguration->schedulerSpinTimer(); globalTransporterRegistry.update_connections(); globalData.incrementWatchDogCounter(5); i = 0; }//if - - globalData.incrementWatchDogCounter(6); - globalTransporterRegistry.performSend(); - - globalData.incrementWatchDogCounter(7); - if (globalTransporterRegistry.pollReceive(timeOutMillis)) { - globalData.incrementWatchDogCounter(8); - globalTransporterRegistry.performReceive(); - } - + spinning = false; + do + { //-------------------------------------------------------------------- // We scan the time queue to see if there are any timed signals that // is now ready to be executed. //-------------------------------------------------------------------- - globalData.incrementWatchDogCounter(2); - scanTimeQueue(); + globalData.incrementWatchDogCounter(2); + scanTimeQueue(); + if (LEVEL_IDLE == globalData.highestAvailablePrio) { +//-------------------------------------------------------------------- +// The buffers are empty, we need to wait for a while until we continue. +// We cannot wait forever since we can also have timed events. +//-------------------------------------------------------------------- +// We set the time to sleep on sockets before waking up to 10 +// milliseconds unless we have set spin timer to be larger than 0. In +// this case we spin checking for events on the transporter until we +// have expired the spin time. +//-------------------------------------------------------------------- + timeOutMillis = 10; + if (min_spin_time) + { + if (spinning) + res2 = NdbTick_getMicroTimer(&end_micro); + if (!(res1 + res2)) + { + micros_passed = + (Uint32)NdbTick_getMicrosPassed(start_micro, end_micro); + if (micros_passed < min_spin_time) + timeOutMillis = 0; + } + } + } + +//-------------------------------------------------------------------- +// Perform receive before entering execute loop +//-------------------------------------------------------------------- + globalData.incrementWatchDogCounter(7); + if (globalTransporterRegistry.pollReceive(timeOutMillis)) { + globalData.incrementWatchDogCounter(8); + globalTransporterRegistry.performReceive(); + } + spinning = true; +//-------------------------------------------------------------------- +// In an idle system we will use this loop to wait either for external +// signal received or a message generated by the time queue. +//-------------------------------------------------------------------- + } while (LEVEL_IDLE == globalData.highestAvailablePrio); +//-------------------------------------------------------------------- +// Get current microsecond to ensure we will continue executing +// signals for at least a configured time while there are more +// signals to receive. +//-------------------------------------------------------------------- + if (execute_loop_constant || min_spin_time) + res1= NdbTick_getMicroTimer(&start_micro); + do + { //-------------------------------------------------------------------- // This is where the actual execution of signals occur. We execute // until all buffers are empty or until we have executed 2048 signals. //-------------------------------------------------------------------- - globalScheduler.doJob(); - }//while + globalScheduler.doJob(); +//-------------------------------------------------------------------- +// Get timer after executing this set of jobs. If we have passed the +// maximum execution time we will break out of the loop always +// otherwise we will check for new received signals before executing +// the send of the buffers. +// By setting exec_loop_constant to 0 we go back to the traditional +// algorithm of sending once per receive instance. +//-------------------------------------------------------------------- + if (!execute_loop_constant && !min_spin_time) + break; + res2= NdbTick_getMicroTimer(&end_micro); + if (res1 + res2) + break; + micros_passed = (Uint32)NdbTick_getMicrosPassed(start_micro, end_micro); + tot_exec_time += micros_passed; + if (no_exec_loops++ >= 8192) + { + Uint32 expired_time = + (Uint32)NdbTick_getMicrosPassed(statistics_start_micro, end_micro); + statistics_start_micro = end_micro; + globalScheduler.reportThreadConfigLoop(expired_time, + execute_loop_constant, + &no_exec_loops, + &tot_exec_time, + &no_extra_loops, + &tot_extra_time); + } + if (micros_passed > execute_loop_constant) + break; + +//-------------------------------------------------------------------- +// There were still time for execution left, we check if there are +// signals newly received on the transporters and if so we execute one +// more round before sending the buffered signals. +//-------------------------------------------------------------------- + globalData.incrementWatchDogCounter(7); + if (!globalTransporterRegistry.pollReceive(0)) + break; + + no_extra_loops++; + tot_extra_time += micros_passed; + start_micro = end_micro; + globalData.incrementWatchDogCounter(8); + globalTransporterRegistry.performReceive(); + } while (1); + }//while globalData.incrementWatchDogCounter(6); globalTransporterRegistry.performSend(); - }//ThreadConfig::ipControlLoop() int diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet mysql-5.1.12/storage/ndb/src/mgmsrv/ConfigInfo.cpp clean_dolphin_sched/storage/ndb/src/mgmsrv/ConfigInfo.cpp --- mysql-5.1.12/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2006-10-16 15:33:30 -04:00 +++ clean_dolphin_sched/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2006-10-21 13:23:41 -04:00 @@ -582,6 +582,30 @@ STR_VALUE(MAX_INT_RNIL) }, { + CFG_DB_SCHED_EXEC_TIME, + "SchedulerExecutionTimer", + DB_TOKEN, + "Number of microseconds to execute in scheduler before sending", + ConfigInfo::CI_USED, + false, + ConfigInfo::CI_INT, + "50", + "0", + "11000" }, + + { + CFG_DB_SCHED_SPIN_TIME, + "SchedulerSpinTimer", + DB_TOKEN, + "Number of microseconds to execute in scheduler before sleeping", + ConfigInfo::CI_USED, + false, + ConfigInfo::CI_INT, + "0", + "0", + "11000" }, + + { CFG_DB_STOP_ON_ERROR, "StopOnError", DB_TOKEN,