Skip to content

Commit 6665aa2

Browse files
committed
Add json output to pcm-raw
1 parent 88da511 commit 6665aa2

File tree

4 files changed

+119
-37
lines changed

4 files changed

+119
-37
lines changed

.github/workflows/ci-test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,9 @@ jobs:
6363
with:
6464
name: test-log-raw-tr-wi_ext-single_header-${{ github.sha }}
6565
path: build/bin/raw_tr_wi_ext_single_header.csv
66+
67+
- name: upload-artifact
68+
uses: actions/upload-artifact@v2
69+
with:
70+
name: test-log-raw-json-${{ github.sha }}
71+
path: build/bin/raw_json.json

src/pcm-raw.cpp

Lines changed: 83 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ void print_usage(const string progname)
6666
cerr << " -r | --reset | /reset => reset PMU configuration (at your own risk)\n";
6767
cerr << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n"
6868
<< " to a file, in case filename is provided\n";
69+
cerr << " -json[=file.json] | /json[=file.json] => output json format to screen or\n"
70+
<< " to a file, in case filename is provided\n";
6971
cerr << " -out filename | /out filename => write all output (stdout and stderr) to specified file\n";
7072
cerr << " event description example: -e core/config=0x30203,name=LD_BLOCKS.STORE_FORWARD/ -e core/fixed,config=0x333/ \n";
7173
cerr << " -e cha/config=0,name=UNC_CHA_CLOCKTICKS/ -e imc/fixed,name=DRAM_CLOCKS/\n";
@@ -954,7 +956,9 @@ bool transpose = false;
954956
bool extendPrintout = false;
955957
bool singleHeader = false;
956958
std::string separator = ",";
959+
const std::string jsonSeparator = "\":";
957960
bool sampleSeparator = false;
961+
bool outputToJson = false;
958962

959963
struct PrintOffset {
960964
const std::string entry;
@@ -973,21 +977,41 @@ int getPrintOffsetIdx(const std::string &value) {
973977
return -1;
974978
}
975979

976-
void printRowBegin(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
980+
void printNewLine(const CsvOutputType outputType) {
981+
if (outputType == Data)
982+
cout << "\n";
983+
else if (outputType == Json)
984+
cout << "}\n";
985+
}
986+
987+
void printRowBeginCSV(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
977988
{
978989
printDateForCSV(CsvOutputType::Data, separator);
979990
cout << EventName << separator << (1000ULL * getInvariantTSC(BeforeState, AfterState)) / m->getNominalFrequency() << separator << getInvariantTSC(BeforeState, AfterState);
980991
}
981992

982-
983-
template <class MetricFunc>
984-
void printRow(const std::string & EventName, MetricFunc metricFunc, const std::vector<CoreCounterState>& BeforeState, const std::vector<CoreCounterState>& AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset)
993+
void printRowBeginJson(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m)
985994
{
995+
cout << "{\"";
996+
printDateForJson(separator, jsonSeparator);
997+
cout << "Event" << jsonSeparator << "\"" << EventName << "\"" << separator << "ms" << jsonSeparator << (1000ULL * getInvariantTSC(BeforeState, AfterState)) / m->getNominalFrequency()
998+
<< separator << "InvariantTSC" << jsonSeparator << getInvariantTSC(BeforeState, AfterState);
999+
}
1000+
1001+
void printRowBegin(const std::string & EventName, const CoreCounterState & BeforeState, const CoreCounterState & AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset) {
9861002
if (outputType == Data) {
987-
printRowBegin(EventName, BeforeState[0], AfterState[0], m);
1003+
printRowBeginCSV(EventName, BeforeState, AfterState, m);
9881004
for (int i = 0 ; i < printOffset.start ; i++)
9891005
std::cout << separator;
1006+
} else if (outputType == Json) {
1007+
printRowBeginJson(EventName, BeforeState, AfterState, m);
9901008
}
1009+
}
1010+
1011+
template <class MetricFunc>
1012+
void printRow(const std::string & EventName, MetricFunc metricFunc, const std::vector<CoreCounterState>& BeforeState, const std::vector<CoreCounterState>& AfterState, PCM* m, const CsvOutputType outputType, PrintOffset& printOffset)
1013+
{
1014+
printRowBegin(EventName, BeforeState[0], AfterState[0], m, outputType, printOffset);
9911015

9921016
for (uint32 core = 0; core < m->getNumCores(); ++core)
9931017
{
@@ -1005,13 +1029,15 @@ void printRow(const std::string & EventName, MetricFunc metricFunc, const std::v
10051029
cout << separator << "core_SKT" << m->getSocketId(core) << "_CORE" << core;
10061030
printOffset.end++;
10071031
}
1008-
else
1032+
else if (outputType == Json) {
1033+
cout << separator << "core_SKT" << m->getSocketId(core) << "_CORE" << core <<
1034+
jsonSeparator << metricFunc(BeforeState[core], AfterState[core]);
1035+
} else
10091036
assert(!"unknown output type");
10101037
}
10111038
}
10121039

1013-
if (outputType == Data)
1014-
cout << "\n";
1040+
printNewLine(outputType);
10151041
};
10161042

10171043
typedef uint64 (*UncoreMetricFunc)(const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after);
@@ -1089,11 +1115,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
10891115
{
10901116
if (fixedEvents.size())
10911117
{
1092-
if (outputType == Data) {
1093-
printRowBegin(miscName, BeforeState[0], AfterState[0], m);
1094-
for (int off = 0 ; off < printOffset.start; off++)
1095-
cout << separator;
1096-
}
1118+
printRowBegin(miscName, BeforeState[0], AfterState[0], m, outputType, printOffset);
10971119

10981120
for (uint32 s = 0; s < m->getNumSockets(); ++s)
10991121
{
@@ -1111,6 +1133,9 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11111133
else if (outputType == Header21) {
11121134
cout << separator << type << "_SKT" << s << "_" << miscName << u;
11131135
printOffset.end++;
1136+
} else if (outputType == Json) {
1137+
cout << separator << type << "_SKT" << s << "_" << miscName << u
1138+
<< jsonSeparator << fixedMetricFunc(u, BeforeUncoreState[s], AfterUncoreState[s]);
11141139
} else
11151140
assert(!"unknown output type");
11161141
}
@@ -1119,8 +1144,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11191144
if (is_header)
11201145
is_header_printed = true;
11211146

1122-
if (outputType == Data)
1123-
cout << "\n";
1147+
printNewLine(outputType);
11241148
}
11251149
uint32 i = 0;
11261150
for (auto& event : events)
@@ -1130,11 +1154,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11301154
if (is_header && is_header_printed)
11311155
break;
11321156

1133-
if (outputType == Data) {
1134-
printRowBegin(name, BeforeState[0], AfterState[0], m);
1135-
for (int off = 0 ; off < printOffset.start; off++)
1136-
cout << separator;
1137-
}
1157+
printRowBegin(name, BeforeState[0], AfterState[0], m, outputType, printOffset);
11381158

11391159
for (uint32 s = 0; s < m->getNumSockets(); ++s)
11401160
{
@@ -1158,6 +1178,11 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11581178
cout << separator << type << "_SKT" << s << "_" << miscName << u;
11591179
printOffset.end++;
11601180
}
1181+
else if (outputType == Json)
1182+
{
1183+
cout << separator << type << "_SKT" << s << "_" << miscName << u
1184+
<< jsonSeparator << metricFunc(u, i, BeforeUncoreState[s], AfterUncoreState[s]);
1185+
}
11611186
else
11621187
{
11631188
assert(!"unknown output type");
@@ -1169,8 +1194,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11691194
is_header_printed = true;
11701195

11711196
++i;
1172-
if (outputType == Data)
1173-
cout << "\n";
1197+
printNewLine(outputType);
11741198
}
11751199
};
11761200
auto printMSRRows = [&](const MSRScope& scope)
@@ -1184,11 +1208,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
11841208
if (is_header && is_header_printed)
11851209
return false;
11861210

1187-
if (outputType == Data) {
1188-
printRowBegin(name, BeforeState[0], AfterState[0], m);
1189-
for (int off = 0; off < printOffset.start; off++)
1190-
cout << separator;
1191-
}
1211+
printRowBegin(name, BeforeState[0], AfterState[0], m, outputType, printOffset);
11921212

11931213
switch (scope)
11941214
{
@@ -1213,6 +1233,10 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12131233
cout << separator << type << "_SKT" << s ;
12141234
printOffset.end++;
12151235
}
1236+
else if (outputType == Json) {
1237+
cout << separator << type << "_SKT" << s
1238+
<< jsonSeparator << getMSREvent(index, msrType, BeforeSocketState[s], AfterSocketState[s]);
1239+
}
12161240
else
12171241
{
12181242
assert(!"unknown output type");
@@ -1240,6 +1264,10 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12401264
cout << separator << type << "_SKT" << m->getSocketId(core) << "_CORE" << core;
12411265
printOffset.end++;
12421266
}
1267+
else if (outputType == Json) {
1268+
cout << separator << type << "_SKT" << m->getSocketId(core) << "_CORE" << core
1269+
<< jsonSeparator << getMSREvent(index, msrType, BeforeState[core], AfterState[core]);
1270+
}
12431271
else
12441272
{
12451273
assert(!"unknown output type");
@@ -1251,8 +1279,7 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
12511279
if (is_header)
12521280
is_header_printed = true;
12531281

1254-
if (outputType == Data)
1255-
cout << "\n";
1282+
printNewLine(outputType);
12561283

12571284
return true;
12581285
};
@@ -1335,15 +1362,15 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13351362
choose(outputType,
13361363
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), "LINK"); },
13371364
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), type); },
1338-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM3UPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket());
1365+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM3UPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket(), "LINK");
13391366
});
13401367
}
13411368
else if (type == "xpi" || type == "upi" || type == "qpi")
13421369
{
13431370
choose(outputType,
13441371
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), "LINK"); },
13451372
[&]() { printUncoreRows(nullptr, (uint32) m->getQPILinksPerSocket(), type); },
1346-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getXPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket());
1373+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getXPICounter(u, i, before, after); }, (uint32) m->getQPILinksPerSocket(), "LINK");
13471374
});
13481375
}
13491376
else if (type == "imc")
@@ -1360,15 +1387,15 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13601387
choose(outputType,
13611388
[&]() { printUncoreRows(nullptr, (uint32) m->getMCPerSocket(), "MC"); },
13621389
[&]() { printUncoreRows(nullptr, (uint32) m->getMCPerSocket(), type); },
1363-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM2MCounter(u, i, before, after); }, (uint32)m->getMCPerSocket());
1390+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getM2MCounter(u, i, before, after); }, (uint32)m->getMCPerSocket(), "MC");
13641391
});
13651392
}
13661393
else if (type == "pcu")
13671394
{
13681395
choose(outputType,
13691396
[&]() { printUncoreRows(nullptr, 1U, ""); },
13701397
[&]() { printUncoreRows(nullptr, 1U, type); },
1371-
[&]() { printUncoreRows([](const uint32, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getPCUCounter(i, before, after); }, 1U);
1398+
[&]() { printUncoreRows([](const uint32, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getPCUCounter(i, before, after); }, 1U, "");
13721399
});
13731400
}
13741401
else if (type == "ubox")
@@ -1385,23 +1412,23 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
13851412
choose(outputType,
13861413
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfCBoxes(), "C"); },
13871414
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfCBoxes(), type); },
1388-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getCBOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfCBoxes());
1415+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getCBOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfCBoxes(), "C");
13891416
});
13901417
}
13911418
else if (type == "irp")
13921419
{
13931420
choose(outputType,
13941421
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), "IRP"); },
13951422
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), type); },
1396-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIRPCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks());
1423+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIRPCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks(), "IRP");
13971424
});
13981425
}
13991426
else if (type == "iio")
14001427
{
14011428
choose(outputType,
14021429
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), "IIO"); },
14031430
[&]() { printUncoreRows(nullptr, (uint32) m->getMaxNumOfIIOStacks(), type); },
1404-
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIIOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks());
1431+
[&]() { printUncoreRows([](const uint32 u, const uint32 i, const ServerUncoreCounterState& before, const ServerUncoreCounterState& after) { return getIIOCounter(u, i, before, after); }, (uint32)m->getMaxNumOfIIOStacks(), "IIO");
14051432
});
14061433
}
14071434
else
@@ -1735,6 +1762,11 @@ void printAll(const PCM::RawPMUConfigs& curPMUConfigs,
17351762
std::vector<PCM::RawPMUConfigs>& PMUConfigs,
17361763
const bool & isLastGroup)
17371764
{
1765+
if (outputToJson) {
1766+
printTransposed(curPMUConfigs, m, BeforeState, AfterState, BeforeUncoreState, AfterUncoreState, BeforeSocketState, AfterSocketState, Json, isLastGroup);
1767+
return;
1768+
}
1769+
17381770
static bool displayHeader = true;
17391771

17401772
if (!extendPrintout && transpose)
@@ -1843,6 +1875,21 @@ int main(int argc, char* argv[])
18431875
}
18441876
continue;
18451877
}
1878+
else if (strncmp(*argv, "-json", 5) == 0 ||
1879+
strncmp(*argv, "/json", 5) == 0)
1880+
{
1881+
separator = ",\"";
1882+
outputToJson = true;
1883+
string cmd = string(*argv);
1884+
size_t found = cmd.find('=', 5);
1885+
if (found != string::npos) {
1886+
string filename = cmd.substr(found + 1);
1887+
if (!filename.empty()) {
1888+
m->setOutput(filename);
1889+
}
1890+
}
1891+
continue;
1892+
}
18461893
else if (mainLoop.parseArg(*argv))
18471894
{
18481895
continue;

src/utils.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ enum CsvOutputType
239239
Header1,
240240
Header2,
241241
Data,
242-
Header21 // merged headers 2 and 1
242+
Header21, // merged headers 2 and 1
243+
Json
243244
};
244245

245246
template <class H1, class H2, class D>
@@ -255,6 +256,7 @@ inline void choose(const CsvOutputType outputType, H1 h1Func, H2 h2Func, D dataF
255256
h2Func();
256257
break;
257258
case Data:
259+
case Json:
258260
dataFunc();
259261
break;
260262
default:
@@ -289,6 +291,26 @@ inline void printDateForCSV(const CsvOutputType outputType, std::string separato
289291
});
290292
}
291293

294+
inline void printDateForJson(const std::string& separator, const std::string &jsonSeparator)
295+
{
296+
std::pair<tm, uint64> tt{ pcm_localtime() };
297+
std::cout.precision(3);
298+
char old_fill = std::cout.fill('0');
299+
std::cout <<
300+
"Date" << jsonSeparator << "\"" <<
301+
std::setw(4) << 1900 + tt.first.tm_year << '-' <<
302+
std::setw(2) << 1 + tt.first.tm_mon << '-' <<
303+
std::setw(2) << tt.first.tm_mday << "\"" << separator <<
304+
"Time" << jsonSeparator << "\"" <<
305+
std::setw(2) << tt.first.tm_hour << ':' <<
306+
std::setw(2) << tt.first.tm_min << ':' <<
307+
std::setw(2) << tt.first.tm_sec << '.' <<
308+
std::setw(3) << tt.second << "\"" << separator; // milliseconds
309+
std::cout.fill(old_fill);
310+
std::cout.setf(std::ios::fixed);
311+
std::cout.precision(2);
312+
}
313+
292314
std::vector<std::string> split(const std::string & str, const char delim);
293315

294316
class PCM;

tests/test.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,11 @@ if [ "$?" -ne "0" ]; then
327327
exit 1
328328
fi
329329

330+
echo Testing pcm-raw with -json
331+
./pcm-raw -el event_file_test.txt -json=raw_json.json -i=4 0.25
332+
if [ "$?" -ne "0" ]; then
333+
echo "Error in pcm-raw"
334+
exit 1
335+
fi
336+
330337
popd

0 commit comments

Comments
 (0)