4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "Stroika/Foundation/Characters/FloatConversion.h"
12#include "Stroika/Foundation/Execution/CommandLine.h"
13#include "Stroika/Foundation/Execution/Process.h"
15#if qStroika_Foundation_Common_Platform_POSIX
16#include "Stroika/Foundation/Execution/SignalHandlers.h"
19#include "Stroika/Foundation/Execution/WaitableEvent.h"
20#include "Stroika/Foundation/Streams/MemoryStream.h"
22#include "Stroika/Frameworks/SystemPerformance/AllInstruments.h"
23#include "Stroika/Frameworks/SystemPerformance/Capturer.h"
24#include "Stroika/Frameworks/SystemPerformance/Instruments/CPU.h"
25#include "Stroika/Frameworks/SystemPerformance/Instruments/Memory.h"
26#include "Stroika/Frameworks/SystemPerformance/Instruments/Process.h"
27#include "Stroika/Frameworks/SystemPerformance/Measurement.h"
34using namespace Stroika::Frameworks;
35using namespace Stroika::Frameworks::SystemPerformance;
54 String result = String::FromUTF8 (out.
As<
string> ());
56 result = result.
StripAll ([] (
Character c) ->
bool {
return c ==
'\n' or c ==
'\r'; });
60#if qCompilerAndStdLib_template_template_argument_as_different_template_paramters_Buggy
66#if qCompilerAndStdLib_template_template_argument_as_different_template_paramters_Buggy
67 return Time::clock_cast<DisplayedRealtimeClock, RANGE_TEMPLATE_BWA> (tpRange);
68#elif qCompilerAndStdLib_template_template_auto_deduced_Buggy
69 return Time::clock_cast<DisplayedRealtimeClock, Range> (tpRange);
71 return Time::clock_cast<DisplayedRealtimeClock> (tpRange);
74 void Demo_PrintInstruments_ ()
76 cout <<
"Instrument:" << endl;
77 for (
const Instrument& i : SystemPerformance::GetAllInstruments ()) {
78 cout <<
" " << i.instrumentName ().GetPrintName ().AsNarrowSDKString () << endl;
88 for (
const Instrument& i : SystemPerformance::GetAllInstruments ()) {
89 if (not run.
empty ()) {
90 if (not run.Contains (i.instrumentName)) {
96 capturer.AddCaptureSet (cs);
98 capturer.AddMeasurementsCallback ([oneLineMode] (
MeasurementSet ms) {
99 cout <<
" Measured-At: " << toDisp_ (ms.fMeasuredAt).ToString ().AsNarrowSDKString () << endl;
101 cout <<
" " << mi.fType.GetPrintName ().AsNarrowSDKString () <<
": " << Serialize_ (mi.fValue, oneLineMode) << endl;
110 cout <<
"Results for each instrument:" << endl;
111 for (
Instrument i : SystemPerformance::GetAllInstruments ()) {
112 if (not run.
empty ()) {
113 if (not run.Contains (i.instrumentName)) {
117 cout <<
" " << i.instrumentName ().GetPrintName ().AsNarrowSDKString () << endl;
118 Execution::Sleep (captureInterval);
120 if (m.fMeasurements.empty ()) {
121 cout <<
" NO DATA" << endl;
124 cout <<
" Measured-At: " << toDisp_ (m.fMeasuredAt).ToString ().AsNarrowSDKString () << endl;
126 cout <<
" " << mi.fType.GetPrintName ().AsNarrowSDKString () <<
": " << Serialize_ (mi.fValue, oneLineMode) << endl;
134 namespace Demo_Using_Capturer_GetMostRecentMeasurements__Private_ {
135 using namespace Stroika::Frameworks::SystemPerformance;
143 : fProcessInstrument{Instruments::Process::Options{.fRestrictToPIDs =
Set<
pid_t>{Execution::GetCurrentProcessID ()}}}
145 AddCaptureSet (
CaptureSet{30s, {fCPUInstrument, fProcessInstrument}});
149 void Demo_Using_Capturer_GetMostRecentMeasurements_ (
const Duration& runFor)
158 using namespace Demo_Using_Capturer_GetMostRecentMeasurements__Private_;
160 MyCapturer_ capturer;
164 cout <<
"Printing most recent measurements (in loop):" << endl;
165 while (Time::GetTickCount () < doneAt) {
166 auto measurements = capturer.pMostRecentMeasurements ();
167 DateTime now = DateTime::Now ();
169 optional<double> runQLength;
170 optional<double> totalCPUUsage;
171 optional<double> totalCPURatio;
172 if (
auto om = capturer.fCPUInstrument.MeasurementAs<Instruments::CPU::Info> (measurements)) {
173 runQLength = om->fRunQLength;
174 totalCPUUsage = om->fTotalCPUUsage;
175 totalCPURatio = om->GetTotalCPURatio ();
177 optional<Duration> thisProcUptime;
178 optional<Duration> thisProcAverageCPUTimeUsed;
179 optional<uint64_t> thisProcWorkingOrResidentSetSize;
180 optional<double> thisProcCombinedIORate;
183 Assert (om->size () <= 1);
184 if (om->size () == 1) {
186 if (
auto o = thisProcess.fProcessStartedAt) {
187 thisProcUptime = now - *o;
191 thisProcCombinedIORate = thisProcess.fCombinedIOWriteRate;
194 using namespace Memory;
195 cout <<
"\tPass: " << pass << endl;
196 cout <<
"\t\tSys: " << endl;
197 cout <<
"\t\t\tRun-Q Length: " << Characters::ToString (runQLength).AsNarrowSDKString () << endl;
198 cout <<
"\t\t\tTotal CPU Usage: " << Characters::ToString (totalCPUUsage).AsNarrowSDKString () <<
" ("
199 << Characters::ToString (totalCPURatio * 100.0).AsNarrowSDKString () <<
"% of computer)" << endl;
200 cout <<
"\t\tThis Process: " << endl;
201 cout <<
"\t\t\tUptime: " << Characters::ToString (thisProcUptime).AsNarrowSDKString () << endl;
202 cout <<
"\t\t\tAverage CPU Time Used: " << Characters::ToString (thisProcAverageCPUTimeUsed).AsNarrowSDKString () << endl;
203 cout <<
"\t\t\tWorking Or Resident-Set Size: " << Characters::ToString (thisProcWorkingOrResidentSetSize).AsNarrowSDKString () << endl;
204 cout <<
"\t\t\tCombined IO Rate: " << Characters::ToString (thisProcCombinedIORate).AsNarrowSDKString () << endl;
205 Execution::Sleep (30s);
211int main (
int argc,
const char* argv[])
215#if qStroika_Foundation_Common_Platform_POSIX
218 using namespace Execution::StandardCommandLineOptions;
221 const Execution::CommandLine::Option kOneLineModeO_{.fSingleCharName =
'o', .fHelpOptionText =
"prints instrument results (with newlines stripped)"sv};
223 .fSupportsArgument =
true,
225 .fHelpArgName =
"RUN-INSTRUMENT"sv,
226 .fHelpOptionText =
"runs the given instrument (it can be repeated)"sv};
228 .fSingleCharName =
't', .fSupportsArgument =
true, .fHelpOptionText =
"time to run for (if zero run each matching instrument once)"sv};
230 .fSingleCharName =
'c', .fSupportsArgument =
true, .fHelpArgName =
"NSEC"sv, .fHelpOptionText =
"time interval between captures"sv};
232 const initializer_list<Execution::CommandLine::Option> kAllOptions_ = {
233 kHelp, kPrintNamesO_, kMostRecentO_, kOneLineModeO_, kRunInstrumentArg_, kRunForO_, kTimeBetweenCapturesO_};
235 bool printUsage = cmdLine.Has (kHelp);
236 bool mostRecentCaptureMode = cmdLine.Has (kMostRecentO_);
237 bool printNames = cmdLine.Has (kPrintNamesO_);
238 bool oneLineMode = cmdLine.Has (kOneLineModeO_);
240 if (
auto o = cmdLine.GetArgument (kRunForO_)) {
241 runFor =
Duration{Characters::FloatConversion::ToFloat<Duration::rep> (*o)};
244 if (
auto o = cmdLine.GetArgument (kTimeBetweenCapturesO_)) {
245 captureInterval =
Duration{Characters::FloatConversion::ToFloat<Duration::rep> (*o)};
251 cerr << cmdLine.GenerateUsage (kAllOptions_).AsNarrowSDKString ();
256 cmdLine.Validate (kAllOptions_);
258 Demo_PrintInstruments_ ();
260 else if (mostRecentCaptureMode) {
261 Demo_Using_Capturer_GetMostRecentMeasurements_ (runFor);
263 else if (runFor > 0s) {
264 Demo_UsingCapturerWithCallbacks_ (run, oneLineMode, captureInterval, runFor);
267 Demo_Using_Direct_Capture_On_Instrument_ (run, oneLineMode,
Duration{captureInterval});
271 cerr <<
"Error encountered: " << Characters::ToString (current_exception ()).AsNarrowSDKString () << endl;
272 cerr << cmdLine.GenerateUsage (kAllOptions_).AsNarrowSDKString () << endl;
276 String exceptMsg = Characters::ToString (current_exception ());
277 cerr <<
"Exception - " << exceptMsg.
AsNarrowSDKString () <<
" - terminating..." << endl;
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual string AsNarrowSDKString() const
nonvirtual String StripAll(bool(*removeCharIf)(Character)) const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to Set, and improve that case to ...
An Atom is like a String, except that its much cheaper to copy/store/compare, and the semantics of co...
nonvirtual void Write(const VariantValue &v, const Streams::OutputStream::Ptr< byte > &out) const
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
nonvirtual void SetSignalHandlers(SignalID signal)
static SignalHandlerRegistry & Get()
static const SignalHandler kIGNORED
Wrap any object with Synchronized<> and it can be used similarly to the base type,...
nonvirtual void Wait(Time::DurationSeconds timeout=Time::kInfinity)
Duration is a chrono::duration<double> (=.
nonvirtual bool empty() const
Returns true iff size() == 0.
Create a format-string (see std::wformat_string or Stroika FormatString, or python 'f' strings.
int pid_t
TODO - maybe move this to configuraiotn module???