Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Institute of Technical Acoustics (ITA)
ITABase
Commits
c30395db
Commit
c30395db
authored
Aug 25, 2021
by
Philipp Schäfer
Browse files
Profiler - JSON: change to nlohmann/json lib - TESTING Required
parent
2ce64514
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/ITAProfiler/profiler.cpp
View file @
c30395db
...
...
@@ -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
;
jn
Section
.
set_name
(
"Profile Sections"
);
jnRoot
[
"Time Unit"
]
=
"us - 1e-6"
;
jn
Root
[
"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
(
)
)
jn
Root
.
set_n
ame
(
"["
+
eventCountPair
.
first
.
sFunction
+
"]["
+
eventCountPair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
)
;
s
Root
N
ame
=
"["
+
eventCountPair
.
first
.
sFunction
+
"]["
+
eventCountPair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
;
else
jn
Root
.
set_n
ame
(
"["
+
eventCountPair
.
first
.
sFunction
+
"]["
+
eventCountPair
.
first
.
sName
+
"]["
+
std
::
to_string
(
std
::
hash
<
std
::
thread
::
id
>
()(
eventCountPair
.
first
.
iThreadId
)
)
+
"]"
)
;
s
Root
N
ame
=
"["
+
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
(
)
)
jn
Root
.
set_n
ame
(
"["
+
sectionPair
.
first
.
sFunction
+
"]["
+
sectionPair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
)
;
s
Root
N
ame
=
"["
+
sectionPair
.
first
.
sFunction
+
"]["
+
sectionPair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
;
else
jn
Root
.
set_n
ame
(
"["
+
sectionPair
.
first
.
sFunction
+
"]["
+
sectionPair
.
first
.
sName
+
"]["
+
std
::
to_string
(
std
::
hash
<
std
::
thread
::
id
>
()(
sectionPair
.
first
.
iThreadId
)
)
+
"]"
)
;
s
Root
N
ame
=
"["
+
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
(
)
)
jn
Root
.
set_n
ame
(
"["
+
valuePair
.
first
.
sFunction
+
"]["
+
valuePair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
);
s
Root
N
ame
=
(
"["
+
valuePair
.
first
.
sFunction
+
"]["
+
valuePair
.
first
.
sName
+
"]["
+
sThreadName
+
"]"
);
else
jn
Root
.
set_n
ame
(
"["
+
valuePair
.
first
.
sFunction
+
"]["
+
valuePair
.
first
.
sName
+
"]["
+
std
::
to_string
(
std
::
hash
<
std
::
thread
::
id
>
(
)
(
valuePair
.
first
.
iThreadId
)
)
+
"]"
)
;
s
Root
N
ame
=
"["
+
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:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment