Commit c30395db authored by Philipp Schäfer's avatar Philipp Schäfer
Browse files

Profiler - JSON: change to nlohmann/json lib - TESTING Required

parent 2ce64514
......@@ -24,7 +24,9 @@
// misc includes
#include <VistaBase/VistaTimeUtils.h>
#include <libjson.h>
#include <nlohmann/json.hpp>
using namespace nlohmann;
namespace ITAProfiler
{
......@@ -217,21 +219,21 @@ namespace ITAProfiler
///
std::stringstream ProfilerToJSON ( )
{
JSONNode jnRoot;
jnRoot.set_name ( "Profiler" );
jnRoot.push_back ( JSONNode ( "Time Unit", "us - 1e-6" ) );
jnRoot.push_back ( JSONNode ( "CPU Frequency", ITAClock::getDefaultClock ( )->getFrequency ( ) ) );
json jnRoot;
//TODO: Name should not be needed here. Test this and remove lines afterwards.
//jnRoot.set_name ( "Profiler" );
JSONNode jnSection;
jnSection.set_name ( "Profile Sections" );
jnRoot["Time Unit"] = "us - 1e-6";
jnRoot["CPU Frequency"] = ITAClock::getDefaultClock ( )->getFrequency ( );
JSONNode jnEventCount;
jnEventCount.set_name ( "Profile EventCounts" );
json jnSection;
json jnEventCount;
json jnValue;
JSONNode jnValue;
jnValue.set_name ( "Profile Values" );
//TODO: Check whether this was change properly (see further below). Remove afterwards.
//jnSection.set_name ( "Profile Sections" );
//jnEventCount.set_name ( "Profile EventCounts" );
//jnValue.set_name ( "Profile Values" );
// Disable profiling while we write to file.
m_bEnabled = false;
......@@ -253,42 +255,51 @@ namespace ITAProfiler
for ( const auto& sectionPair : threadStorage.second.m_mSections )
{
swSection.start ( );
jnSection.push_back ( ProfileSectionToJSON ( sectionPair, m_mThreadNames ) );
//TODO: I think the node will become a json array if using push_back on an empty node.
//It would probably be better to create the name of the node in this function and use jnSection[name] = jsonNode (without a root name)
if ( jnSection = NULL )
jnSection = ProfileSectionToJSON ( sectionPair, m_mThreadNames );
else
jnSection.push_back ( ProfileSectionToJSON ( sectionPair, m_mThreadNames ) );
swSection.stop ( );
}
for ( const auto& eventCountPair : threadStorage.second.m_mEventCount )
{
swEvent.start ( );
jnEventCount.push_back ( ProfileEventCountToJSON ( eventCountPair, m_mThreadNames ) );
if ( jnEventCount.empty() )
jnEventCount = ProfileEventCountToJSON ( eventCountPair, m_mThreadNames );
else
jnEventCount.push_back ( ProfileEventCountToJSON ( eventCountPair, m_mThreadNames ) );
swEvent.stop ( );
}
for ( const auto& valuePair : threadStorage.second.m_mValues )
{
swValue.start ( );
jnValue.push_back ( ProfileValuesToJSON ( valuePair, m_mThreadNames ) );
if ( jnValue.empty ( ) )
jnValue = ProfileValuesToJSON ( valuePair, m_mThreadNames );
else
jnValue.push_back ( ProfileValuesToJSON ( valuePair, m_mThreadNames ) );
swValue.stop ( );
}
swThread.stop ( );
}
jnRoot.push_back ( JSONNode ( "Section SW", swSection.ToString ( ) ) );
jnRoot.push_back ( JSONNode ( "Event SW", swEvent.ToString ( ) ) );
jnRoot.push_back ( JSONNode ( "Value SW", swValue.ToString ( ) ) );
jnRoot.push_back ( JSONNode ( "Thread SW", swThread.ToString ( ) + ", sum=" + std::to_string ( swThread.sum ( ) ) ) );
jnRoot.push_back ( jnSection );
jnRoot.push_back ( jnEventCount );
jnRoot["Section SW"] = swSection.ToString ( );
jnRoot["Event SW"] = swEvent.ToString ( );
jnRoot["Value SW"] = swValue.ToString ( );
jnRoot["Thread SW"] = swThread.ToString ( ) + ", sum=" + std::to_string ( swThread.sum ( ) );
jnRoot.push_back ( jnValue );
jnRoot["Profile Sections"] = jnSection;
jnRoot["Profile EventCounts"] = jnEventCount;
jnRoot["Profile Values"] = jnValue;
// Reenable profiling
m_bEnabled = true;
std::stringstream ss;
ss << jnRoot.write ( );
ss << jnRoot;
return ss;
}
......@@ -298,7 +309,7 @@ namespace ITAProfiler
/// \param mThreadNames map, containing the names of the threads.
/// \return a JSON Node with the data of the given eventCount pair.
///
JSONNode ProfileEventCountToJSON ( const std::pair<ProfilerKey, ProfileEventCount>& eventCountPair,
json ProfileEventCountToJSON ( const std::pair<ProfilerKey, ProfileEventCount>& eventCountPair,
const std::unordered_map<std::thread::id, std::string>& mThreadNames )
{
std::string sThreadName;
......@@ -308,22 +319,27 @@ namespace ITAProfiler
if ( threadNameIterator != mThreadNames.end ( ) )
sThreadName = threadNameIterator->second;
JSONNode jnRoot;
json jnRootWithName;
std::string sRootName;
//TODO: The code section is almost the same in this and the two functions below: Create subfunction for reusability?
if ( !sThreadName.empty ( ) )
jnRoot.set_name ( "[" + eventCountPair.first.sFunction + "][" + eventCountPair.first.sName + "][" + sThreadName + "]" );
sRootName = "[" + eventCountPair.first.sFunction + "][" + eventCountPair.first.sName + "][" + sThreadName + "]";
else
jnRoot.set_name ( "[" + eventCountPair.first.sFunction + "][" + eventCountPair.first.sName + "][" +
std::to_string ( std::hash<std::thread::id>()(eventCountPair.first.iThreadId) ) + "]" );
sRootName = "[" + eventCountPair.first.sFunction + "][" + eventCountPair.first.sName + "][" +
std::to_string ( std::hash<std::thread::id> ( ) ( eventCountPair.first.iThreadId ) ) + "]";
jnRoot.push_back ( JSONNode ( "Name", eventCountPair.first.sName ) );
jnRoot.push_back ( JSONNode ( "File Name", eventCountPair.first.sFile ) );
jnRoot.push_back ( JSONNode ( "Function Name", eventCountPair.first.sFunction ) );
jnRoot.push_back ( JSONNode ( "Thread Id", std::hash<std::thread::id>()(eventCountPair.first.iThreadId) ) );
json jnRoot;
jnRoot["Name"] = eventCountPair.first.sName;
jnRoot["File Name"] = eventCountPair.first.sFile;
jnRoot["Function Name"] = eventCountPair.first.sFunction;
jnRoot["Thread Id"] = std::hash<std::thread::id> ( ) ( eventCountPair.first.iThreadId );
if ( !sThreadName.empty ( ) )
jnRoot.push_back ( JSONNode ( "Thread Name", sThreadName ) );
jnRoot["Thread Name"] = sThreadName;
jnRoot.push_back ( JSONNode ( "Count", eventCountPair.second.vTimeStamps.size ( ) ) );
jnRoot["Count"] = eventCountPair.second.vTimeStamps.size ( );
//TODO: End of repeating section (see TODO above)
std::vector<double> vdTimeStamps ( eventCountPair.second.vTimeStamps.size ( ) );
......@@ -347,9 +363,10 @@ namespace ITAProfiler
const int precision = 1 + std::ceil ( std::log10 ( ITAClock::getDefaultClock ( )->getFrequency ( ) ) );
jnRoot.push_back ( JSONNode ( "Time Stamps", ConvertToString ( vdTimeStamps, precision, "," ) ) );
jnRoot["Time Stamps"] = ConvertToString ( vdTimeStamps, precision, "," );
return jnRoot;
jnRootWithName[sRootName] = jnRoot;
return jnRootWithName;
}
///
......@@ -360,7 +377,7 @@ namespace ITAProfiler
/// \param mThreadNames map, containing the names of the threads.
/// \return a JSON Node with the data of the given section pair.
///
JSONNode ProfileSectionToJSON ( const std::pair<ProfilerKey, ProfileSection>& sectionPair, const std::unordered_map<std::thread::id, std::string>& mThreadNames )
json ProfileSectionToJSON ( const std::pair<ProfilerKey, ProfileSection>& sectionPair, const std::unordered_map<std::thread::id, std::string>& mThreadNames )
{
std::string sThreadName;
......@@ -369,22 +386,24 @@ namespace ITAProfiler
if ( threadNameIterator != mThreadNames.end ( ) )
sThreadName = threadNameIterator->second;
JSONNode jnRoot;
json jnRootWithName;
std::string sRootName;
if ( !sThreadName.empty ( ) )
jnRoot.set_name ( "[" + sectionPair.first.sFunction + "][" + sectionPair.first.sName + "][" + sThreadName + "]" );
sRootName = "[" + sectionPair.first.sFunction + "][" + sectionPair.first.sName + "][" + sThreadName + "]";
else
jnRoot.set_name ( "[" + sectionPair.first.sFunction + "][" + sectionPair.first.sName + "][" + std::to_string ( std::hash<std::thread::id>()(sectionPair.first.iThreadId) ) +
"]" );
sRootName = "[" + sectionPair.first.sFunction + "][" + sectionPair.first.sName + "][" +
std::to_string ( std::hash<std::thread::id> ( ) ( sectionPair.first.iThreadId ) ) + "]";
jnRoot.push_back ( JSONNode ( "Name", sectionPair.first.sName ) );
jnRoot.push_back ( JSONNode ( "File Name", sectionPair.first.sFile ) );
jnRoot.push_back ( JSONNode ( "Function Name", sectionPair.first.sFunction ) );
jnRoot.push_back ( JSONNode ( "Thread Id", std::hash<std::thread::id>()(sectionPair.first.iThreadId ) ) );
json jnRoot;
jnRoot["Name"] = sectionPair.first.sName;
jnRoot["File Name"] = sectionPair.first.sFile;
jnRoot["Function Name"] = sectionPair.first.sFunction;
jnRoot["Thread Id"] = std::hash<std::thread::id> ( ) ( sectionPair.first.iThreadId );
if ( !sThreadName.empty ( ) )
jnRoot.push_back ( JSONNode ( "Thread Name", sThreadName ) );
jnRoot["Thread Name"] = sThreadName;
jnRoot.push_back ( JSONNode ( "Count", sectionPair.second.vpStartEndTimes.size ( ) ) );
jnRoot["Count"] = sectionPair.second.vpStartEndTimes.size ( );
std::vector<double> vdStartTime ( sectionPair.second.vpStartEndTimes.size ( ) );
std::vector<double> vdEndTime ( sectionPair.second.vpStartEndTimes.size ( ) );
......@@ -426,10 +445,11 @@ namespace ITAProfiler
const int precision = 1 + std::ceil ( std::log10 ( ITAClock::getDefaultClock ( )->getFrequency ( ) ) );
jnRoot.push_back ( JSONNode ( "Start Times", ConvertToString ( vdStartTime, precision, "," ) ) );
jnRoot.push_back ( JSONNode ( "End Times", ConvertToString ( vdEndTime, precision, "," ) ) );
jnRoot["Start Times"] = ConvertToString ( vdStartTime, precision, "," );
jnRoot["End Times"] = ConvertToString ( vdEndTime, precision, "," );
return jnRoot;
jnRootWithName[sRootName] = jnRoot;
return jnRootWithName;
}
///
......@@ -438,7 +458,7 @@ namespace ITAProfiler
/// \param mThreadNames map, containing the names of the threads.
/// \return a JSON Node with the data of the given ProfileValue pair.
///
JSONNode ProfileValuesToJSON ( const std::pair<ProfilerKey, ProfileValue>& valuePair, const std::unordered_map<std::thread::id, std::string>& mThreadNames )
json ProfileValuesToJSON ( const std::pair<ProfilerKey, ProfileValue>& valuePair, const std::unordered_map<std::thread::id, std::string>& mThreadNames )
{
std::string sThreadName;
......@@ -447,24 +467,28 @@ namespace ITAProfiler
if ( threadNameIterator != mThreadNames.end ( ) )
sThreadName = threadNameIterator->second;
JSONNode jnRoot;
json jnRootWithName;
std::string sRootName;
if ( !sThreadName.empty ( ) )
jnRoot.set_name ( "[" + valuePair.first.sFunction + "][" + valuePair.first.sName + "][" + sThreadName + "]" );
sRootName = ( "[" + valuePair.first.sFunction + "][" + valuePair.first.sName + "][" + sThreadName + "]" );
else
jnRoot.set_name ( "[" + valuePair.first.sFunction + "][" + valuePair.first.sName + "][" +
std::to_string ( std::hash<std::thread::id> ( ) ( valuePair.first.iThreadId ) ) + "]" );
sRootName = "[" + valuePair.first.sFunction + "][" + valuePair.first.sName + "][" +
std::to_string ( std::hash<std::thread::id> ( ) ( valuePair.first.iThreadId ) ) + "]";
jnRoot.push_back ( JSONNode ( "Name", valuePair.first.sName ) );
jnRoot.push_back ( JSONNode ( "File Name", valuePair.first.sFile ) );
jnRoot.push_back ( JSONNode ( "Function Name", valuePair.first.sFunction ) );
jnRoot.push_back ( JSONNode ( "Thread Id", std::hash<std::thread::id>()(valuePair.first.iThreadId ) ) );
json jnRoot;
jnRoot["Name"] = "Name", valuePair.first.sName;
jnRoot["File Name"] = valuePair.first.sFile;
jnRoot["Function Name"] = valuePair.first.sFunction;
jnRoot["Thread Id"] = std::hash<std::thread::id> ( ) ( valuePair.first.iThreadId );
if ( !sThreadName.empty ( ) )
jnRoot.push_back ( JSONNode ( "Thread Name", sThreadName ) );
jnRoot["Thread Name"] = sThreadName;
jnRoot.push_back ( JSONNode ( "Count", valuePair.second.Size ( ) ) );
jnRoot["Count"] = valuePair.second.Size ( );
std::tuple<JSONNode, JSONNode> valueNodes;
//TODO: Check whether change from Tuple to Node with two subnodes worked
//std::tuple<json, json> valueNodes;
json valueNodes;
// store the tim stamps
switch ( valuePair.second.GetDataType ( ) )
......@@ -494,10 +518,13 @@ namespace ITAProfiler
ITA_EXCEPT_INVALID_PARAMETER ( "Unkown data type" );
}
jnRoot.push_back ( std::get<0> ( valueNodes ) );
jnRoot.push_back ( std::get<1> ( valueNodes ) );
// TODO: Check whether change from Tuple to Node with two subnodes worked
//jnRoot.push_back ( std::get<0> ( valueNodes ) );
//jnRoot.push_back ( std::get<1> ( valueNodes ) );
jnRoot.push_back ( valueNodes );
return jnRoot;
jnRootWithName[sRootName] = jnRoot;
return jnRootWithName;
}
///
......@@ -507,7 +534,7 @@ namespace ITAProfiler
/// \return returns a tuple with the JSONNode for the time stamp and data.
///
template<class T>
std::tuple<JSONNode, JSONNode> ValueDataToJSON ( const ProfileValue& oProfileValue )
json ValueDataToJSON ( const ProfileValue& oProfileValue )
{
std::vector<std::pair<T, double>> dataVector = oProfileValue.GetData<T> ( m_dStartTime );
......@@ -536,10 +563,14 @@ namespace ITAProfiler
const int precision = 1 + std::ceil ( std::log10 ( ITAClock::getDefaultClock ( )->getFrequency ( ) ) );
JSONNode jnTimeStampArray ( "Time Stamps", ConvertToString ( vdTimeStamps, precision, "," ) );
JSONNode jnDataArray ( "Data", ConvertToString ( vTData, 8, "," ) );
return std::make_pair ( jnTimeStampArray, jnDataArray );
//TODO: Check whether this still does the correct thing!
json jnRoot;
jnRoot["Time Stamps"] = ConvertToString ( vdTimeStamps, precision, "," );
jnRoot["Data"] = ConvertToString ( vTData, 8, "," );
//json jnTimeStampArray ( "Time Stamps", ConvertToString ( vdTimeStamps, precision, "," ) );
//json jnDataArray ( "Data", ConvertToString ( vTData, 8, "," ) );
//return std::make_pair ( jnTimeStampArray, jnDataArray );
return jnRoot;
}
private:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment