Skip to content

Commit 1388f45

Browse files
committed
pcm-power: implement csv output
Change-Id: I1d575f50a333855402063eff45405e7a19c1bac9
1 parent 0b8e582 commit 1388f45

File tree

1 file changed

+125
-45
lines changed

1 file changed

+125
-45
lines changed

src/pcm-power.cpp

Lines changed: 125 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,8 @@ void print_usage(const string & progname)
341341
cout << " -silent => silence information output and print only measurements\n";
342342
cout << " --version => print application version\n";
343343
cout << " -i[=number] | /i[=number] => allow to determine number of iterations\n";
344-
// cout << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n"
345-
// << " to a file, in case filename is provided\n";
344+
cout << " -csv[=file.csv] | /csv[=file.csv] => output compact CSV format to screen or\n"
345+
<< " to a file, in case filename is provided\n";
346346
cout << " [-m imc_profile] [-p pcu_profile] [-a freq_band0] [-b freq_band1] [-c freq_band2]\n\n";
347347
cout << " Where: imc_profile, pcu_profile, freq_band0, freq_band1 and freq_band2 are the following:\n";
348348
cout << " <imc_profile> - profile (counter group) for IMC PMU. Possible values are: 0,1,2,3,4,-1 \n";
@@ -382,8 +382,64 @@ struct Metric
382382
Metric() = default;
383383
};
384384

385-
void printMetrics(const std::string & header, const std::vector<Metric> & metrics, const bool skipZeroValues = false)
385+
bool csv = false;
386+
bool csv_header = false;
387+
388+
void printMetrics(const std::string & header, const std::vector<Metric> & metrics, const CsvOutputType outputType, const bool skipZeroValues = false)
386389
{
390+
if (csv)
391+
{
392+
const auto numMetrics = metrics.size();
393+
choose(outputType,
394+
[&]() {
395+
for (size_t i = 0; i < numMetrics; ++i)
396+
{
397+
cout << header << ',';
398+
}
399+
},
400+
[&]() {
401+
for (size_t i = 0; i < numMetrics; ++i)
402+
{
403+
cout << metrics[i].name;
404+
if (!metrics[i].unit.empty())
405+
{
406+
cout << '(' << metrics[i].unit << ')';
407+
}
408+
cout << ',';
409+
}
410+
},
411+
[&]() {
412+
for (size_t i = 0; i < numMetrics; ++i)
413+
{
414+
if (std::holds_alternative<uint64>(metrics[i].value))
415+
{
416+
cout << std::get<uint64>(metrics[i].value);
417+
}
418+
else if (std::holds_alternative<double>(metrics[i].value))
419+
{
420+
cout << std::get<double>(metrics[i].value);
421+
}
422+
else if (std::holds_alternative<int64>(metrics[i].value))
423+
{
424+
cout << std::get<int64>(metrics[i].value);
425+
}
426+
else if (std::holds_alternative<int32>(metrics[i].value))
427+
{
428+
cout << std::get<int32>(metrics[i].value);
429+
}
430+
else if (std::holds_alternative<bool>(metrics[i].value))
431+
{
432+
cout << (std::get<bool>(metrics[i].value) ? '1' : '0');
433+
}
434+
else
435+
{
436+
assert(false && "Unknown metric type");
437+
}
438+
cout << ',';
439+
}
440+
});
441+
return;
442+
}
387443
cout << header << "; ";
388444
for (const auto & metric : metrics)
389445
{
@@ -444,14 +500,14 @@ void printMetrics(const std::string & header, const std::vector<Metric> & metric
444500
cout << "\n";
445501
}
446502

447-
void printMetrics(const std::string & header, const std::initializer_list<Metric> & metrics, const bool skipZeroValues = false)
503+
void printMetrics(const std::string & header, const std::initializer_list<Metric> & metrics, const CsvOutputType outputType, const bool skipZeroValues = false)
448504
{
449505
std::vector<Metric> metricsVec;
450506
for (const auto & metric : metrics)
451507
{
452508
metricsVec.push_back(metric);
453509
}
454-
printMetrics(header, metricsVec, skipZeroValues);
510+
printMetrics(header, metricsVec, outputType, skipZeroValues);
455511
}
456512

457513
PCM_MAIN_NOTHROW;
@@ -479,7 +535,6 @@ int mainThrows(int argc, char * argv[])
479535
freq_band[1] = default_freq_band[1];
480536
freq_band[2] = default_freq_band[2];
481537

482-
bool csv = false;
483538
MainLoop mainLoop;
484539
string program = string(argv[0]);
485540

@@ -504,10 +559,12 @@ int mainThrows(int argc, char * argv[])
504559
else if (check_argument_equals(*argv, {"-csv", "/csv"}))
505560
{
506561
csv = true;
562+
csv_header = true;
507563
}
508564
else if (extract_argument_value(*argv, {"-csv", "/csv"}, arg_value))
509565
{
510566
csv = true;
567+
csv_header = true;
511568
if (!arg_value.empty()) {
512569
m->setOutput(arg_value);
513570
}
@@ -684,10 +741,17 @@ int mainThrows(int argc, char * argv[])
684741

685742
if (PERF_LIMIT_REASON_TPMI_Supported) PERF_LIMIT_REASON_TPMI::reset(max_pm_modules);
686743

687-
auto printAll = [&](const int delay_ms)
744+
auto printAll = [&](const int delay_ms, const CsvOutputType outputType)
688745
{
689-
cout << "Time elapsed: " << AfterTime - BeforeTime << " ms\n";
690-
cout << "Called sleep function for " << delay_ms << " ms\n";
746+
if (csv)
747+
{
748+
printDateForCSV(outputType);
749+
}
750+
else
751+
{
752+
cout << "Time elapsed: " << AfterTime - BeforeTime << " ms\n";
753+
cout << "Called sleep function for " << delay_ms << " ms\n";
754+
}
691755
for (uint32 socket = 0; socket < numSockets; ++socket)
692756
{
693757
if (nCorePowerLicenses)
@@ -699,7 +763,7 @@ int mainThrows(int argc, char * argv[])
699763
{
700764
metrics.push_back(Metric("Core Power License " + std::to_string(l), getPowerLicenseResidency(l, beforeSocketState[socket], afterSocketState[socket]), "%"));
701765
}
702-
printMetrics("S" + std::to_string(socket), metrics);
766+
printMetrics("S" + std::to_string(socket), metrics, outputType);
703767
}
704768
for (uint32 port = 0; port < m->getQPILinksPerSocket(); ++port)
705769
{
@@ -708,7 +772,7 @@ int mainThrows(int argc, char * argv[])
708772
Metric(std::string(m->xPI()) + " Clocks", getQPIClocks(port, BeforeState[socket], AfterState[socket]), ""),
709773
Metric("L0p Tx Cycles", 100. * getNormalizedQPIL0pTxCycles(port, BeforeState[socket], AfterState[socket]), "%"),
710774
Metric("L1 Cycles", 100. * getNormalizedQPIL1Cycles(port, BeforeState[socket], AfterState[socket]), "%")
711-
});
775+
}, outputType);
712776
}
713777
for (uint32 channel = 0; channel < m->getMCChannelsPerSocket(); ++channel)
714778
{
@@ -723,7 +787,7 @@ int mainThrows(int argc, char * argv[])
723787
getCKEOffAverageCycles(channel, getFirstRank(imc_profile), BeforeState[socket], AfterState[socket]), ""),
724788
Metric("Rank" + std::to_string(getFirstRank(imc_profile)) + " Cycles per transition",
725789
getCyclesPerTransition(channel, getFirstRank(imc_profile), BeforeState[socket], AfterState[socket]), "")
726-
});
790+
}, outputType);
727791

728792
printMetrics("S" + std::to_string(socket) + "CH" + std::to_string(channel),
729793
{
@@ -734,7 +798,7 @@ int mainThrows(int argc, char * argv[])
734798
getCKEOffAverageCycles(channel, getSecondRank(imc_profile), BeforeState[socket], AfterState[socket]), ""),
735799
Metric("Rank" + std::to_string(getSecondRank(imc_profile)) + " Cycles per transition",
736800
getCyclesPerTransition(channel, getSecondRank(imc_profile), BeforeState[socket], AfterState[socket]), "")
737-
});
801+
}, outputType);
738802
} else if (imc_profile == 4)
739803
{
740804
printMetrics("S" + std::to_string(socket) + "CH" + std::to_string(channel),
@@ -743,55 +807,51 @@ int mainThrows(int argc, char * argv[])
743807
Metric("Self-refresh cycles", getSelfRefreshCycles(channel, BeforeState[socket], AfterState[socket]), ""),
744808
Metric("Self-refresh transitions", getSelfRefreshTransitions(channel, BeforeState[socket], AfterState[socket]), ""),
745809
Metric("PPD cycles", getPPDCycles(channel, BeforeState[socket], AfterState[socket]), "")
746-
});
810+
}, outputType);
747811
}
748812
}
749813

750814
for (uint32 u = 0; u < m->getMaxNumOfUncorePMUs(PCM::PCU_PMU_ID); ++u)
751815
{
752-
auto getHeader = [&socket,&m,&u, &BeforeState, &AfterState] ()
816+
std::string header = "S" + std::to_string(socket);
817+
if (m->getMaxNumOfUncorePMUs(PCM::PCU_PMU_ID) > 1)
753818
{
754-
std::string header = "S" + std::to_string(socket);
755-
if (m->getMaxNumOfUncorePMUs(PCM::PCU_PMU_ID) > 1)
756-
{
757-
header += "U" + std::to_string(u);
758-
}
759-
return header;
760-
};
819+
header += "U" + std::to_string(u);
820+
}
761821
std::vector<Metric> metrics;
762822
switch (pcu_profile)
763823
{
764824
case 0:
765825
if (cpu_family_model == PCM::HASWELLX || cpu_family_model == PCM::BDX_DE || cpu_family_model == PCM::SKX)
766826
break;
767827

768-
printMetrics(getHeader(),
828+
printMetrics(header,
769829
{
770830
Metric("PCUClocks", getPCUClocks(u, BeforeState[socket], AfterState[socket]), ""),
771831
Metric("Freq band 0 cycles", 100. * getNormalizedPCUCounter(u, 1, BeforeState[socket], AfterState[socket]), "%"),
772832
Metric("Freq band 1 cycles", 100. * getNormalizedPCUCounter(u, 2, BeforeState[socket], AfterState[socket]), "%"),
773833
Metric("Freq band 2 cycles", 100. * getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket]), "%")
774-
});
834+
}, outputType);
775835
break;
776836

777837
case 1:
778-
printMetrics(getHeader(),
838+
printMetrics(header,
779839
{
780840
Metric("PCUClocks", getPCUClocks(u, BeforeState[socket], AfterState[socket]), ""),
781841
Metric(cpu_family_model == PCM::SKX ? "C0_1-state residency" : "C0-state residency", getNormalizedPCUCounter(u, 1, BeforeState[socket], AfterState[socket]), ""),
782842
Metric("C3-state residency", getNormalizedPCUCounter(u, 2, BeforeState[socket], AfterState[socket]), ""),
783843
Metric(cpu_family_model == PCM::SKX ? "C6_7-state residency" : "C6-state residency", getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket]), "")
784-
});
844+
}, outputType);
785845
break;
786846

787847
case 2:
788-
printMetrics(getHeader(),
848+
printMetrics(header,
789849
{
790850
Metric("PCUClocks", getPCUClocks(u, BeforeState[socket], AfterState[socket]), ""),
791851
Metric("Internal prochot cycles", 100. * getNormalizedPCUCounter(u, 1, BeforeState[socket], AfterState[socket]), "%"),
792852
Metric("External prochot cycles", 100. * getNormalizedPCUCounter(u, 2, BeforeState[socket], AfterState[socket]), "%"),
793853
Metric("Thermal freq limit cycles", 100. * getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket]), "%")
794-
});
854+
}, outputType);
795855
break;
796856

797857
case 3:
@@ -809,7 +869,7 @@ int mainThrows(int argc, char * argv[])
809869
{
810870
metrics.push_back(Metric("Clipped freq limit cycles", 100. * getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket]), "%"));
811871
}
812-
printMetrics(getHeader(), metrics);
872+
printMetrics(header, metrics, outputType);
813873
break;
814874

815875
case 4:
@@ -826,13 +886,13 @@ int mainThrows(int argc, char * argv[])
826886
cout << "This PCU profile is not supported on your processor\n";
827887
break;
828888
}
829-
printMetrics(getHeader(),
889+
printMetrics(header,
830890
{
831891
Metric("PCUClocks", getPCUClocks(u, BeforeState[socket], AfterState[socket]), ""),
832892
Metric("OS freq limit cycles", 100. * getNormalizedPCUCounter(u, 1, BeforeState[socket], AfterState[socket]), "%"),
833893
Metric("Power freq limit cycles", 100. * getNormalizedPCUCounter(u, 2, BeforeState[socket], AfterState[socket]), "%"),
834894
Metric("Clipped freq limit cycles", 100. * getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket]), "%")
835-
});
895+
}, outputType);
836896
break;
837897
case 5:
838898
metrics.push_back(Metric("PCUClocks", getPCUClocks(u, BeforeState[socket], AfterState[socket]), ""));
@@ -843,7 +903,7 @@ int mainThrows(int argc, char * argv[])
843903
metrics.push_back(Metric("UFS transition count", getUncoreCounter(PCM::PCU_PMU_ID, u, 3, BeforeState[socket], AfterState[socket]), ""));
844904
metrics.push_back(Metric("UFS transition cycles", 100. * getNormalizedPCUCounter(u, 0, BeforeState[socket], AfterState[socket], m), "%"));
845905
}
846-
printMetrics(getHeader(), metrics);
906+
printMetrics(header, metrics, outputType);
847907
break;
848908
case 6:
849909
if (cpu_family_model == PCM::HASWELLX || PCM::BDX_DE == cpu_family_model)
@@ -871,25 +931,25 @@ int mainThrows(int argc, char * argv[])
871931
metrics.push_back(Metric("PC6 transitions", getUncoreCounter(PCM::PCU_PMU_ID, u, 3, BeforeState[socket], AfterState[socket]), ""));
872932
break;
873933
}
874-
printMetrics(getHeader(), metrics);
934+
printMetrics(header, metrics, outputType);
875935
break;
876936
case 7:
877937
if (PCM::HASWELLX == cpu_family_model || PCM::BDX_DE == cpu_family_model || PCM::BDX == cpu_family_model) {
878-
printMetrics(getHeader(),
938+
printMetrics(header,
879939
{
880940
Metric("UFS_TRANSITIONS_PERF_P_LIMIT", getNormalizedPCUCounter(u, 0, BeforeState[socket], AfterState[socket], m) * 100., "%"),
881941
Metric("UFS_TRANSITIONS_IO_P_LIMIT", getNormalizedPCUCounter(u, 1, BeforeState[socket], AfterState[socket], m) * 100., "%"),
882942
Metric("UFS_TRANSITIONS_UP_RING_TRAFFIC", getNormalizedPCUCounter(u, 2, BeforeState[socket], AfterState[socket], m) * 100., "%"),
883943
Metric("UFS_TRANSITIONS_UP_STALL_CYCLES", getNormalizedPCUCounter(u, 3, BeforeState[socket], AfterState[socket], m) * 100., "%")
884-
});
944+
}, outputType);
885945
}
886946
break;
887947
case 8:
888948
if (PCM::HASWELLX == cpu_family_model || PCM::BDX_DE == cpu_family_model || PCM::BDX == cpu_family_model) {
889-
printMetrics(getHeader(),
949+
printMetrics(header,
890950
{
891951
Metric("UFS_TRANSITIONS_DOWN", getNormalizedPCUCounter(u, 0, BeforeState[socket], AfterState[socket], m) * 100., "%")
892-
});
952+
}, outputType);
893953
}
894954
break;
895955
}
@@ -901,13 +961,13 @@ int mainThrows(int argc, char * argv[])
901961
Metric("Consumed Joules", getConsumedJoules(BeforeState[socket], AfterState[socket]), ""),
902962
Metric("Watts", 1000. * getConsumedJoules(BeforeState[socket], AfterState[socket]) / double(AfterTime - BeforeTime), ""),
903963
Metric("Thermal headroom below TjMax", AfterState[socket].getPackageThermalHeadroom(), "°C")
904-
});
964+
}, outputType);
905965
printMetrics("S" + std::to_string(socket),
906966
{
907967
Metric("Consumed DRAM energy units", getDRAMConsumedEnergy(BeforeState[socket], AfterState[socket]), ""),
908968
Metric("Consumed DRAM Joules", getDRAMConsumedJoules(BeforeState[socket], AfterState[socket]), ""),
909969
Metric("DRAM Watts", 1000. * getDRAMConsumedJoules(BeforeState[socket], AfterState[socket]) / double(AfterTime - BeforeTime), "")
910-
});
970+
}, outputType);
911971
}
912972
for (auto instance = 0ULL; instance < PERF_LIMIT_REASON_TPMI_dies_data.size(); ++instance)
913973
{
@@ -919,7 +979,7 @@ int mainThrows(int argc, char * argv[])
919979
{
920980
metrics.push_back(Metric(PERF_LIMIT_REASON_TPMI::Coarse_Grained_PLR_Bit_Definition_Strings[l], extract_bits(data, l, l) ? true : false, ""));
921981
}
922-
printMetrics("S" + std::to_string(instance) + "D" + std::to_string(die) + " PERF LIMIT REASONS (DIE LEVEL)", metrics);
982+
printMetrics("S" + std::to_string(instance) + "D" + std::to_string(die) + " PERF LIMIT REASONS (DIE LEVEL)", metrics, outputType);
923983
}
924984
}
925985
for (auto instance = 0ULL; instance < PERF_LIMIT_REASON_TPMI_modules_data.size(); ++instance)
@@ -960,16 +1020,27 @@ int mainThrows(int argc, char * argv[])
9601020
metrics.push_back(Metric(std::string(PERF_LIMIT_REASON_TPMI::Coarse_Grained_PLR_Bit_Definition_Strings[PERF_LIMIT_REASON_TPMI::Fine_Grained_PLR_Bit_Definition_Data[l].coarse_grained_mapping]) + "." +
9611021
PERF_LIMIT_REASON_TPMI::Fine_Grained_PLR_Bit_Definition_Data[l].name, fineGrainedData[die][l], ""));
9621022
}
963-
printMetrics("S" + std::to_string(instance) + "D" + std::to_string(die) + " PERF LIMIT REASONS (#CORE MODULES)", metrics, true);
1023+
printMetrics("S" + std::to_string(instance) + "D" + std::to_string(die) + " PERF LIMIT REASONS (#CORE MODULES)", metrics, outputType, true);
9641024
}
9651025
}
1026+
if (csv)
1027+
{
1028+
cout << "\n";
1029+
}
9661030
};
9671031

968-
mainLoop([&]()
1032+
auto printLine = []()
9691033
{
9701034
cout << "----------------------------------------------------------------------------------------------\n";
1035+
};
9711036

972-
if (!csv) cout << flush;
1037+
mainLoop([&]()
1038+
{
1039+
if (!csv)
1040+
{
1041+
printLine();
1042+
cout << flush;
1043+
}
9731044

9741045
const auto delay_ms = calibratedSleep(delay, sysCmd, mainLoop, m);
9751046

@@ -986,14 +1057,23 @@ int mainThrows(int argc, char * argv[])
9861057
PERF_LIMIT_REASON_TPMI::reset(max_pm_modules);
9871058
}
9881059

989-
printAll(delay_ms);
1060+
if (csv_header)
1061+
{
1062+
printAll(delay_ms, Header1);
1063+
printAll(delay_ms, Header2);
1064+
csv_header = false;
1065+
}
1066+
printAll(delay_ms, Data);
9901067

9911068
swap(BeforeState, AfterState);
9921069
swap(BeforeTime, AfterTime);
9931070
swap(beforeSocketState, afterSocketState);
9941071

9951072
if (m->isBlocked()) {
996-
cout << "----------------------------------------------------------------------------------------------\n";
1073+
if (!csv)
1074+
{
1075+
printLine();
1076+
}
9971077
// in case PCM was blocked after spawning child application: break monitoring loop here
9981078
return false;
9991079
}

0 commit comments

Comments
 (0)