Zth (libzth)
Loading...
Searching...
No Matches
5_perf.cpp

perf example.

perf example.

/*
* SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <zth>
// To generate VCD output, run this example like:
// ZTH_CONFIG_DO_PERF_EVENT=1 examples/5_perf
//
// Play around by setting ZTH_CONFIG_ENABLE_DEBUG_PRINT=[01] or running the Debug or Release build.
static void do_work(int amount)
{
zth::Timestamp end = zth::Timestamp::now() + 1e-1F * (float)amount;
while(!end.hasPassed())
; // busy wait
}
static void scheduling()
{
// When ZTH_CONFIG_DO_PERF_EVENT is set to 1, the perf API is enabled, which includes
// generating a VCD file. This VCD file shows every fiber in the system and indicates the
// state of every fiber at every instance in time. This allows you to investigate the
// scheduling behavior of fibers. The state of every fiber is indicated in IEEE 1164
// std_logic format, using the following values:
// - U (undefined): the fiber has not been created yet
// - L (low): the fiber has been created, but not initialized (zth::Fiber::New state)
// - 0: the fiber is ready (zth::Fiber::Ready state), but not actually using the CPU
// - 1: the fiber is currently running, which can be only one fiber per zth::Worker.
// - W (weak): the fiber is blocked (zth::Fiber::Waiting) (sleeping/poll/blocking read/etc.)
// - Z (high impedance): the fiber is suspended (zth::Fiber::Suspended)
// - X (unknown): the fiber is dead (zth::Fiber::Dead), but not cleaned up
// - - (don't care): the fiber has been cleaned up, which also indicates that the zth::Fiber
// object has been deleted.
// The VCD file will show for this fiber the following sequence:
// U L 1 W 0 1 X -
//
// The Waiter (usually fiber #3) manages the mnap of below. Open the generated VCD file,
// using gtkwave, for example. Try to understand the relation between fibers in the VCD.
zth::mnap(10);
}
static void measure()
{
// This example measures the duration of a task. There are several helpful functions for
// this. First, take a time stamp. zth::Timestamp::now() is (supposed to be) fast and is
// used everywhere, so go ahead and safe t0.
// perf_mark() allow you to put very efficiently a marker (which must be a C string literal)
// in the VCD log at the current time. We are going to use this to double check our
// measurements in the VCD file. This is like printf()-debugging, but with accurate timing
// information.
zth::perf_mark("do_work(1)");
// Go do some lengthy work.
do_work(1);
// Set another marker.
zth::perf_mark("do_work(1) done");
// Compute time difference. This is not completely fair, as this includes running
// perf_mark() twice.
// Let us format some log string.
zth::string log = zth::format("do_work(1) took %s", dt.str().c_str());
// Put the log string also in the VCD file...
zth::perf_log("%s", log.c_str());
// ...and to stdout.
printf("%s\n", log.c_str());
// Open the generated VCD file. Every fiber has two 'signals': the schedule state of the
// fiber, and a string with logs. The perf_mark() and perf_log() should show up there. Try
// to measure the length between the perf_mark()s in the VCD log string and compare it with
// the measured time interval.
}
static void stack()
{
// Make a snapshot of the current stack backtrace.
// Print it to stdout.
bt.print();
// Make another snapshot.
bt2.printDelta(bt);
}
int main_fiber(int /*argc*/, char** /*argv*/)
{
zth::fiber(scheduling);
zth::fiber(measure);
zth::fiber(stack);
return 0;
}
// For target that do not have filesystem support, the default configuration is to not generate VCD
// output, but you can still call zth::perf_start()/zth::perf_stop()/zth::perf_dump() or
// zth::perf_rum() manually. This allows overriding where to write the dump data to. For example,
// you can write the dump data to a serial port. Afterwards, use zth::perf_vcd() to convert the dump
// data to VCD format.
//
// The dump buffer size is limited. It may influence the performance too much to dump continuously.
// So, you may have some trigger, call zth::perf_start(), and only copy the data to the PC once when
// the buffer is full. This gives you a accurate VCD snapshot of a specific time window, for
// debugging purposes.
Convenient wrapper around struct timespec that contains a time interval.
Definition time.h:82
string str() const
Definition time.h:488
Convenient wrapper around struct timespec that contains an absolute timestamp.
Definition time.h:629
static Timestamp now()
Definition time.h:656
bool hasPassed() const noexcept
Definition time.h:684
int main_fiber(int argc, char **argv)
fiber_type< F >::fiber fiber(F &&f, Args &&... args)
Create and start a new fiber.
Definition async.h:1221
void mnap(long sleepFor_ms)
Sleep for the given amount of milliseconds.
Definition waiter.h:294
void perf_mark(char const *marker, Timestamp const &t=Timestamp()) noexcept
Put a string marker into the perf output.
Definition perf.cpp:394
void perf_log(char const *fmt,...) noexcept
Put a formatted log string into the perf output.
Definition perf.cpp:443
impl::PickBacktrace ::type Backtrace
Save a backtrace.
Definition backtrace.h:168
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
Definition util.h:330
void log(char const *fmt,...)
Logs a given printf()-like formatted string.
Definition util.h:318
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
Definition util.h:498