From ae37bdd4f43d5e183492f1f24c3d5dc70baf81f8 Mon Sep 17 00:00:00 2001 From: Earl Ou Date: Wed, 16 Sep 2020 15:17:26 +0800 Subject: [PATCH] systemc: self-manage TimeSlot in Scheduler TimeSlot is new and deleted frequently. Having a recycling memory manager can help saving the time spent new and delete. Tested and see about 4% improvement in simulation speed. Change-Id: I0ab173168336a883b85f768d7fdf07a936a14d69 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/34615 Reviewed-by: Gabe Black Maintainer: Gabe Black Tested-by: kokoro --- src/systemc/core/scheduler.hh | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh index 693cb3a84..273faf7d7 100644 --- a/src/systemc/core/scheduler.hh +++ b/src/systemc/core/scheduler.hh @@ -152,14 +152,24 @@ class Scheduler class TimeSlot : public ::Event { public: - TimeSlot(const Tick& targeted_when) : ::Event(Default_Pri, AutoDelete), - targeted_when(targeted_when) {} + TimeSlot(Scheduler* scheduler) : ::Event(Default_Pri, AutoDelete), + parent_scheduler(scheduler) {} // Event::when() is only set after it's scheduled to an event queue. // However, TimeSlot won't be scheduled before init is done. We need // to keep the real 'targeted_when' information before scheduled. Tick targeted_when; + Scheduler* parent_scheduler; ScEvents events; void process(); + + protected: + void + releaseImpl() override + { + if (!scheduled()) + parent_scheduler->releaseTimeSlot(this); + } + }; typedef std::list TimeSlots; @@ -259,7 +269,7 @@ class Scheduler while (it != timeSlots.end() && (*it)->targeted_when < tick) it++; if (it == timeSlots.end() || (*it)->targeted_when != tick) { - it = timeSlots.emplace(it, new TimeSlot(tick)); + it = timeSlots.emplace(it, acquireTimeSlot(tick)); schedule(*it, tick); } event->schedule((*it)->events, tick); @@ -386,6 +396,27 @@ class Scheduler void registerTraceFile(TraceFile *tf) { traceFiles.insert(tf); } void unregisterTraceFile(TraceFile *tf) { traceFiles.erase(tf); } + TimeSlot* + acquireTimeSlot(Tick tick) + { + TimeSlot *ts = nullptr; + if (!freeTimeSlots.empty()) { + ts = freeTimeSlots.top(); + freeTimeSlots.pop(); + } else { + ts = new TimeSlot(this); + } + ts->targeted_when = tick; + ts->events.clear(); + return ts; + } + + void + releaseTimeSlot(TimeSlot *ts) + { + freeTimeSlots.push(ts); + } + private: typedef const EventBase::Priority Priority; static Priority DefaultPriority = EventBase::Default_Pri; @@ -422,6 +453,7 @@ class Scheduler ScEvents deltas; TimeSlots timeSlots; + std::stack freeTimeSlots; Process * getNextReady() -- 2.30.2