better perf

This commit is contained in:
Martino Ferrari
2026-02-25 16:51:07 +01:00
parent aaf69c0949
commit dfb399bbba
12 changed files with 713 additions and 633 deletions

View File

@@ -6,6 +6,9 @@
#include "MemoryMapBroker.h"
#include "ObjectRegistryDatabase.h"
#include "ObjectBuilder.h"
#include "Vector.h"
#include "FastPollingMutexSem.h"
#include "HighResolutionTimer.h"
// Original broker headers
#include "MemoryMapInputBroker.h"
@@ -17,39 +20,45 @@
#include "MemoryMapMultiBufferOutputBroker.h"
#include "MemoryMapSynchronisedMultiBufferInputBroker.h"
#include "MemoryMapSynchronisedMultiBufferOutputBroker.h"
#include "MemoryMapAsyncOutputBroker.h"
#include "MemoryMapAsyncTriggerOutputBroker.h"
namespace MARTe {
/**
* @brief Base implementation for all debug brokers.
* @brief Helper for optimized signal processing within brokers.
*/
class DebugBrokerHelper {
public:
static void Process(BrokerI* broker, DebugService* service, DebugSignalInfo** signalInfoPointers, uint32 numSignals) {
static void Process(DebugService* service, DebugSignalInfo** signalInfoPointers, Vector<uint32>& activeIndices, Vector<uint32>& activeSizes, FastPollingMutexSem& activeMutex) {
if (service == NULL_PTR(DebugService*)) return;
// Re-establish break logic
while (service->IsPaused()) {
Sleep::MSec(10);
}
if (signalInfoPointers != NULL_PTR(DebugSignalInfo**)) {
for (uint32 i = 0; i < numSignals; i++) {
DebugSignalInfo *s = signalInfoPointers[i];
if (s != NULL_PTR(DebugSignalInfo*)) {
if (s->isTracing || s->isForcing) {
uint32 size = broker->GetCopyByteSize(i);
service->ProcessSignal(s, size);
}
}
activeMutex.FastLock();
uint32 n = activeIndices.GetNumberOfElements();
if (n > 0 && signalInfoPointers != NULL_PTR(DebugSignalInfo**)) {
// Capture timestamp ONCE per broker cycle for lowest impact
uint64 ts = (uint64)((float64)HighResolutionTimer::Counter() * HighResolutionTimer::Period() * 1000000.0);
for (uint32 i = 0; i < n; i++) {
uint32 idx = activeIndices[i];
uint32 size = activeSizes[i];
DebugSignalInfo *s = signalInfoPointers[idx];
service->ProcessSignal(s, size, ts);
}
}
activeMutex.FastUnLock();
}
static void InitSignals(MemoryMapBroker* broker, DataSourceI &dataSourceIn, DebugService* &service, DebugSignalInfo** &signalInfoPointers, uint32 &numSignals, MemoryMapBrokerCopyTableEntry* copyTable, const char8* functionName, SignalDirection direction) {
numSignals = broker->GetNumberOfCopies();
if (numSignals > 0) {
signalInfoPointers = new DebugSignalInfo*[numSignals];
for (uint32 i=0; i<numSignals; i++) signalInfoPointers[i] = NULL_PTR(DebugSignalInfo*);
// Pass numCopies explicitly so we can mock it
static void InitSignals(BrokerI* broker, DataSourceI &dataSourceIn, DebugService* &service, DebugSignalInfo** &signalInfoPointers, uint32 numCopies, MemoryMapBrokerCopyTableEntry* copyTable, const char8* functionName, SignalDirection direction, volatile bool* anyActiveFlag, Vector<uint32>* activeIndices, Vector<uint32>* activeSizes, FastPollingMutexSem* activeMutex) {
if (numCopies > 0) {
signalInfoPointers = new DebugSignalInfo*[numCopies];
for (uint32 i=0; i<numCopies; i++) signalInfoPointers[i] = NULL_PTR(DebugSignalInfo*);
}
ReferenceContainer *root = ObjectRegistryDatabase::Instance();
@@ -61,21 +70,26 @@ public:
if (service && (copyTable != NULL_PTR(MemoryMapBrokerCopyTableEntry*))) {
StreamString dsPath;
DebugService::GetFullObjectName(dataSourceIn, dsPath);
MemoryMapBroker* mmb = dynamic_cast<MemoryMapBroker*>(broker);
for (uint32 i = 0; i < numSignals; i++) {
for (uint32 i = 0; i < numCopies; i++) {
void *addr = copyTable[i].dataSourcePointer;
TypeDescriptor type = copyTable[i].type;
uint32 dsIdx = broker->GetDSCopySignalIndex(i);
uint32 dsIdx = i;
if (mmb != NULL_PTR(MemoryMapBroker*)) {
dsIdx = mmb->GetDSCopySignalIndex(i);
}
StreamString signalName;
if (!dataSourceIn.GetSignalName(dsIdx, signalName)) signalName = "Unknown";
// 1. Register canonical DataSource name (Absolute, No Root prefix)
// Register canonical name
StreamString dsFullName;
dsFullName.Printf("%s.%s", dsPath.Buffer(), signalName.Buffer());
service->RegisterSignal(addr, type, dsFullName.Buffer());
// 2. Also register absolute GAM alias
// Register alias
if (functionName != NULL_PTR(const char8*)) {
StreamString gamFullName;
const char8* dirStr = (direction == InputSignals) ? "In" : "Out";
@@ -92,73 +106,209 @@ public:
signalInfoPointers[i] = service->RegisterSignal(addr, type, dsFullName.Buffer());
}
}
// Register broker in DebugService for optimized control
service->RegisterBroker(signalInfoPointers, numCopies, mmb, anyActiveFlag, activeIndices, activeSizes, activeMutex);
}
}
};
#define DECLARE_DEBUG_BROKER_COMMON(BaseClass) \
Debug##BaseClass() : BaseClass() { \
service = NULL_PTR(DebugService*); \
signalInfoPointers = NULL_PTR(DebugSignalInfo**); \
numSignals = 0; \
} \
virtual ~Debug##BaseClass() { \
if (signalInfoPointers) delete[] signalInfoPointers; \
} \
virtual bool Execute() { \
bool ret = BaseClass::Execute(); \
if (ret) DebugBrokerHelper::Process(this, service, signalInfoPointers, numSignals); \
return ret; \
} \
private: \
DebugService *service; \
DebugSignalInfo **signalInfoPointers; \
/**
* @brief Template class to instrument any MARTe2 Broker.
*/
template <typename BaseClass>
class DebugBrokerWrapper : public BaseClass {
public:
DebugBrokerWrapper() : BaseClass() {
service = NULL_PTR(DebugService*);
signalInfoPointers = NULL_PTR(DebugSignalInfo**);
numSignals = 0;
anyActive = false;
}
virtual ~DebugBrokerWrapper() {
if (signalInfoPointers) delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = BaseClass::Execute();
if (ret && (anyActive || (service && service->IsPaused()))) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices, activeSizes, activeMutex);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem) {
bool ret = BaseClass::Init(direction, ds, name, gamMem);
if (ret) {
numSignals = this->GetNumberOfCopies();
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction, &anyActive, &activeIndices, &activeSizes, &activeMutex);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem, const bool optim) {
bool ret = BaseClass::Init(direction, ds, name, gamMem, optim);
if (ret) {
numSignals = this->GetNumberOfCopies();
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction, &anyActive, &activeIndices, &activeSizes, &activeMutex);
}
return ret;
}
DebugService *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
#define DECLARE_DEBUG_BROKER(BaseClass) \
class Debug##BaseClass : public BaseClass { \
public: \
DECLARE_DEBUG_BROKER_COMMON(BaseClass) \
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem) { \
bool ret = BaseClass::Init(direction, ds, name, gamMem); \
if (ret) DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction); \
return ret; \
} \
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem, const bool optim) { \
bool ret = BaseClass::Init(direction, ds, name, gamMem, optim); \
if (ret) DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction); \
return ret; \
} \
}; \
class Debug##BaseClass##Builder : public ObjectBuilder { \
public: \
virtual Object *Build(HeapI* const heap) const { return new (heap) Debug##BaseClass(); } \
volatile bool anyActive;
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
FastPollingMutexSem activeMutex;
};
#define DECLARE_DEBUG_BROKER_NO_OPTIM(BaseClass) \
class Debug##BaseClass : public BaseClass { \
public: \
DECLARE_DEBUG_BROKER_COMMON(BaseClass) \
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem) { \
bool ret = BaseClass::Init(direction, ds, name, gamMem); \
if (ret) DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction); \
return ret; \
} \
}; \
class Debug##BaseClass##Builder : public ObjectBuilder { \
public: \
virtual Object *Build(HeapI* const heap) const { return new (heap) Debug##BaseClass(); } \
template <typename BaseClass>
class DebugBrokerWrapperNoOptim : public BaseClass {
public:
DebugBrokerWrapperNoOptim() : BaseClass() {
service = NULL_PTR(DebugService*);
signalInfoPointers = NULL_PTR(DebugSignalInfo**);
numSignals = 0;
anyActive = false;
}
virtual ~DebugBrokerWrapperNoOptim() {
if (signalInfoPointers) delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = BaseClass::Execute();
if (ret && (anyActive || (service && service->IsPaused()))) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices, activeSizes, activeMutex);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds, const char8 *const name, void *gamMem) {
bool ret = BaseClass::Init(direction, ds, name, gamMem);
if (ret) {
numSignals = this->GetNumberOfCopies();
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers, numSignals, this->copyTable, name, direction, &anyActive, &activeIndices, &activeSizes, &activeMutex);
}
return ret;
}
DebugService *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
FastPollingMutexSem activeMutex;
};
DECLARE_DEBUG_BROKER(MemoryMapInputBroker)
DECLARE_DEBUG_BROKER(MemoryMapOutputBroker)
DECLARE_DEBUG_BROKER(MemoryMapSynchronisedInputBroker)
DECLARE_DEBUG_BROKER(MemoryMapSynchronisedOutputBroker)
DECLARE_DEBUG_BROKER_NO_OPTIM(MemoryMapInterpolatedInputBroker)
DECLARE_DEBUG_BROKER(MemoryMapMultiBufferInputBroker)
DECLARE_DEBUG_BROKER(MemoryMapMultiBufferOutputBroker)
DECLARE_DEBUG_BROKER(MemoryMapSynchronisedMultiBufferInputBroker)
DECLARE_DEBUG_BROKER(MemoryMapSynchronisedMultiBufferOutputBroker)
class DebugMemoryMapAsyncOutputBroker : public MemoryMapAsyncOutputBroker {
public:
DebugMemoryMapAsyncOutputBroker() : MemoryMapAsyncOutputBroker() {
service = NULL_PTR(DebugService*);
signalInfoPointers = NULL_PTR(DebugSignalInfo**);
numSignals = 0;
anyActive = false;
}
virtual ~DebugMemoryMapAsyncOutputBroker() {
if (signalInfoPointers) delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = MemoryMapAsyncOutputBroker::Execute();
if (ret && (anyActive || (service && service->IsPaused()))) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices, activeSizes, activeMutex);
}
return ret;
}
virtual bool InitWithBufferParameters(const SignalDirection direction, DataSourceI &dataSourceIn, const char8 * const functionName,
void * const gamMemoryAddress, const uint32 numberOfBuffersIn, const ProcessorType& cpuMaskIn, const uint32 stackSizeIn) {
bool ret = MemoryMapAsyncOutputBroker::InitWithBufferParameters(direction, dataSourceIn, functionName, gamMemoryAddress, numberOfBuffersIn, cpuMaskIn, stackSizeIn);
if (ret) {
numSignals = this->GetNumberOfCopies();
DebugBrokerHelper::InitSignals(this, dataSourceIn, service, signalInfoPointers, numSignals, this->copyTable, functionName, direction, &anyActive, &activeIndices, &activeSizes, &activeMutex);
}
return ret;
}
DebugService *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
FastPollingMutexSem activeMutex;
};
class DebugMemoryMapAsyncTriggerOutputBroker : public MemoryMapAsyncTriggerOutputBroker {
public:
DebugMemoryMapAsyncTriggerOutputBroker() : MemoryMapAsyncTriggerOutputBroker() {
service = NULL_PTR(DebugService*);
signalInfoPointers = NULL_PTR(DebugSignalInfo**);
numSignals = 0;
anyActive = false;
}
virtual ~DebugMemoryMapAsyncTriggerOutputBroker() {
if (signalInfoPointers) delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = MemoryMapAsyncTriggerOutputBroker::Execute();
if (ret && (anyActive || (service && service->IsPaused()))) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices, activeSizes, activeMutex);
}
return ret;
}
virtual bool InitWithTriggerParameters(const SignalDirection direction, DataSourceI &dataSourceIn, const char8 * const functionName,
void * const gamMemoryAddress, const uint32 numberOfBuffersIn, const uint32 preTriggerBuffersIn,
const uint32 postTriggerBuffersIn, const ProcessorType& cpuMaskIn, const uint32 stackSizeIn) {
bool ret = MemoryMapAsyncTriggerOutputBroker::InitWithTriggerParameters(direction, dataSourceIn, functionName, gamMemoryAddress, numberOfBuffersIn, preTriggerBuffersIn, postTriggerBuffersIn, cpuMaskIn, stackSizeIn);
if (ret) {
numSignals = this->GetNumberOfCopies();
DebugBrokerHelper::InitSignals(this, dataSourceIn, service, signalInfoPointers, numSignals, this->copyTable, functionName, direction, &anyActive, &activeIndices, &activeSizes, &activeMutex);
}
return ret;
}
DebugService *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
FastPollingMutexSem activeMutex;
};
template <typename T>
class DebugBrokerBuilder : public ObjectBuilder {
public:
virtual Object *Build(HeapI* const heap) const { return new (heap) T(); }
};
typedef DebugBrokerWrapper<MemoryMapInputBroker> DebugMemoryMapInputBroker;
// LCOV_EXCL_START
typedef DebugBrokerWrapper<MemoryMapOutputBroker> DebugMemoryMapOutputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedInputBroker> DebugMemoryMapSynchronisedInputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedOutputBroker> DebugMemoryMapSynchronisedOutputBroker;
typedef DebugBrokerWrapperNoOptim<MemoryMapInterpolatedInputBroker> DebugMemoryMapInterpolatedInputBroker;
typedef DebugBrokerWrapper<MemoryMapMultiBufferInputBroker> DebugMemoryMapMultiBufferInputBroker;
typedef DebugBrokerWrapper<MemoryMapMultiBufferOutputBroker> DebugMemoryMapMultiBufferOutputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedMultiBufferInputBroker> DebugMemoryMapSynchronisedMultiBufferInputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedMultiBufferOutputBroker> DebugMemoryMapSynchronisedMultiBufferOutputBroker;
// LCOV_EXCL_STOP
typedef DebugBrokerBuilder<DebugMemoryMapInputBroker> DebugMemoryMapInputBrokerBuilder;
// LCOV_EXCL_START
typedef DebugBrokerBuilder<DebugMemoryMapOutputBroker> DebugMemoryMapOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedInputBroker> DebugMemoryMapSynchronisedInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedOutputBroker> DebugMemoryMapSynchronisedOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapInterpolatedInputBroker> DebugMemoryMapInterpolatedInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapMultiBufferInputBroker> DebugMemoryMapMultiBufferInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapMultiBufferOutputBroker> DebugMemoryMapMultiBufferOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedMultiBufferInputBroker> DebugMemoryMapSynchronisedMultiBufferInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedMultiBufferOutputBroker> DebugMemoryMapSynchronisedMultiBufferOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapAsyncOutputBroker> DebugMemoryMapAsyncOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapAsyncTriggerOutputBroker> DebugMemoryMapAsyncTriggerOutputBrokerBuilder;
// LCOV_EXCL_STOP
}