MLECO-756 First cut of adding JSONTimelineDecoder and tests
authorÉanna Ó Catháin <eanna.ocathain@arm.com>
Wed, 1 Apr 2020 14:40:12 +0000 (15:40 +0100)
committerJim Flynn <jim.flynn@arm.com>
Wed, 1 Apr 2020 15:21:49 +0000 (15:21 +0000)
Change-Id: Ibcd5fdefb5dda3ac3f2a5ff6d6eca618c27c538b
Signed-off-by: Éanna Ó Catháin <eanna.ocathain@arm.com>
CMakeLists.txt
src/timelineDecoder/CMakeLists.txt
src/timelineDecoder/JSONTimelineDecoder.cpp [new file with mode: 0644]
src/timelineDecoder/JSONTimelineDecoder.hpp [new file with mode: 0644]
src/timelineDecoder/tests/JSONTimelineDecoderTests.cpp [new file with mode: 0644]

index 605e0421ed83022c2a934c48a7db5094dd833451..c093344acd7e084059129046498bfb0a6bcd2689 100644 (file)
@@ -883,6 +883,7 @@ if(BUILD_UNIT_TESTS)
 
     if(BUILD_TIMELINE_DECODER)
         list(APPEND unittest_sources
+             src/timelineDecoder/tests/JSONTimelineDecoderTests.cpp
              src/timelineDecoder/tests/TimelineTests.cpp
              )
     endif()
index e34fae71fadc495f776e0a576eaa152a022100b0..12fe2a0f0472ef08519a30df3c18e9e64a47e136 100644 (file)
@@ -9,6 +9,8 @@ if(BUILD_TIMELINE_DECODER)
             ../../include/armnn/profiling/ITimelineDecoder.hpp
             TimelineCaptureCommandHandler.cpp
             TimelineCaptureCommandHandler.hpp
+            JSONTimelineDecoder.cpp
+            JSONTimelineDecoder.hpp
             TimelineDecoder.cpp
             TimelineDecoder.hpp
             TimelineDirectoryCaptureCommandHandler.cpp
diff --git a/src/timelineDecoder/JSONTimelineDecoder.cpp b/src/timelineDecoder/JSONTimelineDecoder.cpp
new file mode 100644 (file)
index 0000000..520995a
--- /dev/null
@@ -0,0 +1,406 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "JSONTimelineDecoder.hpp"
+#include "../profiling/ProfilingUtils.hpp"
+
+#include <string>
+#include <fstream>
+
+namespace armnn
+{
+namespace timelinedecoder
+{
+
+static const char *const CONNECTION = "connection";
+static const char *const BACKEND_ID = "backendId";
+static const char *const NAME = "name";
+static const char *const TYPE = "type";
+static const char *const WORKLOAD = "workload";
+static const char *const WORKLOAD_EXECUTION = "workload_execution";
+static const char *const INFERENCE = "inference";
+static const char *const LAYER = "layer";
+static const char *const ENTITY = "Entity";
+static const char *const EVENTCLASS = "EventClass";
+static const char *const EVENT = "Event";
+
+JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEntity(const Entity& entity)
+{
+    JSONEntity jsonEntity(entity.m_Guid);
+    jsonEntity.SetType(ENTITY);
+    this->m_Model.jsonEntities.insert({entity.m_Guid, jsonEntity});
+    return TimelineStatus::TimelineStatus_Success;
+}
+
+JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEventClass(const EventClass& eventClass)
+{
+    JSONEntity jsonEntity(eventClass.m_Guid);
+    jsonEntity.SetType(EVENTCLASS);
+    this->m_Model.eventClasses.insert({eventClass.m_Guid, eventClass});
+    this->m_Model.jsonEntities.insert({eventClass.m_Guid, jsonEntity});
+    return TimelineStatus::TimelineStatus_Success;
+}
+
+JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEvent(const Event& event)
+{
+    JSONEntity jsonEntity(event.m_Guid);
+    jsonEntity.SetType(EVENT);
+    this->m_Model.events.insert({event.m_Guid, event});
+    this->m_Model.jsonEntities.insert({jsonEntity.GetGuid(), jsonEntity});
+    return TimelineStatus::TimelineStatus_Success;
+}
+
+JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateLabel(const Label& label)
+{
+    this->m_Model.labels.insert({label.m_Guid, label});
+    return TimelineStatus::TimelineStatus_Success;
+}
+
+JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateRelationship(const Relationship& relationship)
+{
+    if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::RetentionLink)
+    {
+        HandleRetentionLink(relationship);
+    }
+    else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::LabelLink)
+    {
+        HandleLabelLink(relationship);
+    }
+    else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::ExecutionLink)
+    {
+        HandleExecutionLink(relationship);
+    }
+    else
+    {
+        /*
+         * TODO Handle DataLink
+         */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+
+    return TimelineStatus::TimelineStatus_Success;
+}
+
+
+void JSONTimelineDecoder::HandleExecutionLink(const ITimelineDecoder::Relationship& relationship)
+{
+    uint64_t tailGuid = relationship.m_TailGuid;
+    uint64_t headGuid = relationship.m_HeadGuid;
+
+    if (m_Model.jsonEntities.count(relationship.m_HeadGuid) != 0)
+    {
+        JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(tailGuid);
+        JSONEntity& headJSONEntity = m_Model.jsonEntities.at(headGuid);
+        tailJSONEntity.SetParent(headJSONEntity);
+        m_Model.jsonEntities.insert({headGuid, headJSONEntity});
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+    else
+    {
+        /*
+         * TODO Add some protection against packet ordering issues
+         */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleLabelLink(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.labels.count(relationship.m_TailGuid) != 0)
+    {
+        if (m_Model.labels.at(relationship.m_TailGuid).m_Name == CONNECTION)
+        {
+            HandleConnectionLabel(relationship);
+        }
+        else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == BACKEND_ID)
+        {
+            HandleBackendIdLabel(relationship);
+        }
+        else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == NAME)
+        {
+            HandleNameLabel(relationship);
+        }
+        else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == TYPE)
+        {
+            HandleTypeLabel(relationship);
+        }
+        else
+        {
+            /*
+             * TODO Add some protection against packet ordering issues
+             */
+            m_Model.relationships.insert({relationship.m_Guid, relationship});
+        }
+    } else
+    {
+        /*
+         * TODO Add some protection against packet ordering issues
+         */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleTypeLabel(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
+    {
+        Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
+        if (m_Model.jsonEntities.count(labelRelation.m_HeadGuid) != 0)
+        {
+            JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
+            std::string type = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
+            headEntity.SetType(type);
+        }
+    }
+    else
+    {
+        /*
+        * TODO Add some protection against packet ordering issues
+        */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleNameLabel(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
+    {
+        Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
+        JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
+        std::string name = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
+        headEntity.SetName(name);
+    }
+    else
+    {
+        /*
+        * TODO Add some protection against packet ordering issues
+        */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleBackendIdLabel(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
+    {
+        Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
+        JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
+        std::string backendName = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
+        headEntity.extendedData.insert({BACKEND_ID, backendName});
+    }
+    else
+    {
+        /*
+        * TODO Add some protection against packet ordering issues
+        */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleConnectionLabel(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
+    {
+        Relationship retentionRelation = m_Model.relationships.at(relationship.m_HeadGuid);
+        JSONEntity& headEntity = m_Model.jsonEntities.at(retentionRelation.m_HeadGuid);
+        JSONEntity& tailEntity = m_Model.jsonEntities.at(retentionRelation.m_TailGuid);
+        headEntity.AddConnection(headEntity, tailEntity);
+    }
+    else
+    {
+        /*
+        * TODO Add some protection against packet ordering issues
+        */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::HandleRetentionLink(const ITimelineDecoder::Relationship& relationship)
+{
+    if (m_Model.jsonEntities.count(relationship.m_TailGuid) != 0 && m_Model.jsonEntities
+    .count(relationship.m_HeadGuid) != 0)
+    {
+        JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(relationship.m_TailGuid);
+        JSONEntity& headJSONEntity = m_Model.jsonEntities.at(relationship.m_HeadGuid);
+        tailJSONEntity.SetParent(headJSONEntity);
+        m_Model.jsonEntities.insert({relationship.m_HeadGuid, headJSONEntity});
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+    else
+    {
+        /*
+        * TODO Add some protection against packet ordering issues
+        */
+        m_Model.relationships.insert({relationship.m_Guid, relationship});
+    }
+}
+
+void JSONTimelineDecoder::JSONEntity::SetParent(JSONEntity& parent)
+{
+    parent.childEntities.push_back(GetGuid());
+}
+
+void JSONTimelineDecoder::PrintJSON(JSONTimelineDecoder::JSONEntity& rootEntity)
+{
+    std::string jsonString = GetJSONString(rootEntity);
+    std::ofstream outfile;
+    outfile.open(this->outputJSONFile);
+    outfile << jsonString;
+}
+
+std::string JSONTimelineDecoder::GetJSONString(JSONTimelineDecoder::JSONEntity& rootEntity)
+{
+    int counter = 0;
+    std::string json;
+    json.append("{\n");
+    if(rootEntity.GetType() != "")
+    {
+        json.append("\tArmNN");
+        json.append(": {\n");
+
+        for (uint64_t childEntityId : rootEntity.childEntities)
+        {
+            JSONEntity& childEntity = this->m_Model.jsonEntities.at(childEntityId);
+            json.append(GetJSONEntityString(childEntity, counter));
+        }
+    }
+    json.append("}\n");
+    return json;
+}
+
+std::string JSONTimelineDecoder::GetJSONEntityString(JSONTimelineDecoder::JSONEntity& entity, int& counter)
+{
+    std::string jsonEntityString;
+    if(entity.GetType() == LAYER)
+    {
+        return GetLayerJSONString(entity, counter, jsonEntityString);
+    }
+    else if (entity.GetType() == WORKLOAD)
+    {
+        return GetWorkloadJSONString(entity, counter, jsonEntityString);
+    }
+    else if (entity.GetType() == WORKLOAD_EXECUTION)
+    {
+        return GetWorkloadExecutionJSONString(entity, jsonEntityString);
+    }
+    else if (entity.GetType() == INFERENCE)
+    {
+        return jsonEntityString;
+    }
+    else
+    {
+        for (uint64_t child_entity_id : entity.childEntities)
+        {
+            JSONEntity& childEntity = this->m_Model.jsonEntities.at(child_entity_id);
+            jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
+        }
+        return jsonEntityString;
+    }
+}
+
+std::string JSONTimelineDecoder::GetWorkloadExecutionJSONString(const JSONTimelineDecoder::JSONEntity& entity,
+                                                                std::string& jsonEntityString) const
+{
+    if(entity.childEntities.size() < 2)
+    {
+        throw Exception("Workload Execution Entity Packet does not have the expected Event packets attached");
+    }
+    JSONEntity jsonEventOne = entity.childEntities[0];
+    JSONEntity jsonEventTwo = entity.childEntities[1];
+
+    Event event1 = m_Model.events.at(jsonEventOne.GetGuid());
+    Event event2 = m_Model.events.at(jsonEventTwo.GetGuid());
+
+    uint64_t wall_clock_time = event2.m_TimeStamp - event1.m_TimeStamp;
+    jsonEntityString.append("\t\t\t");
+    jsonEntityString.append("raw : [");
+    jsonEntityString.append(std::to_string(wall_clock_time));
+    jsonEntityString.append("], \n");
+    jsonEntityString.append("\t\t\t");
+    jsonEntityString.append("unit : us,\n");
+    jsonEntityString.append("\t\t\t");
+    jsonEntityString.append("}\n");
+
+    return jsonEntityString;
+}
+
+std::string JSONTimelineDecoder::GetWorkloadJSONString(const JSONTimelineDecoder::JSONEntity& entity, int& counter,
+                                                       std::string& jsonEntityString)
+{
+    jsonEntityString.append("\t\t\t");
+    jsonEntityString.append("backendId :");
+    jsonEntityString.append(entity.extendedData.at(BACKEND_ID));
+    jsonEntityString.append(",\n");
+    for (uint64_t child_entity_id : entity.childEntities)
+    {
+        JSONEntity &childEntity = m_Model.jsonEntities.at(child_entity_id);
+        jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
+    }
+    return jsonEntityString;
+}
+
+std::string JSONTimelineDecoder::GetLayerJSONString(JSONTimelineDecoder::JSONEntity& entity, int& counter,
+                                                    std::string& jsonEntityString)
+{
+    jsonEntityString.append("\t\t");
+    jsonEntityString.append(entity.GetName());
+    jsonEntityString.append("_");
+    jsonEntityString.append(std::to_string(counter));
+    jsonEntityString.append(": {\n");
+    jsonEntityString.append("\t\t\t");
+    jsonEntityString.append("type: Measurement,\n");
+    for (uint64_t child_entity_id : entity.childEntities)
+    {
+        JSONEntity& childEntity = m_Model.jsonEntities.at(child_entity_id);
+        jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
+    }
+    return jsonEntityString;
+}
+
+void JSONTimelineDecoder::JSONEntity::AddConnection(JSONEntity& headEntity, JSONEntity& connectedEntity)
+{
+    std::vector<uint64_t>::iterator it = std::find(headEntity.childEntities.begin(),
+            headEntity.childEntities.end(), connectedEntity.GetGuid());
+    headEntity.childEntities.erase(it);
+    headEntity.connected_entities.push_back(connectedEntity.m_Guid);
+}
+
+uint64_t JSONTimelineDecoder::JSONEntity::GetGuid()
+{
+    return m_Guid;
+}
+
+const JSONTimelineDecoder::Model &JSONTimelineDecoder::GetModel()
+{
+    return m_Model;
+}
+
+void JSONTimelineDecoder::SetOutgoingCaptureFile(const std::string& outgoingCaptureFile)
+{
+    this->outputJSONFile = outgoingCaptureFile;
+}
+
+void JSONTimelineDecoder::JSONEntity::SetName(std::string entityName)
+{
+    this->name = entityName;
+}
+
+std::string JSONTimelineDecoder::JSONEntity::GetName()
+{
+    return this->name;
+}
+
+void JSONTimelineDecoder::JSONEntity::SetType(std::string entityType)
+{
+    this->type = entityType;
+}
+
+std::string JSONTimelineDecoder::JSONEntity::GetType()
+{
+    return this->type;
+}
+
+}
+}
\ No newline at end of file
diff --git a/src/timelineDecoder/JSONTimelineDecoder.hpp b/src/timelineDecoder/JSONTimelineDecoder.hpp
new file mode 100644 (file)
index 0000000..17ee84b
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "armnn/profiling/ITimelineDecoder.hpp"
+
+#include <map>
+#include <vector>
+
+namespace armnn
+{
+namespace timelinedecoder
+{
+class JSONTimelineDecoder : public ITimelineDecoder
+{
+public:
+    struct JSONEntity
+    {
+    public:
+        std::vector<uint64_t> connected_entities;
+        std::vector<uint64_t> childEntities;
+
+        JSONEntity(uint64_t guid): m_Guid(guid){}
+        uint64_t GetGuid();
+        std::string GetName();
+        std::string GetType();
+        void SetName(std::string entityName);
+        void SetType(std::string entityType);
+        void SetParent(JSONEntity& parent);
+        void AddConnection(JSONEntity& headEntity, JSONEntity& connectedEntity);
+        std::map<std::string, std::string> extendedData;
+
+    private:
+        uint64_t m_Guid;
+        std::string name;
+        std::string type;
+    };
+
+    struct Model
+    {
+        std::map<uint64_t, JSONEntity> jsonEntities;
+        std::map<uint64_t, Relationship> relationships;
+        std::map<uint64_t, Label> labels;
+        std::map<uint64_t, Event> events;
+        std::map<uint64_t, EventClass> eventClasses;
+    };
+
+    void PrintJSON(JSONEntity& entity);
+    std::string GetJSONString(JSONEntity& rootEntity);
+    std::string GetJSONEntityString(JSONEntity& entity, int& counter);
+
+    virtual TimelineStatus CreateEntity(const Entity&) override;
+    virtual TimelineStatus CreateEventClass(const EventClass&) override;
+    virtual TimelineStatus CreateEvent(const Event&) override;
+    virtual TimelineStatus CreateLabel(const Label&) override;
+    virtual TimelineStatus CreateRelationship(const Relationship&) override;
+
+    const Model& GetModel();
+    void SetOutgoingCaptureFile(const std::string& basicString);
+
+private:
+    Model m_Model;
+    std::string outputJSONFile = "/tmp/output.json";
+
+    void HandleRetentionLink(const Relationship& relationship);
+    void HandleLabelLink(const Relationship& relationship);
+    void HandleExecutionLink(const Relationship& relationship);
+    void HandleConnectionLabel(const Relationship& relationship);
+    void HandleBackendIdLabel(const Relationship& relationship);
+    void HandleNameLabel(const Relationship& relationship);
+    void HandleTypeLabel(const Relationship& relationship);
+
+    std::string GetLayerJSONString(JSONEntity& entity, int& counter, std::string& jsonEntityString);
+    std::string GetWorkloadJSONString(const JSONEntity& entity, int& counter, std::string& jsonEntityString);
+    std::string GetWorkloadExecutionJSONString(const JSONEntity& entity, std::string& jsonEntityString) const;
+};
+
+}
+}
\ No newline at end of file
diff --git a/src/timelineDecoder/tests/JSONTimelineDecoderTests.cpp b/src/timelineDecoder/tests/JSONTimelineDecoderTests.cpp
new file mode 100644 (file)
index 0000000..71e76b1
--- /dev/null
@@ -0,0 +1,813 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <JSONTimelineDecoder.hpp>
+#include <TimelineCaptureCommandHandler.hpp>
+#include <TimelineDecoder.hpp>
+
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test_suite.hpp>
+
+#include <fstream>
+
+BOOST_AUTO_TEST_SUITE(JSONTimelineDecoderTests)
+
+using namespace armnn;
+using namespace timelinedecoder;
+
+void RunSimpleModelThroughDecoder(JSONTimelineDecoder& timelineDecoder)
+{
+    /*
+    * Building Simple model structure to test
+    */
+    ITimelineDecoder::Label name;
+    name.m_Guid = uint64_t(10420554295983197538U);
+    name.m_Name = "name";
+    timelineDecoder.CreateLabel(name);
+
+    ITimelineDecoder::Label type;
+    type.m_Guid = uint64_t(14196220359693045352U);
+    type.m_Name = "type";
+    timelineDecoder.CreateLabel(type);
+
+    ITimelineDecoder::Label index;
+    index.m_Guid = uint64_t(13922236767355949814U);
+    index.m_Name = "index";
+    timelineDecoder.CreateLabel(index);
+
+    ITimelineDecoder::Label backendId;
+    backendId.m_Guid = uint64_t(10874037804557439415U);
+    backendId.m_Name = "backendId";
+    timelineDecoder.CreateLabel(backendId);
+
+    ITimelineDecoder::Label layer;
+    layer.m_Guid = uint64_t(14761340794127440397U);
+    layer.m_Name = "layer";
+    timelineDecoder.CreateLabel(layer);
+
+    ITimelineDecoder::Label workload;
+    workload.m_Guid = uint64_t(15704252740552608110U);
+    workload.m_Name = "workload";
+    timelineDecoder.CreateLabel(workload);
+
+    ITimelineDecoder::Label network;
+    network.m_Guid = uint64_t(16862199137063532871U);
+    network.m_Name = "network";
+    timelineDecoder.CreateLabel(network);
+
+    ITimelineDecoder::Label connection;
+    connection.m_Guid = uint64_t(15733717748792475675U);
+    connection.m_Name = "connection";
+    timelineDecoder.CreateLabel(connection);
+
+    ITimelineDecoder::Label inference;
+    inference.m_Guid = uint64_t(15026600058430441282U);
+    inference.m_Name = "inference";
+    timelineDecoder.CreateLabel(inference);
+
+    ITimelineDecoder::Label workload_execution;
+    workload_execution.m_Guid = uint64_t(10172155312650606003U);
+    workload_execution.m_Name = "workload_execution";
+    timelineDecoder.CreateLabel(workload_execution);
+
+    ITimelineDecoder::EventClass eventClass1;
+    eventClass1.m_Guid = uint64_t(17170418158534996719U);
+    timelineDecoder.CreateEventClass(eventClass1);
+
+    ITimelineDecoder::EventClass eventClass2;
+    eventClass2.m_Guid = uint64_t(10812061579584851344U);
+    timelineDecoder.CreateEventClass(eventClass2);
+
+    ITimelineDecoder::Entity entity6;
+    entity6.m_Guid = uint64_t(6);
+    timelineDecoder.CreateEntity(entity6);
+
+    ITimelineDecoder::Relationship relationship7;
+    relationship7.m_Guid = uint64_t(7);
+    relationship7.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship7.m_HeadGuid = uint64_t(6);
+    relationship7.m_TailGuid = uint64_t(16862199137063532871U);
+    timelineDecoder.CreateRelationship(relationship7);
+
+    ITimelineDecoder::Relationship relationship8;
+    relationship8.m_Guid = uint64_t(8);
+    relationship8.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship8.m_HeadGuid = uint64_t(7);
+    relationship8.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship8);
+
+    // Adding normalization layer
+    ITimelineDecoder::Entity entity0;
+    entity0.m_Guid = uint64_t(0);
+    timelineDecoder.CreateEntity(entity0);
+
+    ITimelineDecoder::Label input;
+    input.m_Guid = uint64_t(18179123836411086572U);
+    input.m_Name = "input";
+    timelineDecoder.CreateLabel(input);
+
+    ITimelineDecoder::Relationship relationship9;
+    relationship9.m_Guid = uint64_t(9);
+    relationship9.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship9.m_HeadGuid = uint64_t(0);
+    relationship9.m_TailGuid = uint64_t(18179123836411086572U);
+    timelineDecoder.CreateRelationship(relationship9);
+
+    ITimelineDecoder::Relationship relationship10;
+    relationship10.m_Guid = uint64_t(10);
+    relationship10.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship10.m_HeadGuid = uint64_t(9);
+    relationship10.m_TailGuid = uint64_t(10420554295983197538U);
+    timelineDecoder.CreateRelationship(relationship10);
+
+    ITimelineDecoder::Relationship relationship11;
+    relationship11.m_Guid = uint64_t(11);
+    relationship11.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship11.m_HeadGuid = uint64_t(0);
+    relationship11.m_TailGuid = uint64_t(14761340794127440397U);
+    timelineDecoder.CreateRelationship(relationship11);
+
+    ITimelineDecoder::Relationship relationship12;
+    relationship12.m_Guid = uint64_t(12);
+    relationship12.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship12.m_HeadGuid = uint64_t(11);
+    relationship12.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship12);
+
+    ITimelineDecoder::Relationship relationship13;
+    relationship13.m_Guid = uint64_t(13);
+    relationship13.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship13.m_HeadGuid = uint64_t(6);
+    relationship13.m_TailGuid = uint64_t(0);
+    timelineDecoder.CreateRelationship(relationship13);
+
+
+    // Adding normalization layer
+    ITimelineDecoder::Entity entity1;
+    entity1.m_Guid = uint64_t(1);
+    timelineDecoder.CreateEntity(entity1);
+
+    ITimelineDecoder::Label normalization;
+    normalization.m_Guid = uint64_t(15955949569988957863U);
+    normalization.m_Name = "normalization";
+    timelineDecoder.CreateLabel(normalization);
+
+    ITimelineDecoder::Relationship relationship14;
+    relationship14.m_Guid = uint64_t(14);
+    relationship14.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship14.m_HeadGuid = uint64_t(1);
+    relationship14.m_TailGuid = uint64_t(15955949569988957863U);
+    timelineDecoder.CreateRelationship(relationship14);
+
+    ITimelineDecoder::Relationship relationship15;
+    relationship15.m_Guid = uint64_t(15);
+    relationship15.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship15.m_HeadGuid = uint64_t(14);
+    relationship15.m_TailGuid = uint64_t(10420554295983197538U);
+    timelineDecoder.CreateRelationship(relationship15);
+
+    ITimelineDecoder::Relationship relationship16;
+    relationship16.m_Guid = uint64_t(16);
+    relationship16.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship16.m_HeadGuid = uint64_t(1);
+    relationship16.m_TailGuid = uint64_t(14761340794127440397U);
+    timelineDecoder.CreateRelationship(relationship16);
+
+    ITimelineDecoder::Relationship relationship17;
+    relationship17.m_Guid = uint64_t(17);
+    relationship17.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship17.m_HeadGuid = uint64_t(16);
+    relationship17.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship17);
+
+    ITimelineDecoder::Relationship relationship18;
+    relationship18.m_Guid = uint64_t(18);
+    relationship18.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship18.m_HeadGuid = uint64_t(6);
+    relationship18.m_TailGuid = uint64_t(1);
+    timelineDecoder.CreateRelationship(relationship18);
+
+    ITimelineDecoder::Relationship relationship19;
+    relationship19.m_Guid = uint64_t(19);
+    relationship19.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship19.m_HeadGuid = uint64_t(0);
+    relationship19.m_TailGuid = uint64_t(1);
+    timelineDecoder.CreateRelationship(relationship19);
+
+    ITimelineDecoder::Relationship relationship20;
+    relationship20.m_Guid = uint64_t(20);
+    relationship20.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship20.m_HeadGuid = uint64_t(19);
+    relationship20.m_TailGuid = uint64_t(15733717748792475675U);
+    timelineDecoder.CreateRelationship(relationship20);
+
+    ITimelineDecoder::Relationship relationship21;
+    relationship21.m_Guid = uint64_t(21);
+    relationship21.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship21.m_HeadGuid = uint64_t(20);
+    relationship21.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship21);
+
+
+    ITimelineDecoder::Entity entity22;
+    entity22.m_Guid = uint64_t(22);
+    timelineDecoder.CreateEntity(entity22);
+
+    ITimelineDecoder::Relationship relationship23;
+    relationship23.m_Guid = uint64_t(23);
+    relationship23.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship23.m_HeadGuid = uint64_t(22);
+    relationship23.m_TailGuid = uint64_t(15704252740552608110U);
+    timelineDecoder.CreateRelationship(relationship23);
+
+    ITimelineDecoder::Relationship relationship24;
+    relationship24.m_Guid = uint64_t(24);
+    relationship24.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship24.m_HeadGuid = uint64_t(23);
+    relationship24.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship24);
+
+
+    ITimelineDecoder::Label CpuRef;
+    CpuRef.m_Guid = uint64_t(9690680943817437852U);
+    CpuRef.m_Name = "CpuRef";
+    timelineDecoder.CreateLabel(CpuRef);
+
+
+    ITimelineDecoder::Relationship relationship25;
+    relationship25.m_Guid = uint64_t(25);
+    relationship25.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship25.m_HeadGuid = uint64_t(22);
+    relationship25.m_TailGuid = uint64_t(9690680943817437852U);
+    timelineDecoder.CreateRelationship(relationship25);
+
+    ITimelineDecoder::Relationship relationship26;
+    relationship26.m_Guid = uint64_t(26);
+    relationship26.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship26.m_HeadGuid = uint64_t(25);
+    relationship26.m_TailGuid = uint64_t(10874037804557439415U);
+    timelineDecoder.CreateRelationship(relationship26);
+
+    ITimelineDecoder::Relationship relationship27;
+    relationship27.m_Guid = uint64_t(27);
+    relationship27.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink   ;
+    relationship27.m_HeadGuid = uint64_t(1);
+    relationship27.m_TailGuid = uint64_t(22);
+    timelineDecoder.CreateRelationship(relationship27);
+
+    // Adding output layer
+    ITimelineDecoder::Entity entity2;
+    entity2.m_Guid = uint64_t(2);
+    timelineDecoder.CreateEntity(entity2);
+
+    ITimelineDecoder::Label output;
+    output.m_Guid = uint64_t(18419179028513879730U);
+    output.m_Name = "output";
+    timelineDecoder.CreateLabel(output);
+
+    ITimelineDecoder::Relationship relationship28;
+    relationship28.m_Guid = uint64_t(28);
+    relationship28.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship28.m_HeadGuid = uint64_t(2);
+    relationship28.m_TailGuid = uint64_t(18419179028513879730U);
+    timelineDecoder.CreateRelationship(relationship28);
+
+    ITimelineDecoder::Relationship relationship29;
+    relationship29.m_Guid = uint64_t(29);
+    relationship29.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship29.m_HeadGuid = uint64_t(28);
+    relationship29.m_TailGuid = uint64_t(10420554295983197538U);
+    timelineDecoder.CreateRelationship(relationship29);
+
+    ITimelineDecoder::Relationship relationship30;
+    relationship30.m_Guid = uint64_t(30);
+    relationship30.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship30.m_HeadGuid = uint64_t(2);
+    relationship30.m_TailGuid = uint64_t(14761340794127440397U);
+    timelineDecoder.CreateRelationship(relationship30);
+
+    ITimelineDecoder::Relationship relationship31;
+    relationship31.m_Guid = uint64_t(31);
+    relationship31.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship31.m_HeadGuid = uint64_t(30);
+    relationship31.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship31);
+
+    ITimelineDecoder::Relationship relationship32;
+    relationship32.m_Guid = uint64_t(32);
+    relationship32.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship32.m_HeadGuid = uint64_t(6);
+    relationship32.m_TailGuid = uint64_t(2);
+    timelineDecoder.CreateRelationship(relationship32);
+
+    ITimelineDecoder::Relationship relationship33;
+    relationship33.m_Guid = uint64_t(33);
+    relationship33.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship33.m_HeadGuid = uint64_t(1);
+    relationship33.m_TailGuid = uint64_t(2);
+    timelineDecoder.CreateRelationship(relationship33);
+
+    ITimelineDecoder::Relationship relationship34;
+    relationship34.m_Guid = uint64_t(34);
+    relationship34.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship34.m_HeadGuid = uint64_t(33);
+    relationship34.m_TailGuid = uint64_t(15733717748792475675U);
+    timelineDecoder.CreateRelationship(relationship34);
+
+    ITimelineDecoder::Relationship relationship35;
+    relationship35.m_Guid = uint64_t(35);
+    relationship35.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship35.m_HeadGuid = uint64_t(34);
+    relationship35.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship35);
+
+
+    ITimelineDecoder::Entity entity36;
+    entity36.m_Guid = uint64_t(36);
+    timelineDecoder.CreateEntity(entity36);
+
+    ITimelineDecoder::Relationship relationship37;
+    relationship37.m_Guid = uint64_t(37);
+    relationship37.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship37.m_HeadGuid = uint64_t(36);
+    relationship37.m_TailGuid = uint64_t(15704252740552608110U);
+    timelineDecoder.CreateRelationship(relationship37);
+
+    ITimelineDecoder::Relationship relationship38;
+    relationship38.m_Guid = uint64_t(38);
+    relationship38.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship38.m_HeadGuid = uint64_t(37);
+    relationship38.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship38);
+
+    ITimelineDecoder::Relationship relationship39;
+    relationship39.m_Guid = uint64_t(39);
+    relationship39.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship39.m_HeadGuid = uint64_t(36);
+    relationship39.m_TailGuid = uint64_t(9690680943817437852U);
+    timelineDecoder.CreateRelationship(relationship39);
+
+    ITimelineDecoder::Relationship relationship40;
+    relationship40.m_Guid = uint64_t(40);
+    relationship40.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship40.m_HeadGuid = uint64_t(39);
+    relationship40.m_TailGuid = uint64_t(10874037804557439415U);
+    timelineDecoder.CreateRelationship(relationship40);
+
+    ITimelineDecoder::Relationship relationship41;
+    relationship41.m_Guid = uint64_t(41);
+    relationship41.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship41.m_HeadGuid = uint64_t(0);
+    relationship41.m_TailGuid = uint64_t(36);
+    timelineDecoder.CreateRelationship(relationship41);
+
+
+    ITimelineDecoder::Entity entity42;
+    entity42.m_Guid = uint64_t(42);
+    timelineDecoder.CreateEntity(entity42);
+
+    ITimelineDecoder::Relationship relationship43;
+    relationship43.m_Guid = uint64_t(43);
+    relationship43.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship43.m_HeadGuid = uint64_t(42);
+    relationship43.m_TailGuid = uint64_t(15704252740552608110U);
+    timelineDecoder.CreateRelationship(relationship43);
+
+    ITimelineDecoder::Relationship relationship44;
+    relationship44.m_Guid = uint64_t(44);
+    relationship44.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship44.m_HeadGuid = uint64_t(43);
+    relationship44.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship44);
+
+    ITimelineDecoder::Relationship relationship45;
+    relationship45.m_Guid = uint64_t(45);
+    relationship45.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship45.m_HeadGuid = uint64_t(42);
+    relationship45.m_TailGuid = uint64_t(9690680943817437852U);
+    timelineDecoder.CreateRelationship(relationship45);
+
+    ITimelineDecoder::Relationship relationship46;
+    relationship46.m_Guid = uint64_t(46);
+    relationship46.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship46.m_HeadGuid = uint64_t(45);
+    relationship46.m_TailGuid = uint64_t(10874037804557439415U);
+    timelineDecoder.CreateRelationship(relationship46);
+
+    ITimelineDecoder::Relationship relationship47;
+    relationship47.m_Guid = uint64_t(47);
+    relationship47.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship47.m_HeadGuid = uint64_t(2);
+    relationship47.m_TailGuid = uint64_t(42);
+    timelineDecoder.CreateRelationship(relationship47);
+
+    ITimelineDecoder::Entity entity48;
+    entity48.m_Guid = uint64_t(48);
+    timelineDecoder.CreateEntity(entity48);
+
+    ITimelineDecoder::Relationship relationship49;
+    relationship49.m_Guid = uint64_t(49);
+    relationship49.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship49.m_HeadGuid = uint64_t(48);
+    relationship49.m_TailGuid = uint64_t(15026600058430441282U);
+    timelineDecoder.CreateRelationship(relationship49);
+
+    ITimelineDecoder::Relationship relationship50;
+    relationship50.m_Guid = uint64_t(50);
+    relationship50.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship50.m_HeadGuid = uint64_t(49);
+    relationship50.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship50);
+
+    ITimelineDecoder::Relationship relationship51;
+    relationship51.m_Guid = uint64_t(51);
+    relationship51.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship51.m_HeadGuid = uint64_t(6);
+    relationship51.m_TailGuid = uint64_t(48);
+    timelineDecoder.CreateRelationship(relationship51);
+
+    ITimelineDecoder::Relationship relationship53;
+    relationship53.m_Guid = uint64_t(53);
+    relationship53.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship53.m_HeadGuid = uint64_t(48);
+    relationship53.m_TailGuid = uint64_t(52);
+    timelineDecoder.CreateRelationship(relationship53);
+
+    ITimelineDecoder::Relationship relationship54;
+    relationship54.m_Guid = uint64_t(54);
+    relationship54.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship54.m_HeadGuid = uint64_t(52);
+    relationship54.m_TailGuid = uint64_t(17170418158534996719U);
+    timelineDecoder.CreateRelationship(relationship54);
+
+
+    ITimelineDecoder::Entity entity55;
+    entity55.m_Guid = uint64_t(55);
+    timelineDecoder.CreateEntity(entity55);
+
+    ITimelineDecoder::Relationship relationship56;
+    relationship56.m_Guid = uint64_t(56);
+    relationship56.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship56.m_HeadGuid = uint64_t(55);
+    relationship56.m_TailGuid = uint64_t(10172155312650606003U);
+    timelineDecoder.CreateRelationship(relationship56);
+
+    ITimelineDecoder::Relationship relationship57;
+    relationship57.m_Guid = uint64_t(57);
+    relationship57.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship57.m_HeadGuid = uint64_t(56);
+    relationship57.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship57);
+
+    ITimelineDecoder::Relationship relationship58;
+    relationship58.m_Guid = uint64_t(58);
+    relationship58.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship58.m_HeadGuid = uint64_t(48);
+    relationship58.m_TailGuid = uint64_t(55);
+    timelineDecoder.CreateRelationship(relationship58);
+
+    ITimelineDecoder::Relationship relationship59;
+    relationship59.m_Guid = uint64_t(59);
+    relationship59.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship59.m_HeadGuid = uint64_t(36);
+    relationship59.m_TailGuid = uint64_t(55);
+    timelineDecoder.CreateRelationship(relationship59);
+
+    ITimelineDecoder::Event event60;
+    event60.m_Guid = uint64_t(60);
+    event60.m_TimeStamp = uint64_t(96557081111036);
+    event60.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event60);
+
+    ITimelineDecoder::Relationship relationship61;
+    relationship61.m_Guid = uint64_t(61);
+    relationship61.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship61.m_HeadGuid = uint64_t(55);
+    relationship61.m_TailGuid = uint64_t(60);
+    timelineDecoder.CreateRelationship(relationship61);
+
+    ITimelineDecoder::Relationship relationship62;
+    relationship62.m_Guid = uint64_t(62);
+    relationship62.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship62.m_HeadGuid = uint64_t(60);
+    relationship62.m_TailGuid = uint64_t(17170418158534996719U);
+    timelineDecoder.CreateRelationship(relationship62);
+
+    ITimelineDecoder::Event event63;
+    event63.m_Guid = uint64_t(63);
+    event63.m_TimeStamp = uint64_t(96557081149730);
+    event63.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event63);
+
+    ITimelineDecoder::Relationship relationship64;
+    relationship64.m_Guid = uint64_t(61);
+    relationship64.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship64.m_HeadGuid = uint64_t(55);
+    relationship64.m_TailGuid = uint64_t(63);
+    timelineDecoder.CreateRelationship(relationship64);
+
+    ITimelineDecoder::Relationship relationship65;
+    relationship65.m_Guid = uint64_t(62);
+    relationship65.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship65.m_HeadGuid = uint64_t(63);
+    relationship65.m_TailGuid = uint64_t(10812061579584851344U);
+    timelineDecoder.CreateRelationship(relationship65);
+
+
+    ITimelineDecoder::Entity entity66;
+    entity66.m_Guid = uint64_t(66);
+    timelineDecoder.CreateEntity(entity66);
+
+    ITimelineDecoder::Relationship relationship67;
+    relationship67.m_Guid = uint64_t(67);
+    relationship67.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship67.m_HeadGuid = uint64_t(66);
+    relationship67.m_TailGuid = uint64_t(10172155312650606003U);
+    timelineDecoder.CreateRelationship(relationship67);
+
+    ITimelineDecoder::Relationship relationship68;
+    relationship68.m_Guid = uint64_t(68);
+    relationship68.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship68.m_HeadGuid = uint64_t(67);
+    relationship68.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship68);
+
+    ITimelineDecoder::Relationship relationship69;
+    relationship69.m_Guid = uint64_t(69);
+    relationship69.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship69.m_HeadGuid = uint64_t(48);
+    relationship69.m_TailGuid = uint64_t(66);
+    timelineDecoder.CreateRelationship(relationship69);
+
+    ITimelineDecoder::Relationship relationship70;
+    relationship70.m_Guid = uint64_t(70);
+    relationship70.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship70.m_HeadGuid = uint64_t(22);
+    relationship70.m_TailGuid = uint64_t(66);
+    timelineDecoder.CreateRelationship(relationship70);
+
+
+    ITimelineDecoder::Event event71;
+    event71.m_Guid = uint64_t(71);
+    event71.m_TimeStamp = uint64_t(96557081156464);
+    event71.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event71);
+
+    ITimelineDecoder::Relationship relationship72;
+    relationship72.m_Guid = uint64_t(72);
+    relationship72.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship72.m_HeadGuid = uint64_t(66);
+    relationship72.m_TailGuid = uint64_t(71);
+    timelineDecoder.CreateRelationship(relationship72);
+
+    ITimelineDecoder::Relationship relationship73;
+    relationship73.m_Guid = uint64_t(73);
+    relationship73.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship73.m_HeadGuid = uint64_t(71);
+    relationship73.m_TailGuid = uint64_t(17170418158534996719U);
+    timelineDecoder.CreateRelationship(relationship73);
+
+    ITimelineDecoder::Event event74;
+    event74.m_Guid = uint64_t(74);
+    event74.m_TimeStamp = uint64_t(96557081220825);
+    event74.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event74);
+
+    ITimelineDecoder::Relationship relationship75;
+    relationship75.m_Guid = uint64_t(75);
+    relationship75.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship75.m_HeadGuid = uint64_t(66);
+    relationship75.m_TailGuid = uint64_t(74);
+    timelineDecoder.CreateRelationship(relationship75);
+
+    ITimelineDecoder::Relationship relationship76;
+    relationship76.m_Guid = uint64_t(76);
+    relationship76.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship76.m_HeadGuid = uint64_t(74);
+    relationship76.m_TailGuid = uint64_t(10812061579584851344U);
+    timelineDecoder.CreateRelationship(relationship76);
+
+    ITimelineDecoder::Entity entity77;
+    entity77.m_Guid = uint64_t(77);
+    timelineDecoder.CreateEntity(entity77);
+
+    ITimelineDecoder::Relationship relationship78;
+    relationship78.m_Guid = uint64_t(78);
+    relationship78.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship78.m_HeadGuid = uint64_t(77);
+    relationship78.m_TailGuid = uint64_t(10172155312650606003U);
+    timelineDecoder.CreateRelationship(relationship78);
+
+    ITimelineDecoder::Relationship relationship79;
+    relationship79.m_Guid = uint64_t(79);
+    relationship79.m_RelationshipType = ITimelineDecoder::RelationshipType::LabelLink;
+    relationship79.m_HeadGuid = uint64_t(78);
+    relationship79.m_TailGuid = uint64_t(14196220359693045352U);
+    timelineDecoder.CreateRelationship(relationship79);
+
+    ITimelineDecoder::Relationship relationship80;
+    relationship80.m_Guid = uint64_t(80);
+    relationship80.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship80.m_HeadGuid = uint64_t(48);
+    relationship80.m_TailGuid = uint64_t(77);
+    timelineDecoder.CreateRelationship(relationship80);
+
+    ITimelineDecoder::Relationship relationship81;
+    relationship81.m_Guid = uint64_t(81);
+    relationship81.m_RelationshipType = ITimelineDecoder::RelationshipType::RetentionLink;
+    relationship81.m_HeadGuid = uint64_t(42);
+    relationship81.m_TailGuid = uint64_t(77);
+    timelineDecoder.CreateRelationship(relationship81);
+
+    ITimelineDecoder::Event event82;
+    event82.m_Guid = uint64_t(82);
+    event82.m_TimeStamp = uint64_t(96557081227643);
+    event82.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event82);
+
+    ITimelineDecoder::Relationship relationship83;
+    relationship83.m_Guid = uint64_t(83);
+    relationship83.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship83.m_HeadGuid = uint64_t(77);
+    relationship83.m_TailGuid = uint64_t(82);
+    timelineDecoder.CreateRelationship(relationship83);
+
+    ITimelineDecoder::Relationship relationship84;
+    relationship84.m_Guid = uint64_t(84);
+    relationship84.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship84.m_HeadGuid = uint64_t(82);
+    relationship84.m_TailGuid = uint64_t(17170418158534996719U);
+    timelineDecoder.CreateRelationship(relationship84);
+
+    ITimelineDecoder::Event event85;
+    event85.m_Guid = uint64_t(85);
+    event85.m_TimeStamp = uint64_t(96557081240332);
+    event85.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event85);
+
+    ITimelineDecoder::Relationship relationship86;
+    relationship86.m_Guid = uint64_t(86);
+    relationship86.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship86.m_HeadGuid = uint64_t(77);
+    relationship86.m_TailGuid = uint64_t(85);
+    timelineDecoder.CreateRelationship(relationship86);
+
+    ITimelineDecoder::Relationship relationship87;
+    relationship87.m_Guid = uint64_t(87);
+    relationship87.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship87.m_HeadGuid = uint64_t(85);
+    relationship87.m_TailGuid = uint64_t(10812061579584851344U);
+    timelineDecoder.CreateRelationship(relationship87);
+
+    ITimelineDecoder::Event event88;
+    event88.m_Guid = uint64_t(88);
+    event88.m_TimeStamp = uint64_t(96557081243146);
+    event88.m_ThreadId = uint64_t(140522431862592);
+    timelineDecoder.CreateEvent(event88);
+
+    ITimelineDecoder::Relationship relationship89;
+    relationship89.m_Guid = uint64_t(89);
+    relationship89.m_RelationshipType = ITimelineDecoder::RelationshipType::ExecutionLink;
+    relationship89.m_HeadGuid = uint64_t(48);
+    relationship89.m_TailGuid = uint64_t(88);
+    timelineDecoder.CreateRelationship(relationship89);
+
+    ITimelineDecoder::Relationship relationship90;
+    relationship90.m_Guid = uint64_t(90);
+    relationship90.m_RelationshipType = ITimelineDecoder::RelationshipType::DataLink;
+    relationship90.m_HeadGuid = uint64_t(88);
+    relationship90.m_TailGuid = uint64_t(10812061579584851344U);
+    timelineDecoder.CreateRelationship(relationship90);
+}
+
+BOOST_AUTO_TEST_CASE(JSONTimelineDecoderTestStructure)
+{
+    JSONTimelineDecoder timelineDecoder;
+    RunSimpleModelThroughDecoder(timelineDecoder);
+
+    JSONTimelineDecoder::Model model = timelineDecoder.GetModel();
+    BOOST_CHECK(model.jsonEntities.size() == 20);
+    JSONTimelineDecoder::JSONEntity rootEntity = model.jsonEntities.at(6);
+    BOOST_CHECK(rootEntity.childEntities.size() == 4);
+
+    // Testing input layer model
+    JSONTimelineDecoder::JSONEntity entity0 = model.jsonEntities.at(rootEntity.childEntities[0]);
+    BOOST_CHECK(entity0.GetName() == "input");
+    BOOST_CHECK(entity0.GetType() == "layer");
+
+    BOOST_CHECK(entity0.childEntities.size() == 1);
+    JSONTimelineDecoder::JSONEntity input_workload_entity = model.jsonEntities.at(entity0.childEntities[0]);
+    BOOST_CHECK(input_workload_entity.childEntities.size() == 1);
+    BOOST_CHECK(input_workload_entity.GetType() == "workload");
+    BOOST_CHECK(input_workload_entity.extendedData.at("backendId") == "CpuRef");
+
+    JSONTimelineDecoder::JSONEntity input_workload_execution_entity = model.jsonEntities
+            .at(input_workload_entity.childEntities[0]);
+    BOOST_CHECK(input_workload_execution_entity.childEntities.size() == 2);
+    BOOST_CHECK(input_workload_execution_entity.GetType() == "workload_execution");
+
+    JSONTimelineDecoder::JSONEntity input_workload_execution_event0 = model.jsonEntities
+            .at(input_workload_execution_entity.childEntities[0]);
+    BOOST_CHECK(input_workload_execution_event0.GetType() == "Event");
+    BOOST_CHECK(input_workload_execution_event0.childEntities.size() == 0);
+    BOOST_CHECK(model.events.at(input_workload_execution_event0.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(input_workload_execution_event0.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    JSONTimelineDecoder::JSONEntity input_workload_execution_event1 = model.jsonEntities
+            .at(input_workload_execution_entity.childEntities[1]);
+    BOOST_CHECK(input_workload_execution_event0.GetType() == "Event");
+    BOOST_CHECK(input_workload_execution_event1.childEntities.size() == 0);
+    BOOST_CHECK(model.events.at(input_workload_execution_event1.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(input_workload_execution_event1.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    // Testing normalization layer model
+    JSONTimelineDecoder::JSONEntity entity1 = model.jsonEntities.at(rootEntity.childEntities[1]);
+    BOOST_CHECK(entity1.GetName() == "normalization");
+    BOOST_CHECK(entity1.GetType() == "layer");
+
+    JSONTimelineDecoder::JSONEntity normalization_workload_entity = model.jsonEntities
+            .at(entity1.childEntities[0]);
+    BOOST_CHECK(normalization_workload_entity.GetType() == "workload");
+    BOOST_CHECK(normalization_workload_entity.extendedData.at("backendId") == "CpuRef");
+
+    JSONTimelineDecoder::JSONEntity normalization_workload_execution_entity = model.jsonEntities
+            .at(normalization_workload_entity.childEntities[0]);
+    BOOST_CHECK(normalization_workload_execution_entity.GetType() == "workload_execution");
+
+    JSONTimelineDecoder::JSONEntity normalization_workload_execution_event0 = model.jsonEntities
+            .at(normalization_workload_execution_entity.childEntities[0]);
+    BOOST_CHECK(normalization_workload_execution_event0.GetType() == "Event");
+    BOOST_CHECK(model.events.at(normalization_workload_execution_event0.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(normalization_workload_execution_event0.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    JSONTimelineDecoder::JSONEntity normalization_workload_execution_event1 = model.jsonEntities
+            .at(normalization_workload_execution_entity.childEntities[1]);
+    BOOST_CHECK(normalization_workload_execution_event1.GetType() == "Event");
+    BOOST_CHECK(model.events.at(normalization_workload_execution_event1.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(normalization_workload_execution_event1.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    // Testing output layer model
+    JSONTimelineDecoder::JSONEntity entity2 = model.jsonEntities.at(rootEntity.childEntities[2]);
+    BOOST_CHECK(entity2.GetName() == "output");
+    BOOST_CHECK(entity2.GetType() == "layer");
+
+    JSONTimelineDecoder::JSONEntity output_workload_entity = model.jsonEntities.at(entity2.childEntities[0]);
+    BOOST_CHECK(output_workload_entity.GetType() == "workload");
+    BOOST_CHECK(output_workload_entity.extendedData.at("backendId") == "CpuRef");
+
+    JSONTimelineDecoder::JSONEntity output_workload_execution_entity = model.jsonEntities
+            .at(output_workload_entity.childEntities[0]);
+    BOOST_CHECK(output_workload_execution_entity.GetType() == "workload_execution");
+
+    JSONTimelineDecoder::JSONEntity output_workload_execution_event0 = model.jsonEntities
+            .at(output_workload_execution_entity.childEntities[0]);
+    BOOST_CHECK(output_workload_execution_event0.GetType() == "Event");
+    BOOST_CHECK(model.events.at(output_workload_execution_event0.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(output_workload_execution_event0.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    JSONTimelineDecoder::JSONEntity output_workload_execution_event1 = model.jsonEntities
+            .at(output_workload_execution_entity.childEntities[1]);
+    BOOST_CHECK(output_workload_execution_event1.GetType() == "Event");
+    BOOST_CHECK(model.events.at(output_workload_execution_event1.GetGuid()).m_ThreadId > uint64_t(0));
+    BOOST_CHECK(model.events.at(output_workload_execution_event1.GetGuid()).m_TimeStamp > uint64_t(0));
+
+    JSONTimelineDecoder::JSONEntity entity48 =  model.jsonEntities.at(rootEntity.childEntities[3]);
+    BOOST_CHECK(entity48.GetName() == "");
+    BOOST_CHECK(entity48.GetType() == "inference");
+}
+
+BOOST_AUTO_TEST_CASE(JSONTimelineDecoderTestJSON)
+{
+    JSONTimelineDecoder timelineDecoder;
+    RunSimpleModelThroughDecoder(timelineDecoder);
+
+    JSONTimelineDecoder::Model model = timelineDecoder.GetModel();
+    JSONTimelineDecoder::JSONEntity rootEntity = model.jsonEntities.at(6);
+
+    std::string jsonString = timelineDecoder.GetJSONString(rootEntity);
+    BOOST_CHECK(jsonString != "");
+    BOOST_CHECK(jsonString.find("input_0: {")!=std::string::npos);
+    BOOST_CHECK(jsonString.find("type: Measurement,\n"
+                                   "\t\t\tbackendId :CpuRef,")!=std::string::npos);
+    BOOST_CHECK(jsonString.find("normalization_2: {")!=std::string::npos);
+    BOOST_CHECK(jsonString.find("output_4: {")!=std::string::npos);
+
+    timelineDecoder.PrintJSON(rootEntity);
+
+    std::ifstream inFile;
+    inFile.open("/tmp/output.json"); //open the input file
+
+    std::stringstream strStream;
+    strStream << inFile.rdbuf(); //read the file
+    std::string outfileJson = strStream.str();
+
+    BOOST_CHECK(outfileJson != "");
+    BOOST_CHECK(outfileJson.find("input_0: {")!=std::string::npos);
+    BOOST_CHECK(outfileJson.find("type: Measurement,\n"
+                                "\t\t\tbackendId :CpuRef,")!=std::string::npos);
+    BOOST_CHECK(outfileJson.find("normalization_2: {")!=std::string::npos);
+    BOOST_CHECK(outfileJson.find("output_4: {")!=std::string::npos);
+}
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file