From 5bcfdb5400e8030889771d2f936d336eaa5b79bc Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Sat, 14 Sep 2024 08:51:47 -0400 Subject: [PATCH] Optimization: Maintain active zone weak ref set in group Maintain an active zone wak ptr set in gropu so that we dont have to traverse all zones querying if they are active every time. This changes a profile result for my simple test which had around 93% group / 77% zone to 90% group / 78% zone. --- src/engine/group.cpp | 101 ++++++++++++++++++++++++++++--------------- src/engine/group.h | 14 ++++-- src/engine/zone.cpp | 11 +---- 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/src/engine/group.cpp b/src/engine/group.cpp index a3fe54f8..0a059e53 100644 --- a/src/engine/group.cpp +++ b/src/engine/group.cpp @@ -136,31 +136,29 @@ template void Group::processWithOS(scxt::engine::Engine &e) auto &eg2p = endpoints.eg[1]; eg[1].processBlock(*eg2p.aP, *eg2p.hP, *eg2p.dP, *eg2p.sP, *eg2p.rP, *eg2p.asP, *eg2p.dsP, *eg2p.rsP, envGate); - modMatrix.process(); - for (const auto &z : zones) + for (int i = 0; i < activeZones; ++i) { - if (z->isActive()) + auto z = activeZoneWeakRefs[i]; + assert(z->isActive()); + z->process(e); + /* + * This is just an optimization to not accumulate. The zone will + * have already routed to the approprite other bus and output will + * be empty. + */ + if (z->outputInfo.routeTo == DEFAULT_BUS) { - z->process(e); - /* - * This is just an optimization to not accumulate. The zone will - * have already routed to the approprite other bus and output will - * be empty. - */ - if (z->outputInfo.routeTo == DEFAULT_BUS) + if constexpr (OS) + { + blk::accumulate_from_to(z->output[0], lOut); + blk::accumulate_from_to(z->output[1], rOut); + } + else { - if constexpr (OS) - { - blk::accumulate_from_to(z->output[0], lOut); - blk::accumulate_from_to(z->output[1], rOut); - } - else - { - blk::accumulate_from_to(z->output[0], lOut); - blk::accumulate_from_to(z->output[1], rOut); - } + blk::accumulate_from_to(z->output[0], lOut); + blk::accumulate_from_to(z->output[1], rOut); } } } @@ -288,19 +286,6 @@ template void Group::processWithOS(scxt::engine::Engine &e) } } -void Group::addActiveZone() -{ - if (activeZones == 0) - { - parentPart->addActiveGroup(); - attack(); - } - // Important we do this *after* the attack since it allows - // isActive to be accurate with processor ringout - activeZones++; - ringoutTime = 0; -} - bool Group::updateRingout() { auto res{false}; @@ -331,9 +316,49 @@ bool Group::updateRingout() return res; } -void Group::removeActiveZone() +void Group::addActiveZone(engine::Zone *zwp) +{ + // Add active zone to end + activeZoneWeakRefs[activeZones] = zwp; + + if (activeZones == 0) + { + parentPart->addActiveGroup(); + attack(); + } + // Important we do this *after* the attack since it allows + // isActive to be accurate with processor ringout + activeZones++; + ringoutTime = 0; + + /* + SCLOG("addZone " << SCD(activeZones)); + for (int i = 0; i < activeZones; ++i) + { + SCLOG("addZone " << activeZoneWeakRefs[i] << " " << activeZoneWeakRefs[i]->getName()); + } + */ +} + +void Group::removeActiveZone(engine::Zone *zwp) { assert(activeZones); + + // Manage the weak refs + // First find the zone + int zidx{-1}; + for (int idx = 0; idx < activeZones; ++idx) + { + if (activeZoneWeakRefs[idx] == zwp) + { + zidx = idx; + break; + } + } + assert(zidx >= 0); + // OK so now we want to swap the active zone from the end into my slot + activeZoneWeakRefs[zidx] = activeZoneWeakRefs[activeZones - 1]; + activeZones--; if (activeZones == 0) { @@ -341,6 +366,14 @@ void Group::removeActiveZone() ringoutTime = 0; updateRingout(); } + + /* + SCLOG("removeZone " << SCD(activeZones)); + for (int i = 0; i < activeZones; ++i) + { + SCLOG("removeZone " << activeZoneWeakRefs[i] << " " << activeZoneWeakRefs[i]->getName()); + } + */ } engine::Engine *Group::getEngine() diff --git a/src/engine/group.h b/src/engine/group.h index 09484d61..5d333cc5 100644 --- a/src/engine/group.h +++ b/src/engine/group.h @@ -105,6 +105,7 @@ struct Group : MoveableOnly, z->parentGroup = this; z->engine = getEngine(); zones.push_back(std::move(z)); + activeZoneWeakRefs.push_back(nullptr); return zones.size(); } @@ -113,10 +114,15 @@ struct Group : MoveableOnly, z->parentGroup = this; z->engine = getEngine(); zones.push_back(std::move(z)); + activeZoneWeakRefs.push_back(nullptr); return zones.size(); } - void clearZones() { zones.clear(); } + void clearZones() + { + zones.clear(); + activeZoneWeakRefs.clear(); + } int getZoneIndex(const ZoneID &zid) const { @@ -149,6 +155,7 @@ struct Group : MoveableOnly, auto res = std::move(zones[idx]); zones.erase(zones.begin() + idx); + // REPACK WEAK REFS TODO res->parentGroup = nullptr; return res; } @@ -159,8 +166,8 @@ struct Group : MoveableOnly, } bool isActive() const; - void addActiveZone(); - void removeActiveZone(); + void addActiveZone(engine::Zone *zoneWP); + void removeActiveZone(engine::Zone *zoneWP); void onSampleRateChanged() override; @@ -242,6 +249,7 @@ struct Group : MoveableOnly, private: zoneContainer_t zones; + std::vector activeZoneWeakRefs; }; } // namespace scxt::engine diff --git a/src/engine/zone.cpp b/src/engine/zone.cpp index 0317ef06..2bdd511c 100644 --- a/src/engine/zone.cpp +++ b/src/engine/zone.cpp @@ -109,20 +109,13 @@ template void Zone::processWithOS(scxt::engine::Engine &onto) #endif toCleanUp[i]->cleanupVoice(); } - - for (int i = 0; i < osBlock; i += 4) - { - // SCLOG(i << " " << output[0][i] << " " << output[0][i + 1] << " " << output[0][i + 2] << " - // " - // << output[0][i + 3]) - } } void Zone::addVoice(voice::Voice *v) { if (activeVoices == 0) { - parentGroup->addActiveZone(); + parentGroup->addActiveZone(this); } activeVoices++; @@ -148,7 +141,7 @@ void Zone::removeVoice(voice::Voice *v) if (activeVoices == 0) { mUILag.instantlySnap(); - parentGroup->removeActiveZone(); + parentGroup->removeActiveZone(this); } return; }