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 <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
index 693cb3a..273faf7 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -152,14 +152,24 @@
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<TimeSlot *> TimeSlots;
@@ -259,7 +269,7 @@
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 @@
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 @@
ScEvents deltas;
TimeSlots timeSlots;
+ std::stack<TimeSlot*> freeTimeSlots;
Process *
getNextReady()