IVGCVSW-6816 Inject counter registration into ProfilingService

Change-Id: I87ce3a1306eced9fc347cc383d9c7bc8994f0b0c
Signed-off-by: Jim Flynn <jim.flynn@arm.com>
diff --git a/Android.mk b/Android.mk
index fde489f..5c722e1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -117,6 +117,7 @@
         profiling/server/src/timelineDecoder/TimelineCaptureCommandHandler.cpp \
         profiling/server/src/timelineDecoder/TimelineDecoder.cpp \
         profiling/server/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp \
+        src/armnn/ArmNNProfilingServiceInitialiser.cpp \
         src/armnn/BackendHelper.cpp \
         src/armnn/BackendRegistry.cpp \
         src/armnn/Descriptors.cpp \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 16f0188..c74d717 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -337,6 +337,8 @@
     src/armnn/layers/UnidirectionalSequenceLstmLayer.hpp
     src/armnn/layers/UnmapLayer.cpp
     src/armnn/layers/UnmapLayer.hpp
+    src/armnn/ArmNNProfilingServiceInitialiser.cpp
+    src/armnn/ArmNNProfilingServiceInitialiser.hpp
     src/armnn/AsyncExecutionCallback.cpp
     src/armnn/AsyncExecutionCallback.hpp
     src/armnn/BackendRegistry.cpp
@@ -424,6 +426,7 @@
     src/profiling/CommandHandler.hpp
     src/profiling/ConnectionAcknowledgedCommandHandler.cpp
     src/profiling/ConnectionAcknowledgedCommandHandler.hpp
+    src/profiling/Counter.hpp
     src/profiling/CounterDirectory.cpp
     src/profiling/CounterDirectory.hpp
     src/profiling/CounterIdMap.cpp
@@ -441,6 +444,7 @@
     src/profiling/ICounterDirectory.hpp
     src/profiling/ICounterRegistry.hpp
     src/profiling/ICounterValues.hpp
+    src/profiling/IInitialiseProfilingService.hpp
     src/profiling/INotifyBackends.hpp
     src/profiling/IReportStructure.hpp
     src/profiling/ISendCounterPacket.hpp
diff --git a/src/armnn/ArmNNProfilingServiceInitialiser.cpp b/src/armnn/ArmNNProfilingServiceInitialiser.cpp
new file mode 100644
index 0000000..d23cce5
--- /dev/null
+++ b/src/armnn/ArmNNProfilingServiceInitialiser.cpp
@@ -0,0 +1,121 @@
+//
+// Copyright © 2022 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ArmNNProfilingServiceInitialiser.hpp"
+
+#include <armnn/BackendRegistry.hpp>
+#include <armnn/profiling/ArmNNProfiling.hpp>
+#include <Counter.hpp>
+
+namespace armnn
+{
+
+void ArmNNProfilingServiceInitialiser::InitialiseProfilingService(arm::pipe::IProfilingService& profilingService)
+{
+    uint16_t ZERO = 0;
+    double ONE = 1.0;
+    std::string ArmNN_Runtime("ArmNN_Runtime");
+    // Register a category for the basic runtime counters
+    if (!profilingService.IsCategoryRegistered(ArmNN_Runtime))
+    {
+        profilingService.GetCounterRegistry().RegisterCategory(ArmNN_Runtime);
+    }
+
+    std::string networks("networks");
+    std::string networkLoads("Network loads");
+    // Register a counter for the number of Network loads
+    if (!profilingService.IsCounterRegistered(networkLoads))
+    {
+        const arm::pipe::Counter* loadedNetworksCounter =
+            profilingService.GetCounterRegistry().RegisterCounter(armnn::profiling::BACKEND_ID.Get(),
+                                                                  arm::pipe::NETWORK_LOADS,
+                                                                  ArmNN_Runtime,
+                                                                  ZERO,
+                                                                  ZERO,
+                                                                  ONE,
+                                                                  networkLoads,
+                                                                  "The number of networks loaded at runtime",
+                                                                  networks);
+        ARMNN_ASSERT(loadedNetworksCounter);
+        profilingService.InitializeCounterValue(loadedNetworksCounter->m_Uid);
+    }
+    // Register a counter for the number of unloaded networks
+    std::string networkUnloads("Network unloads");
+    if (!profilingService.IsCounterRegistered(networkUnloads))
+    {
+        const arm::pipe::Counter* unloadedNetworksCounter =
+            profilingService.GetCounterRegistry().RegisterCounter(armnn::profiling::BACKEND_ID.Get(),
+                                                                  arm::pipe::NETWORK_UNLOADS,
+                                                                  ArmNN_Runtime,
+                                                                  ZERO,
+                                                                  ZERO,
+                                                                  ONE,
+                                                                  networkUnloads,
+                                                                  "The number of networks unloaded at runtime",
+                                                                  networks);
+        ARMNN_ASSERT(unloadedNetworksCounter);
+        profilingService.InitializeCounterValue(unloadedNetworksCounter->m_Uid);
+    }
+    std::string backends("backends");
+    // Register a counter for the number of registered backends
+    std::string backendsRegistered("Backends registered");
+    if (!profilingService.IsCounterRegistered(backendsRegistered))
+    {
+        const arm::pipe::Counter* registeredBackendsCounter =
+            profilingService.GetCounterRegistry().RegisterCounter(armnn::profiling::BACKEND_ID.Get(),
+                                                                  arm::pipe::REGISTERED_BACKENDS,
+                                                                  ArmNN_Runtime,
+                                                                  ZERO,
+                                                                  ZERO,
+                                                                  ONE,
+                                                                  backendsRegistered,
+                                                                  "The number of registered backends",
+                                                                  backends);
+        ARMNN_ASSERT(registeredBackendsCounter);
+        profilingService.InitializeCounterValue(registeredBackendsCounter->m_Uid);
+
+        // Due to backends being registered before the profiling service becomes active,
+        // we need to set the counter to the correct value here
+        profilingService.SetCounterValue(arm::pipe::REGISTERED_BACKENDS, static_cast<uint32_t>(
+            armnn::BackendRegistryInstance().Size()));
+    }
+    // Register a counter for the number of registered backends
+    std::string backendsUnregistered("Backends unregistered");
+    if (!profilingService.IsCounterRegistered(backendsUnregistered))
+    {
+        const arm::pipe::Counter* unregisteredBackendsCounter =
+            profilingService.GetCounterRegistry().RegisterCounter(armnn::profiling::BACKEND_ID.Get(),
+                                                                  arm::pipe::UNREGISTERED_BACKENDS,
+                                                                  ArmNN_Runtime,
+                                                                  ZERO,
+                                                                  ZERO,
+                                                                  ONE,
+                                                                  backendsUnregistered,
+                                                                  "The number of unregistered backends",
+                                                                  backends);
+        ARMNN_ASSERT(unregisteredBackendsCounter);
+        profilingService.InitializeCounterValue(unregisteredBackendsCounter->m_Uid);
+    }
+    // Register a counter for the number of inferences run
+    std::string inferences("inferences");
+    std::string inferencesRun("Inferences run");
+    if (!profilingService.IsCounterRegistered(inferencesRun))
+    {
+        const arm::pipe::Counter* inferencesRunCounter =
+            profilingService.GetCounterRegistry().RegisterCounter(armnn::profiling::BACKEND_ID.Get(),
+                                                                 arm::pipe::INFERENCES_RUN,
+                                                                 ArmNN_Runtime,
+                                                                 ZERO,
+                                                                 ZERO,
+                                                                 ONE,
+                                                                 inferencesRun,
+                                                                 "The number of inferences run",
+                                                                 inferences);
+        ARMNN_ASSERT(inferencesRunCounter);
+        profilingService.InitializeCounterValue(inferencesRunCounter->m_Uid);
+    }
+}
+
+} // namespace armnn
diff --git a/src/armnn/ArmNNProfilingServiceInitialiser.hpp b/src/armnn/ArmNNProfilingServiceInitialiser.hpp
new file mode 100644
index 0000000..e8a0ae0
--- /dev/null
+++ b/src/armnn/ArmNNProfilingServiceInitialiser.hpp
@@ -0,0 +1,20 @@
+//
+// Copyright © 2022 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <IInitialiseProfilingService.hpp>
+#include <IProfilingService.hpp>
+
+namespace armnn
+{
+
+class ArmNNProfilingServiceInitialiser : public arm::pipe::IInitialiseProfilingService
+{
+public:
+    void InitialiseProfilingService(arm::pipe::IProfilingService& profilingService) override;
+};
+
+} // namespace armnn
diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp
index 4cc34ff..af257e1 100644
--- a/src/armnn/Runtime.cpp
+++ b/src/armnn/Runtime.cpp
@@ -2,6 +2,8 @@
 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
+
+#include "ArmNNProfilingServiceInitialiser.hpp"
 #include "Runtime.hpp"
 
 #include <armnn/Version.hpp>
@@ -115,7 +117,11 @@
                          std::vector<ImportedInputId> preImportedInputs,
                          std::vector<ImportedOutputId> preImportedOutputs)
 {
-    return pRuntimeImpl->Execute(workingMemHandle, inputTensors, outputTensors, preImportedInputs, preImportedOutputs);
+    return pRuntimeImpl->Execute(workingMemHandle,
+                                 inputTensors,
+                                 outputTensors,
+                                 preImportedInputs,
+                                 preImportedOutputs);
 }
 
 Status IRuntime::UnloadNetwork(NetworkId networkId)
@@ -295,10 +301,17 @@
     }
 }
 
+void RuntimeImpl::InitialiseProfilingService(arm::pipe::IProfilingService& profilingService)
+{
+    ArmNNProfilingServiceInitialiser initialiser;
+    initialiser.InitialiseProfilingService(profilingService);
+}
+
 RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
     : m_NetworkIdCounter(0)
 {
-    m_ProfilingService = arm::pipe::IProfilingService::CreateProfilingService(*this);
+    m_ProfilingService = arm::pipe::IProfilingService::CreateProfilingService(
+        arm::pipe::MAX_ARMNN_COUNTER, *this, *this);
     const auto start_time = armnn::GetTimeNow();
     ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION;
     if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
diff --git a/src/armnn/Runtime.hpp b/src/armnn/Runtime.hpp
index a8fa5fd..f2462b1 100644
--- a/src/armnn/Runtime.hpp
+++ b/src/armnn/Runtime.hpp
@@ -14,6 +14,7 @@
 
 #include <armnn/backends/DynamicBackend.hpp>
 
+#include <IInitialiseProfilingService.hpp>
 #include <IProfilingService.hpp>
 #include <IReportStructure.hpp>
 
@@ -24,8 +25,9 @@
 {
 using LoadedNetworks = std::unordered_map<NetworkId, std::unique_ptr<LoadedNetwork>>;
 using IReportStructure = arm::pipe::IReportStructure;
+    using IInitialiseProfilingService = arm::pipe::IInitialiseProfilingService;
 
-struct RuntimeImpl final :  public IReportStructure
+struct RuntimeImpl final :  public IReportStructure, public IInitialiseProfilingService
 {
 public:
     /// Loads a complete network into the Runtime.
@@ -108,7 +110,9 @@
 
     //NOTE: we won't need the profiling service reference but it is good to pass the service
     // in this way to facilitate other implementations down the road
-    void ReportStructure();
+    void ReportStructure() override;
+
+    void InitialiseProfilingService(arm::pipe::IProfilingService& profilingService) override;
 
 private:
     friend void RuntimeLoadedNetworksReserve(RuntimeImpl* runtime); // See RuntimeTests.cpp
diff --git a/src/armnn/test/RuntimeTests.cpp b/src/armnn/test/RuntimeTests.cpp
index 73e36ea..afe4bc7 100644
--- a/src/armnn/test/RuntimeTests.cpp
+++ b/src/armnn/test/RuntimeTests.cpp
@@ -6,6 +6,8 @@
 #include <armnn/Descriptors.hpp>
 #include <armnn/IRuntime.hpp>
 #include <armnn/INetwork.hpp>
+#include <armnn/profiling/ArmNNProfiling.hpp>
+#include <ArmNNProfilingServiceInitialiser.hpp>
 #include <ProfilingOptionsConverter.hpp>
 #include <Processes.hpp>
 #include <Runtime.hpp>
@@ -627,7 +629,9 @@
     armnn::NetworkId netId;
     CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
 
-    ProfilingServiceRuntimeHelper profilingServiceHelper(GetProfilingService(&runtime));
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingServiceRuntimeHelper profilingServiceHelper(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
     BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
     auto readableBuffer = bufferManager.GetReadableBuffer();
 
@@ -649,7 +653,9 @@
     GetProfilingService(&runtime).ResetExternalProfilingOptions(
         ConvertExternalProfilingOptions(options.m_ProfilingOptions), false);
 
-    ProfilingServiceRuntimeHelper profilingServiceHelper(GetProfilingService(&runtime));
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingServiceRuntimeHelper profilingServiceHelper(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
     profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
diff --git a/src/backends/backendsCommon/test/BackendProfilingTests.cpp b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
index d262abc..c0b4e0a 100644
--- a/src/backends/backendsCommon/test/BackendProfilingTests.cpp
+++ b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: MIT
 //
 
+#include "ArmNNProfilingServiceInitialiser.hpp"
 #include "CounterDirectory.hpp"
 #include "CounterIdMap.hpp"
 #include "Holder.hpp"
@@ -38,6 +39,11 @@
     {
         return (counterUid > 4 && counterUid < 11);
     }
+    virtual bool IsCounterRegistered(const std::string& counterName) const override
+    {
+        armnn::IgnoreUnused(counterName);
+        return false;
+    }
     virtual uint16_t GetCounterCount() const override
     {
         return 1;
@@ -161,12 +167,14 @@
     ProfilingOptions options;
     options.m_EnableProfiling = true;
 
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser);
 
     std::unique_ptr<IBackendProfiling> cpuBackendProfilingPtr =
-            std::make_unique<BackendProfiling>(options, profilingService, cpuAccId);
+        std::make_unique<BackendProfiling>(options, *profilingService.get(), cpuAccId);
     std::unique_ptr<IBackendProfiling> gpuBackendProfilingPtr =
-            std::make_unique<BackendProfiling>(options, profilingService, gpuAccId);
+        std::make_unique<BackendProfiling>(options, *profilingService.get(), gpuAccId);
 
     std::shared_ptr<IBackendProfilingContext> cpuProfilingContextPtr =
             std::make_shared<armnn::MockBackendProfilingContext>(cpuBackendProfilingPtr);
@@ -409,10 +417,12 @@
     ProfilingOptions options;
     options.m_EnableProfiling = true;
 
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser);
 
     std::unique_ptr<IBackendProfiling> cpuBackendProfilingPtr =
-            std::make_unique<BackendProfiling>(options, profilingService, cpuAccId);
+        std::make_unique<BackendProfiling>(options, *profilingService.get(), cpuAccId);
 
     std::shared_ptr<IBackendProfilingContext> cpuProfilingContextPtr =
             std::make_shared<armnn::MockBackendProfilingContext>(cpuBackendProfilingPtr);
@@ -461,15 +471,19 @@
     // Reset the profiling service to the uninitialized state
     armnn::IRuntime::CreationOptions options;
     options.m_ProfilingOptions.m_EnableProfiling = true;
-    ProfilingService profilingService;
-    profilingService.ConfigureProfilingService(
+
+    armnn::ArmNNProfilingServiceInitialiser psInitialiser;
+    std::unique_ptr<IProfilingService> profilingService = arm::pipe::IProfilingService::CreateProfilingService(
+        arm::pipe::MAX_ARMNN_COUNTER, psInitialiser);
+
+    profilingService->ConfigureProfilingService(
         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
 
     armnn::MockBackendInitialiser initialiser;
     // Create a runtime. During this the mock backend will be registered and context returned.
     armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
     armnn::MockBackendProfilingService mockProfilingService = armnn::MockBackendProfilingService::Instance();
-    armnn::MockBackendProfilingContext *mockBackEndProfilingContext = mockProfilingService.GetContext();
+    armnn::MockBackendProfilingContext* mockBackEndProfilingContext = mockProfilingService.GetContext();
     // Check that there is a valid context set.
     CHECK(mockBackEndProfilingContext);
     armnn::IBackendInternal::IBackendProfilingPtr& backendProfilingIface =
@@ -487,7 +501,7 @@
 
     // Reset the profiling servie after the test.
     options.m_ProfilingOptions.m_EnableProfiling = false;
-    profilingService.ResetExternalProfilingOptions(
+    profilingService->ResetExternalProfilingOptions(
         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
 }
 
diff --git a/src/profiling/Counter.hpp b/src/profiling/Counter.hpp
new file mode 100644
index 0000000..ff96d25
--- /dev/null
+++ b/src/profiling/Counter.hpp
@@ -0,0 +1,62 @@
+//
+// Copyright © 2022 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <string>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+class Counter final
+{
+public:
+    // Constructors
+    Counter(const std::string& backendId,
+            uint16_t           counterUid,
+            uint16_t           maxCounterUid,
+            uint16_t           counterClass,
+            uint16_t           interpolation,
+            double             multiplier,
+            const std::string& name,
+            const std::string& description,
+            const std::string& units,
+            uint16_t           deviceUid,
+            uint16_t           counterSetUid)
+        : m_BackendId(backendId)
+        , m_Uid(counterUid)
+        , m_MaxCounterUid(maxCounterUid)
+        , m_Class(counterClass)
+        , m_Interpolation(interpolation)
+        , m_Multiplier(multiplier)
+        , m_Name(name)
+        , m_Description(description)
+        , m_Units(units)
+        , m_DeviceUid(deviceUid)
+        , m_CounterSetUid(counterSetUid)
+    {}
+
+    // Fields
+    std::string m_BackendId;
+    uint16_t    m_Uid;
+    uint16_t    m_MaxCounterUid;
+    uint16_t    m_Class;
+    uint16_t    m_Interpolation;
+    double      m_Multiplier;
+    std::string m_Name;
+    std::string m_Description;
+    std::string m_Units;      // Optional, leave empty if the counter does not need units
+
+    // Connections
+    uint16_t m_DeviceUid;     // Optional, set to zero if the counter is not associated with a device
+    uint16_t m_CounterSetUid; // Optional, set to zero if the counter is not associated with a counter set
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/src/profiling/ICounterDirectory.hpp b/src/profiling/ICounterDirectory.hpp
index b6b513a..d024516 100644
--- a/src/profiling/ICounterDirectory.hpp
+++ b/src/profiling/ICounterDirectory.hpp
@@ -5,6 +5,7 @@
 
 #pragma once
 
+#include "Counter.hpp"
 
 #include <string>
 #include <vector>
@@ -22,7 +23,6 @@
 class Category;
 class Device;
 class CounterSet;
-class Counter;
 
 // Profiling objects smart pointer types
 using CategoryPtr   = std::unique_ptr<Category>;
@@ -89,50 +89,6 @@
     uint16_t    m_Count;
 };
 
-class Counter final
-{
-public:
-    // Constructors
-    Counter(const std::string& backendId,
-            uint16_t           counterUid,
-            uint16_t           maxCounterUid,
-            uint16_t           counterClass,
-            uint16_t           interpolation,
-            double             multiplier,
-            const std::string& name,
-            const std::string& description,
-            const std::string& units,
-            uint16_t           deviceUid,
-            uint16_t           counterSetUid)
-        : m_BackendId(backendId)
-        , m_Uid(counterUid)
-        , m_MaxCounterUid(maxCounterUid)
-        , m_Class(counterClass)
-        , m_Interpolation(interpolation)
-        , m_Multiplier(multiplier)
-        , m_Name(name)
-        , m_Description(description)
-        , m_Units(units)
-        , m_DeviceUid(deviceUid)
-        , m_CounterSetUid(counterSetUid)
-    {}
-
-    // Fields
-    std::string m_BackendId;
-    uint16_t    m_Uid;
-    uint16_t    m_MaxCounterUid;
-    uint16_t    m_Class;
-    uint16_t    m_Interpolation;
-    double      m_Multiplier;
-    std::string m_Name;
-    std::string m_Description;
-    std::string m_Units;      // Optional, leave empty if the counter does not need units
-
-    // Connections
-    uint16_t m_DeviceUid;     // Optional, set to zero if the counter is not associated with a device
-    uint16_t m_CounterSetUid; // Optional, set to zero if the counter is not associated with a counter set
-};
-
 class ICounterDirectory
 {
 public:
diff --git a/src/profiling/ICounterRegistry.hpp b/src/profiling/ICounterRegistry.hpp
index 9e04f60..72b08a6 100644
--- a/src/profiling/ICounterRegistry.hpp
+++ b/src/profiling/ICounterRegistry.hpp
@@ -37,10 +37,10 @@
                                            double multiplier,
                                            const std::string& name,
                                            const std::string& description,
-                                           const armnn::Optional<std::string>& units,
-                                           const armnn::Optional<uint16_t>& numberOfCores,
-                                           const armnn::Optional<uint16_t>& deviceUid,
-                                           const armnn::Optional<uint16_t>& counterSetUid) = 0;
+                                           const armnn::Optional<std::string>& units = armnn::EmptyOptional(),
+                                           const armnn::Optional<uint16_t>& numberOfCores = armnn::EmptyOptional(),
+                                           const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
+                                           const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional()) = 0;
 
 };
 
diff --git a/src/profiling/ICounterValues.hpp b/src/profiling/ICounterValues.hpp
index f49ddf4..a851c6b 100644
--- a/src/profiling/ICounterValues.hpp
+++ b/src/profiling/ICounterValues.hpp
@@ -19,6 +19,7 @@
     virtual ~IReadCounterValues() {}
 
     virtual bool IsCounterRegistered(uint16_t counterUid) const = 0;
+    virtual bool IsCounterRegistered(const std::string& counterName) const = 0;
     virtual uint16_t GetCounterCount() const = 0;
     virtual uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const = 0;
     virtual uint32_t GetDeltaCounterValue(uint16_t counterUid) = 0;
diff --git a/src/profiling/IInitialiseProfilingService.hpp b/src/profiling/IInitialiseProfilingService.hpp
new file mode 100644
index 0000000..fc3f4b9
--- /dev/null
+++ b/src/profiling/IInitialiseProfilingService.hpp
@@ -0,0 +1,26 @@
+//
+// Copyright © 2022 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+namespace arm
+{
+
+namespace pipe
+{
+
+// forward declaration
+class IProfilingService;
+
+class IInitialiseProfilingService
+{
+public:
+    virtual ~IInitialiseProfilingService() {}
+    virtual void InitialiseProfilingService(IProfilingService& profilingService) = 0;
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/src/profiling/IProfilingService.cpp b/src/profiling/IProfilingService.cpp
index 9b1aac5..cd85bb9 100644
--- a/src/profiling/IProfilingService.cpp
+++ b/src/profiling/IProfilingService.cpp
@@ -13,9 +13,11 @@
 {
 
 std::unique_ptr<IProfilingService> IProfilingService::CreateProfilingService(
+    uint16_t maxGlobalCounterId,
+    IInitialiseProfilingService& initialiser,
     armnn::Optional<IReportStructure&> reportStructure)
 {
-    return std::make_unique<ProfilingService>(reportStructure);
+    return std::make_unique<ProfilingService>(maxGlobalCounterId, initialiser, reportStructure);
 }
 
 ProfilingGuidGenerator IProfilingService::m_GuidGenerator;
diff --git a/src/profiling/IProfilingService.hpp b/src/profiling/IProfilingService.hpp
index b919522..912265e 100644
--- a/src/profiling/IProfilingService.hpp
+++ b/src/profiling/IProfilingService.hpp
@@ -9,6 +9,7 @@
 #include "Holder.hpp"
 #include "ICounterValues.hpp"
 #include "ICounterRegistry.hpp"
+#include "IInitialiseProfilingService.hpp"
 #include "IProfilingServiceStatus.hpp"
 #include "ISendCounterPacket.hpp"
 #include "IReportStructure.hpp"
@@ -31,6 +32,8 @@
 {
 public:
     static std::unique_ptr<IProfilingService> CreateProfilingService(
+        uint16_t maxGlobalCounterId,
+        IInitialiseProfilingService& initialiser,
         armnn::Optional<IReportStructure&> reportStructure = armnn::EmptyOptional());
     virtual ~IProfilingService() {};
     virtual std::unique_ptr<ISendTimelinePacket> GetSendTimelinePacket() const = 0;
@@ -50,6 +53,9 @@
         std::shared_ptr<IBackendProfilingContext> profilingContext) = 0;
     virtual ICounterRegistry& GetCounterRegistry() = 0;
     virtual IRegisterCounterMapping& GetCounterMappingRegistry() = 0;
+    virtual bool IsCategoryRegistered(const std::string& categoryName) const = 0;
+    virtual void InitializeCounterValue(uint16_t counterUid) = 0;
+
     // IProfilingGuidGenerator functions
     /// Return the next random Guid in the sequence
     ProfilingDynamicGuid NextGuid() override;
@@ -59,6 +65,8 @@
     static ProfilingStaticGuid GetStaticId(const std::string& str);
     void ResetGuidGenerator();
 
+    virtual void Disconnect() = 0;
+
 private:
     static ProfilingGuidGenerator m_GuidGenerator;
 };
diff --git a/src/profiling/ProfilingService.cpp b/src/profiling/ProfilingService.cpp
index eba70e1..97db6e9 100644
--- a/src/profiling/ProfilingService.cpp
+++ b/src/profiling/ProfilingService.cpp
@@ -254,6 +254,16 @@
     return m_CounterIdMap;
 }
 
+bool ProfilingService::IsCategoryRegistered(const std::string& categoryName) const
+{
+    return m_CounterDirectory.IsCategoryRegistered(categoryName);
+}
+
+bool ProfilingService::IsCounterRegistered(const std::string& counterName) const
+{
+    return m_CounterDirectory.IsCounterRegistered(counterName);
+}
+
 CaptureData ProfilingService::GetCaptureData()
 {
     return m_Holder.GetCaptureData();
@@ -305,96 +315,7 @@
 
 void ProfilingService::Initialize()
 {
-    // Register a category for the basic runtime counters
-    if (!m_CounterDirectory.IsCategoryRegistered("ArmNN_Runtime"))
-    {
-        m_CounterDirectory.RegisterCategory("ArmNN_Runtime");
-    }
-
-    // Register a counter for the number of Network loads
-    if (!m_CounterDirectory.IsCounterRegistered("Network loads"))
-    {
-        const Counter* loadedNetworksCounter =
-                m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
-                                                   NETWORK_LOADS,
-                                                   "ArmNN_Runtime",
-                                                   0,
-                                                   0,
-                                                   1.f,
-                                                   "Network loads",
-                                                   "The number of networks loaded at runtime",
-                                                   std::string("networks"));
-        ARMNN_ASSERT(loadedNetworksCounter);
-        InitializeCounterValue(loadedNetworksCounter->m_Uid);
-    }
-    // Register a counter for the number of unloaded networks
-    if (!m_CounterDirectory.IsCounterRegistered("Network unloads"))
-    {
-        const Counter* unloadedNetworksCounter =
-                m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
-                                                   NETWORK_UNLOADS,
-                                                   "ArmNN_Runtime",
-                                                   0,
-                                                   0,
-                                                   1.f,
-                                                   "Network unloads",
-                                                   "The number of networks unloaded at runtime",
-                                                   std::string("networks"));
-        ARMNN_ASSERT(unloadedNetworksCounter);
-        InitializeCounterValue(unloadedNetworksCounter->m_Uid);
-    }
-    // Register a counter for the number of registered backends
-    if (!m_CounterDirectory.IsCounterRegistered("Backends registered"))
-    {
-        const Counter* registeredBackendsCounter =
-                m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
-                                                   REGISTERED_BACKENDS,
-                                                   "ArmNN_Runtime",
-                                                   0,
-                                                   0,
-                                                   1.f,
-                                                   "Backends registered",
-                                                   "The number of registered backends",
-                                                   std::string("backends"));
-        ARMNN_ASSERT(registeredBackendsCounter);
-        InitializeCounterValue(registeredBackendsCounter->m_Uid);
-
-        // Due to backends being registered before the profiling service becomes active,
-        // we need to set the counter to the correct value here
-        SetCounterValue(REGISTERED_BACKENDS, static_cast<uint32_t>(armnn::BackendRegistryInstance().Size()));
-    }
-    // Register a counter for the number of registered backends
-    if (!m_CounterDirectory.IsCounterRegistered("Backends unregistered"))
-    {
-        const Counter* unregisteredBackendsCounter =
-                m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
-                                                   UNREGISTERED_BACKENDS,
-                                                   "ArmNN_Runtime",
-                                                   0,
-                                                   0,
-                                                   1.f,
-                                                   "Backends unregistered",
-                                                   "The number of unregistered backends",
-                                                   std::string("backends"));
-        ARMNN_ASSERT(unregisteredBackendsCounter);
-        InitializeCounterValue(unregisteredBackendsCounter->m_Uid);
-    }
-    // Register a counter for the number of inferences run
-    if (!m_CounterDirectory.IsCounterRegistered("Inferences run"))
-    {
-        const Counter* inferencesRunCounter =
-                m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
-                                                   INFERENCES_RUN,
-                                                   "ArmNN_Runtime",
-                                                   0,
-                                                   0,
-                                                   1.f,
-                                                   "Inferences run",
-                                                   "The number of inferences run",
-                                                   std::string("inferences"));
-        ARMNN_ASSERT(inferencesRunCounter);
-        InitializeCounterValue(inferencesRunCounter->m_Uid);
-    }
+    m_Initialiser.InitialiseProfilingService(*this);
 }
 
 void ProfilingService::InitializeCounterValue(uint16_t counterUid)
diff --git a/src/profiling/ProfilingService.hpp b/src/profiling/ProfilingService.hpp
index 7919c30..efad871 100644
--- a/src/profiling/ProfilingService.hpp
+++ b/src/profiling/ProfilingService.hpp
@@ -50,7 +50,9 @@
     using BackendProfilingContext = std::unordered_map<std::string,
                                                        std::shared_ptr<IBackendProfilingContext>>;
 
-    ProfilingService(armnn::Optional<IReportStructure&> reportStructure = armnn::EmptyOptional())
+    ProfilingService(uint16_t maxGlobalCounterId,
+                     IInitialiseProfilingService& initialiser,
+                     armnn::Optional<IReportStructure&> reportStructure = armnn::EmptyOptional())
         : m_Options()
         , m_TimelineReporting(false)
         , m_CounterDirectory()
@@ -118,8 +120,9 @@
                                                       m_StateMachine,
                                                       *this)
         , m_TimelinePacketWriterFactory(m_BufferManager)
-        , m_MaxGlobalCounterId(INFERENCES_RUN)
+        , m_MaxGlobalCounterId(maxGlobalCounterId)
         , m_ServiceActive(false)
+        , m_Initialiser(initialiser)
     {
         // Register the "Connection Acknowledged" command handler
         m_CommandHandlerRegistry.RegisterFunctor(&m_ConnectionAcknowledgedCommandHandler);
@@ -151,7 +154,7 @@
     void Update();
 
     // Disconnects the profiling service from the external server
-    void Disconnect();
+    void Disconnect() override;
 
     // Store a profiling context returned from a backend that support profiling.
     void AddBackendProfilingContext(const std::string& backendId,
@@ -170,6 +173,8 @@
     // counter global/backend mapping functions
     const ICounterMappings& GetCounterMappings() const override;
     IRegisterCounterMapping& GetCounterMappingRegistry() override;
+    bool IsCategoryRegistered(const std::string& categoryName) const override;
+    bool IsCounterRegistered(const std::string& counterName) const override;
 
     // Getters for the profiling service state
     bool IsProfilingEnabled() const override;
@@ -185,6 +190,8 @@
     uint32_t SubtractCounterValue(uint16_t counterUid, uint32_t value) override;
     uint32_t IncrementCounterValue(uint16_t counterUid) override;
 
+    void InitializeCounterValue(uint16_t counterUid) override;
+
     std::unique_ptr<ISendTimelinePacket> GetSendTimelinePacket() const override;
 
     ISendCounterPacket& GetSendCounterPacket() override
@@ -211,7 +218,6 @@
 
     // Initialization/reset functions
     void Initialize();
-    void InitializeCounterValue(uint16_t counterUid);
     void Reset();
     void Stop();
 
@@ -256,6 +262,8 @@
     std::condition_variable m_ServiceActiveConditionVariable;
     bool m_ServiceActive;
 
+    IInitialiseProfilingService& m_Initialiser;
+
 protected:
 
     // Protected methods for testing
diff --git a/src/profiling/test/ProfilingMocks.hpp b/src/profiling/test/ProfilingMocks.hpp
index 9314503..ca11ae4 100644
--- a/src/profiling/test/ProfilingMocks.hpp
+++ b/src/profiling/test/ProfilingMocks.hpp
@@ -628,9 +628,12 @@
 class MockProfilingService : public ProfilingService
 {
 public:
-    MockProfilingService(MockBufferManager& mockBufferManager,
+    MockProfilingService(uint16_t maxGlobalCounterId,
+                         IInitialiseProfilingService& initialiser,
+                         MockBufferManager& mockBufferManager,
                          bool isProfilingEnabled,
                          const CaptureData& captureData) :
+        ProfilingService(maxGlobalCounterId, initialiser),
         m_SendCounterPacket(mockBufferManager),
         m_IsProfilingEnabled(isProfilingEnabled),
         m_CaptureData(captureData)
diff --git a/src/profiling/test/ProfilingTestUtils.cpp b/src/profiling/test/ProfilingTestUtils.cpp
index 1542346..0d8988c 100644
--- a/src/profiling/test/ProfilingTestUtils.cpp
+++ b/src/profiling/test/ProfilingTestUtils.cpp
@@ -3,11 +3,13 @@
 // SPDX-License-Identifier: MIT
 //
 
+#include <ArmNNProfilingServiceInitialiser.hpp>
 #include "ProfilingOptionsConverter.hpp"
 #include "ProfilingTestUtils.hpp"
 #include "ProfilingUtils.hpp"
 
 #include <armnn/Descriptors.hpp>
+#include <armnn/profiling/ArmNNProfiling.hpp>
 #include <armnn/utility/Assert.hpp>
 #include <armnn/utility/NumericCast.hpp>
 
@@ -125,7 +127,8 @@
     }
     else
     {
-        ProfilingService profilingService;
+        ArmNNProfilingServiceInitialiser initialiser;
+        ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
         CHECK(readProfilingGuid == profilingService.GetStaticId(label));
     }
 
@@ -373,7 +376,9 @@
     GetProfilingService(&runtime).ResetExternalProfilingOptions(
         ConvertExternalProfilingOptions(options.m_ProfilingOptions), false);
 
-    ProfilingServiceRuntimeHelper profilingServiceHelper(GetProfilingService(&runtime));
+    ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingServiceRuntimeHelper profilingServiceHelper(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
     profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
diff --git a/src/profiling/test/ProfilingTestUtils.hpp b/src/profiling/test/ProfilingTestUtils.hpp
index 32a156e..323a762 100644
--- a/src/profiling/test/ProfilingTestUtils.hpp
+++ b/src/profiling/test/ProfilingTestUtils.hpp
@@ -71,19 +71,21 @@
 class ProfilingServiceRuntimeHelper : public ProfilingService
 {
 public:
-    ProfilingServiceRuntimeHelper(IProfilingService& profilingService)
-    : m_ProfilingService(profilingService) {}
+    ProfilingServiceRuntimeHelper(uint16_t maxGlobalCounterId,
+                                  IInitialiseProfilingService& initialiser,
+                                  arm::pipe::IProfilingService& profilingService)
+        : ProfilingService(maxGlobalCounterId, initialiser), m_ProfilingService(profilingService) {}
     ~ProfilingServiceRuntimeHelper() = default;
 
     BufferManager& GetProfilingBufferManager()
     {
-        return GetBufferManager(static_cast<ProfilingService&>(m_ProfilingService));
+        return GetBufferManager(static_cast<arm::pipe::ProfilingService&>(m_ProfilingService));
     }
-    IProfilingService& m_ProfilingService;
+    arm::pipe::IProfilingService& m_ProfilingService;
 
     void ForceTransitionToState(ProfilingState newState)
     {
-        TransitionToState(static_cast<ProfilingService&>(m_ProfilingService), newState);
+        TransitionToState(static_cast<arm::pipe::ProfilingService&>(m_ProfilingService), newState);
     }
 };
 
diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp
index 0a98af2..fd26703 100644
--- a/src/profiling/test/ProfilingTests.cpp
+++ b/src/profiling/test/ProfilingTests.cpp
@@ -3,6 +3,8 @@
 // SPDX-License-Identifier: MIT
 //
 
+#include <ArmNNProfilingServiceInitialiser.hpp>
+
 #include "ProfilingTests.hpp"
 #include "ProfilingTestUtils.hpp"
 
@@ -18,6 +20,7 @@
 #include <ICounterValues.hpp>
 #include <PeriodicCounterCapture.hpp>
 #include <PeriodicCounterSelectionCommandHandler.hpp>
+#include <armnn/profiling/ArmNNProfiling.hpp>
 #include <armnn/profiling/ProfilingOptions.hpp>
 #include <ProfilingStateMachine.hpp>
 #include <ProfilingUtils.hpp>
@@ -657,7 +660,8 @@
 TEST_CASE("CheckProfilingServiceDisabled")
 {
     ProfilingOptions options;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
     profilingService.Update();
@@ -667,7 +671,8 @@
 TEST_CASE("CheckProfilingServiceCounterDirectory")
 {
     ProfilingOptions options;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     const ICounterDirectory& counterDirectory0 = profilingService.GetCounterDirectory();
@@ -691,7 +696,8 @@
 {
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     profilingService.Update();
@@ -1767,6 +1773,11 @@
             armnn::IgnoreUnused(counterUid);
             return true;
         }
+        bool IsCounterRegistered(const std::string& counterName) const override
+        {
+            armnn::IgnoreUnused(counterName);
+            return true;
+        }
         uint16_t GetCounterCount() const override
         {
             return 0;
@@ -2007,7 +2018,9 @@
     options.m_ProfilingOptions.m_EnableProfiling = true;
 
     armnn::RuntimeImpl runtime(options);
-    ProfilingServiceRuntimeHelper profilingServiceHelper(GetProfilingService(&runtime));
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingServiceRuntimeHelper profilingServiceHelper(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
     profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
     profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
@@ -2302,7 +2315,11 @@
             armnn::IgnoreUnused(counterUid);
             return false;
         }
-
+        bool IsCounterRegistered(const std::string& counterName) const override
+        {
+            armnn::IgnoreUnused(counterName);
+            return false;
+        }
         uint16_t GetCounterCount() const override
         {
             return m_CounterSize;
@@ -2550,11 +2567,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "WaitingForAck" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2610,11 +2628,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2668,11 +2687,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2747,11 +2767,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2812,11 +2833,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2889,11 +2911,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -2968,11 +2991,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Try to disconnect the profiling service while in the "Uninitialised" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -3026,11 +3050,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -3093,7 +3118,8 @@
 {
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
     profilingService.ConfigureProfilingService(options);
     // should get as far as NOT_CONNECTED
@@ -3106,7 +3132,8 @@
 TEST_CASE("CheckConfigureProfilingServiceOff")
 {
     ProfilingOptions options;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
     profilingService.ConfigureProfilingService(options);
     // should not move from Uninitialised
@@ -3122,7 +3149,8 @@
     LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
     profilingService.Update();
@@ -3152,7 +3180,8 @@
     // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
     LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
     ProfilingOptions options;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
     profilingService.Update();
@@ -3195,11 +3224,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "WaitingForAck" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -3257,11 +3287,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -3321,11 +3352,12 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Swap the profiling connection factory in the profiling service instance with our mock one
-    SwapProfilingConnectionFactoryHelper helper(profilingService);
+    SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
 
     // Bring the profiling service to the "Active" state
     CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
@@ -3422,7 +3454,8 @@
     // Reset the profiling service to the uninitialized state
     ProfilingOptions options;
     options.m_EnableProfiling          = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     RegisterBackendCounters registerBackendCounters(globalCounterIds, cpuRefId, profilingService);
@@ -3471,7 +3504,8 @@
     options.m_EnableProfiling = true;
 
     // Reset the profiling service to the uninitialized state
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     const std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
@@ -3609,7 +3643,10 @@
     MockBufferManager mockBuffer(1024);
 
     CaptureData captureData;
-    MockProfilingService mockProfilingService(mockBuffer, options.m_EnableProfiling, captureData);
+
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    MockProfilingService mockProfilingService(
+        arm::pipe::MAX_ARMNN_COUNTER, initialiser, mockBuffer, options.m_EnableProfiling, captureData);
     std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
 
     mockProfilingService.RegisterMapping(6, 0, cpuRefId);
@@ -3674,7 +3711,8 @@
     // Change file format to an unsupported value
     options.m_FileFormat = "json";
     // Enable the profiling service
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
     // Start the command handler and the send thread
     profilingService.Update();
diff --git a/src/profiling/test/ProfilingTests.hpp b/src/profiling/test/ProfilingTests.hpp
index fd8ad31..e1590bd 100644
--- a/src/profiling/test/ProfilingTests.hpp
+++ b/src/profiling/test/ProfilingTests.hpp
@@ -206,8 +206,10 @@
 public:
     using MockProfilingConnectionFactoryPtr = std::unique_ptr<MockProfilingConnectionFactory>;
 
-    SwapProfilingConnectionFactoryHelper(ProfilingService& profilingService)
-        : ProfilingService()
+    SwapProfilingConnectionFactoryHelper(uint16_t maxGlobalCounterId,
+                                         IInitialiseProfilingService& initialiser,
+                                         ProfilingService& profilingService)
+        : ProfilingService(maxGlobalCounterId, initialiser)
         , m_ProfilingService(profilingService)
         , m_MockProfilingConnectionFactory(new MockProfilingConnectionFactory())
         , m_BackupProfilingConnectionFactory(nullptr)
diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp
index 4e32149..76fa9c1 100644
--- a/src/profiling/test/SendTimelinePacketTests.cpp
+++ b/src/profiling/test/SendTimelinePacketTests.cpp
@@ -5,11 +5,13 @@
 
 #include "ProfilingMocks.hpp"
 
+#include <ArmNNProfilingServiceInitialiser.hpp>
 #include <BufferManager.hpp>
 #include <ProfilingService.hpp>
 #include "ProfilingOptionsConverter.hpp"
 #include <ProfilingUtils.hpp>
 #include <SendTimelinePacket.hpp>
+#include <armnn/profiling/ArmNNProfiling.hpp>
 #include <armnnUtils/Threads.hpp>
 #include <TimelinePacketWriterFactory.hpp>
 
@@ -429,7 +431,8 @@
     armnn::IRuntime::CreationOptions options;
     options.m_ProfilingOptions.m_EnableProfiling = true;
     armnn::RuntimeImpl runtime(options);
-    ProfilingService profilingService(runtime);
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser, runtime);
 
     profilingService.ResetExternalProfilingOptions(
         ConvertExternalProfilingOptions(options.m_ProfilingOptions), true);
@@ -450,7 +453,8 @@
 {
     ProfilingOptions options;
     options.m_EnableProfiling = true;
-    ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     std::unique_ptr<ISendTimelinePacket> writer = profilingService.GetSendTimelinePacket();
diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp
index b0b7bff..0833eb4 100644
--- a/src/profiling/test/TimelineUtilityMethodsTests.cpp
+++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp
@@ -6,10 +6,13 @@
 #include "ProfilingMocks.hpp"
 #include "ProfilingTestUtils.hpp"
 
+#include <ArmNNProfilingServiceInitialiser.hpp>
 #include <SendTimelinePacket.hpp>
 #include <TimelineUtilityMethods.hpp>
 #include <ProfilingService.hpp>
 
+#include <armnn/profiling/ArmNNProfiling.hpp>
+
 #include <common/include/LabelsAndEventClasses.hpp>
 
 #include <memory>
@@ -24,7 +27,8 @@
 TEST_CASE("CreateTypedLabelTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
 
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
@@ -74,7 +78,8 @@
 TEST_CASE("SendWellKnownLabelsAndEventClassesTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     SendTimelinePacket sendTimelinePacket(mockBufferManager);
 
     CHECK_NOTHROW(TimelineUtilityMethods::SendWellKnownLabelsAndEventClasses(sendTimelinePacket));
@@ -201,7 +206,8 @@
 TEST_CASE("CreateNamedTypedChildEntityTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
 
@@ -288,7 +294,8 @@
 TEST_CASE("DeclareLabelTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
 
@@ -317,7 +324,8 @@
 TEST_CASE("CreateNameTypeEntityInvalidTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
 
@@ -342,7 +350,8 @@
 TEST_CASE("CreateNameTypeEntityTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
 
@@ -409,7 +418,8 @@
 TEST_CASE("RecordEventTest")
 {
     MockBufferManager mockBufferManager(1024);
-    ProfilingService  profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager);
     TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
     // Generate first guid to ensure that the named typed entity guid is not 0 on local single test.
diff --git a/tests/profiling/gatordmock/tests/GatordMockTests.cpp b/tests/profiling/gatordmock/tests/GatordMockTests.cpp
index 1556058..ff007bb 100644
--- a/tests/profiling/gatordmock/tests/GatordMockTests.cpp
+++ b/tests/profiling/gatordmock/tests/GatordMockTests.cpp
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: MIT
 //
 
+#include <ArmNNProfilingServiceInitialiser.hpp>
 #include <DirectoryCaptureCommandHandler.hpp>
 #include <GatordMockService.hpp>
 #include <ProfilingService.hpp>
@@ -254,7 +255,8 @@
     options.m_EnableProfiling = true;
     options.m_TimelineEnabled = true;
 
-    arm::pipe::ProfilingService profilingService;
+    armnn::ArmNNProfilingServiceInitialiser initialiser;
+    arm::pipe::ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
     profilingService.ResetExternalProfilingOptions(options, true);
 
     // Bring the profiling service to the "WaitingForAck" state
@@ -417,8 +419,8 @@
         FAIL("Failed to receive StreamMetaData");
     }
 
-    armnn::MockBackendProfilingService mockProfilingService = armnn::MockBackendProfilingService::Instance();
-    armnn::MockBackendProfilingContext *mockBackEndProfilingContext = mockProfilingService.GetContext();
+    armnn::MockBackendProfilingService  mockProfilingService = armnn::MockBackendProfilingService::Instance();
+    armnn::MockBackendProfilingContext* mockBackEndProfilingContext = mockProfilingService.GetContext();
 
     // Send Ack from GatorD
     mockService.SendConnectionAck();