Browse Source

less alloc/dealloc on scheduler

Only 'detached' tasks need dedicated holder allocated on heap; for
simple continuations local holder is enough (no need to new/delete)
alexey 3 years ago
parent
commit
4e867c2c60
5 changed files with 47 additions and 62 deletions
  1. 10 4
      src/coroutine.cpp
  2. 0 43
      src/mini_timer.cpp
  3. 1 8
      src/mini_timer.h
  4. 35 6
      src/searchdtask.cpp
  5. 1 1
      src/searchdtask.h

+ 10 - 4
src/coroutine.cpp

@@ -522,7 +522,7 @@ public:
 		}
 
 		assert ( CurrentWorker() != this );
-		Restart();
+		RestartSecondary();
 		return true;
 	}
 
@@ -848,9 +848,15 @@ void SleepMsec ( int iMsec )
 	if ( iMsec < 0 )
 		return;
 
-	Coro::YieldWith ( [iMsec, fnRestarter = CurrentRestarter()]() mutable {
-		sph::EngageTask ( iMsec, std::move ( fnRestarter ), "SleepMsec" );
-	} );
+	struct Sleeper_t final: public MiniTimer_c
+	{
+		Sleeper_t () { m_szName = "SleepMsec"; }
+		Waker_c m_tWaker = Worker()->CreateWaker();
+		void OnTimer() final { m_tWaker.Wake(); }
+	} tWait;
+
+	// suspend this fiber
+	Coro::YieldWith ( [&tWait, iMsec](){ tWait.Engage ( iMsec ); });
 }
 
 Event_c::~Event_c ()

+ 0 - 43
src/mini_timer.cpp

@@ -315,49 +315,6 @@ bool sph::TimeExceeded ( int64_t tmMicroTimestamp )
 	return g_TinyTimer ().TimeExceeded ( tmMicroTimestamp );
 }
 
-// scheduled job - will live in timeout heap and then fire when time is out.
-class ScheduledJob_c final: public MiniTimer_c
-{
-	Threads::Handler m_fnHandler;
-
-private:
-	void OnTimer() final
-	{
-		if ( m_fnHandler )
-			m_fnHandler();
-		delete this;
-	}
-
-public:
-	ScheduledJob_c ( Threads::Handler fnTask, const char* szName )
-		: m_fnHandler { std::move ( fnTask ) }
-	{
-		if ( szName )
-			m_szName = szName;
-	}
-
-	~ScheduledJob_c()
-	{
-		m_szName = nullptr;
-	}
-};
-
-void sph::EngageTask ( int64_t iTimePeriodMS, Threads::Handler fnTask, const char* szName )
-{
-	assert ( iTimePeriodMS > 0 );
-	DEBUGT << "sph::EngageTask " << timespan_t(iTimePeriodMS*1000);
-	auto pScheduledJob = new ScheduledJob_c ( std::move ( fnTask ), szName );
-	pScheduledJob->Engage ( iTimePeriodMS );
-}
-
-void sph::EngageTaskAt ( int64_t iTimeStampUS, Threads::Handler fnTask, const char* szName )
-{
-	assert ( iTimeStampUS > 0 );
-	DEBUGT << "sph::EngageTask " << timestamp_t ( iTimeStampUS );
-	auto pScheduledJob = new ScheduledJob_c ( std::move ( fnTask ), szName );
-	pScheduledJob->EngageUS ( iTimeStampUS-sphMicroTimer() );
-}
-
 void sph::ShutdownMiniTimer()
 {
 	if ( IsTinyTimerCreated() )

+ 1 - 8
src/mini_timer.h

@@ -31,13 +31,6 @@ namespace sph
 	/// non-engaged timer doesn't tick and may infinitely return false.
 	bool TimeExceeded ( int64_t iTimestampUS );
 
-	/// engage timer, so that provided fnTask will be called when it is reached.
-	/// also it will be called on global interrupt (shutdown), so that fnTask must be aware to check it.
-	void EngageTask ( int64_t iTimePeriodMS, Threads::Handler fnTask, const char* szName="task" );
-
-	/// engage timer to absolute time. Note, timestamp is in microseconds
-	void EngageTaskAt ( int64_t iTimeStampUS, Threads::Handler fnTask, const char* szName="task" );
-
 	/// should be called on shutdown
 	void ShutdownMiniTimer();
 
@@ -67,6 +60,6 @@ public:
 	int64_t Engage ( int64_t iTimePeriodMS );
 	int64_t EngageUS ( int64_t iTimePeriodUS ); // same, but period is in microseconds
 
-	/// if destroy before timer - unengage and unlink everything
+	/// if m_szName is not null - unengage and unlink everything
 	virtual ~MiniTimer_c();
 };

+ 35 - 6
src/searchdtask.cpp

@@ -101,14 +101,43 @@ TaskID TaskManager::RegisterGlobal ( CSphString sName, int iThreads )
 	return iTaskID;
 }
 
-
-void TaskManager::ScheduleJob ( TaskID iTask, int64_t iTimestampUS, Threads::Handler fnJob )
+// scheduled job - will live in timeout heap and then fire when time is out.
+class ScheduledTask_c final: public MiniTimer_c
 {
-	INFOX << "ScheduleJob (id=" << iTask << ", \"" << g_Tasks[iTask].m_sName << "\", start " << timestamp_t( iTimestampUS) << ")";
-	sph::EngageTaskAt ( iTimestampUS, [iTask,fnJob=std::move(fnJob)]() mutable
+	TaskID m_iTask;
+	Threads::Handler m_fnJob;
+
+private:
+	void OnTimer() final
+	{
+		TaskManager::StartJob ( m_iTask, std::move ( m_fnJob ) );
+		delete this;
+	}
+
+	~ScheduledTask_c() final
+	{
+		m_szName = nullptr; // signal to not call remove() in MiniTimer_c dtr
+	}
+
+	ScheduledTask_c ( TaskID iTask, Threads::Handler fnTask )
+		: m_iTask ( iTask )
+		, m_fnJob { std::move ( fnTask ) }
+	{
+		m_szName = g_Tasks[iTask].m_sName.cstr();
+	}
+
+public:
+	static void EngageJob ( TaskID iTask, int64_t iTimeStampUS, Threads::Handler fnJob )
 	{
-		TaskManager::StartJob ( iTask, std::move ( fnJob ) );
-	},	g_Tasks[iTask].m_sName.cstr());
+		assert ( iTimeStampUS > 0 );
+		( new ScheduledTask_c { iTask, std::move ( fnJob ) } )->EngageUS ( iTimeStampUS - sphMicroTimer() );
+	}
+};
+
+void TaskManager::ScheduleJob ( TaskID iTask, int64_t iTimeStampUS, Threads::Handler fnJob )
+{
+	INFOX << "ScheduleJob (id=" << iTask << ", \"" << g_Tasks[iTask].m_sName << "\", start " << timestamp_t ( iTimeStampUS ) << ")";
+	ScheduledTask_c::EngageJob ( iTask, iTimeStampUS, std::move ( fnJob ) );
 }
 
 VecTraits_T<TaskManager::TaskInfo_t> TaskManager::GetTaskInfo ()

+ 1 - 1
src/searchdtask.h

@@ -50,7 +50,7 @@ namespace TaskManager {
 	 * @param iTimestamp - time (absolute) when job need to be executed
 	 * @param fnJob - task route
 	 */
-	void ScheduleJob ( TaskID iTask, int64_t iTimestampUS, Threads::Handler fnJob );
+	void ScheduleJob ( TaskID iTask, int64_t iTimeStampUS, Threads::Handler fnJob );
 
 	/*!
 	 * @brief enqueue job which will be run ASAP. For MT jobs queue's limit will be honored, so exceeding job will