#!/usr/bin/env dub
/+ dub.sdl:
name "cpu_pmu_counting_group"
platforms "linux"
targetPath "build"
+/
/**
* Grouped scalar counting via `perf_event_open(2)` and PMC multiplexing, pure D.
*
* Two demonstrations of the Linux *counting* path, both over druntime's
* `core.sys.linux.perf_event` (the attr layout + syscall wrapper) — no C shim:
*
* 1. A `PERF_FORMAT_GROUP` group — a `cycles` leader plus `instructions` —
* read in one `read(2)` as `{nr, time_enabled, time_running, value[nr]}`.
* The two values give IPC. Because the events share one group the kernel
* schedules them as a unit, so `time_running == time_enabled` and the
* counts are exact (`scale == 1.0`).
* 2. Deliberate oversubscription: N independent single-event groups (N greater
* than the PMU's general-purpose counters — 6 on Zen 4) opened over one
* workload window so the kernel round-robin-*multiplexes* them. Each event
* then reports `time_running < time_enabled`; perf recovers an estimate by
* scaling `raw * time_enabled / time_running`. This is the accuracy cost
* the grouped path in (1) is designed to avoid.
*
* Companion to docs/research/cpu-pmu/linux-perf-events.md
* § "Scalar counting: groups, `PERF_FORMAT_GROUP`, and multiplexing".
*
* Run with: dub run --single counting-group.d
*
* Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4; 6 core PMCs),
* `/proc/sys/kernel/perf_event_paranoid` = -1, LDC 1.41 druntime
* `core.sys.linux.perf_event`.
*
* Portability: any `perf_event_open` failure (`perf_event_paranoid`, seccomp,
* no PMU, non-Linux) prints a `SKIP:` line and exits 0 so CI stays green on any
* host.
*/
module (module) cpu_pmu_counting_groupGrouped scalar counting via perf_event_open(2) and PMC multiplexing, pure D.
Two demonstrations of the Linux counting path, both over druntime's
core.sys.linux.perf_event (the attr layout + syscall wrapper) — no C shim:
A PERF_FORMAT_GROUP group — a cycles leader plus instructions —
read in one read(2) as {nr, time_enabled, time_running, value[nr]}.
The two values give IPC. Because the events share one group the kernel
schedules them as a unit, so time_running == time_enabled and the
counts are exact (scale == 1.0).
Deliberate oversubscription: N independent single-event groups (N greater
than the PMU's general-purpose counters — 6 on Zen 4) opened over one
workload window so the kernel round-robin-multiplexes them. Each event
then reports time_running < time_enabled; perf recovers an estimate by
scaling raw * time_enabled / time_running. This is the accuracy cost
the grouped path in (1) is designed to avoid.
Companion to docs/research/cpu-pmu/linux-perf-events.md
§ "Scalar counting: groups, PERF_FORMAT_GROUP, and multiplexing".
Run with: dub run --single counting-group.d
Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4; 6 core PMCs),
/proc/sys/kernel/perf_event_paranoid = -1, LDC 1.41 druntime
core.sys.linux.perf_event.
Portability
any perf_event_open failure (perf_event_paranoid, seccomp,
no PMU, non-Linux) prints a SKIP: line and exits 0 so CI stays green on any
host.
cpu_pmu_counting_group;
version (linuxlinux)
{
import (package) corecore.(package) core.syssys.(package) core.sys.linuxlinux.(module) core.sys.linux.perf_eventD header file for perf_event_open system call.
Converted from linux userspace header, comments included.
perf_event;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.unistdD header file for POSIX.
unistd : (alias) cpu_pmu_counting_group.read = long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread, (alias) cpu_pmu_counting_group.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.ioctlD header file for POSIX.
ioctl : (alias) cpu_pmu_counting_group.ioctl = int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogcioctl;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.configD compatible types that correspond to various basic types in associated
C and C++ compilers.
Source
core/stdc/config.d
config : c_ulong;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) cpu_pmu_counting_group.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln, (alias template) cpu_pmu_counting_group.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
/// A hardware event to count, named for the report.
struct (struct) cpu_pmu_counting_group.EvA hardware event to count, named for the report.
Ev
{
(alias) object.string = stringstring (field) string cpu_pmu_counting_group.Ev.namename;
ulong (field) ulong cpu_pmu_counting_group.Ev.configconfig; // a `perf_hw_id`
}
/// Opens one `PERF_TYPE_HARDWARE` event on the calling thread (`pid == 0`),
/// any CPU (`cpu == -1`). `groupFd == -1` makes it a group leader; a leader
/// carries the read format (`PERF_FORMAT_GROUP` when `grouped`, plus the two
/// time fields) and starts `disabled`. Returns the fd, or -1 on failure.
int int cpu_pmu_counting_group.openEvent(ulong config, int groupFd, bool grouped, bool excludeKernel) @trustedOpens one PERF_TYPE_HARDWARE event on the calling thread (pid == 0),
any CPU (cpu == -1). groupFd` == -1` makes it a group leader; a leader
carries the read format (`PERF_FORMAT_GROUP` when grouped``, plus the two
time fields) and starts disabled. Returns the fd, or -1 on failure.
openEvent(ulong (parameter) ulong configconfig, int (parameter) int groupFdgroupFd, bool (parameter) bool groupedgrouped, bool (parameter) bool excludeKernelexcludeKernel) @trusted
{
(struct) core.sys.linux.perf_event.perf_event_attrHardware event_id to monitor via a performance monitoring event:
@sample_max_stack: Max number of frame pointers in a callchain,
should be < /proc/sys/kernel/perf_event_max_stack
perf_event_attr (local variable) core.sys.linux.perf_event.perf_event_attr attrattr;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.(field) uint core.sys.linux.perf_event.perf_event_attr.sizeSize of the attr structure, for fwd/bwd compat.
size = (struct) core.sys.linux.perf_event.perf_event_attrHardware event_id to monitor via a performance monitoring event:
@sample_max_stack: Max number of frame pointers in a callchain,
should be < /proc/sys/kernel/perf_event_max_stack
perf_event_attr.(constant) ulong core.sys.linux.perf_event.perf_event_attr.sizeof = 112LUsizeof;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.(field) uint core.sys.linux.perf_event.perf_event_attr.typeMajor type: hardware/software/tracepoint/etc.
type = (enum) core.sys.linux.perf_event.perf_type_idattr.type
perf_type_id.(enum value) core.sys.linux.perf_event.perf_type_id.PERF_TYPE_HARDWARE = 0PERF_TYPE_HARDWARE;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.(field) ulong core.sys.linux.perf_event.perf_event_attr.configType specific configuration information.
config = (parameter) ulong configconfig;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.void core.sys.linux.perf_event.perf_event_attr.exclude_hv(ulong v) pure nothrow @nogc @property @safeexclude_hv = 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.void core.sys.linux.perf_event.perf_event_attr.exclude_kernel(ulong v) pure nothrow @nogc @property @safeexclude_kernel = (parameter) bool excludeKernelexcludeKernel ? 1 : 0;
const (local variable) const(bool) isLeaderisLeader = (parameter) int groupFdgroupFd < 0;
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.void core.sys.linux.perf_event.perf_event_attr.disabled(ulong v) pure nothrow @nogc @property @safedisabled = (local variable) const(bool) isLeaderisLeader ? 1 : 0; // enabling the leader enables the group
if ((local variable) const(bool) isLeaderisLeader)
{
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.(field) ulong core.sys.linux.perf_event.perf_event_attr.read_formatread_format = (enum) core.sys.linux.perf_event.perf_event_read_formatThe format of the data returned by read() on a perf event fd,
as specified by attr.read_format:
struct read_format {
{ u64 value;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 id; } && PERF_FORMAT_ID
} && !PERF_FORMAT_GROUP
{ u64 nr;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 value;
{ u64 id; } && PERF_FORMAT_ID
} cntr[nr];
} && PERF_FORMAT_GROUP
};
perf_event_read_format.(enum value) core.sys.linux.perf_event.perf_event_read_format.PERF_FORMAT_TOTAL_TIME_ENABLED = 1uPERF_FORMAT_TOTAL_TIME_ENABLED
| (enum) core.sys.linux.perf_event.perf_event_read_formatThe format of the data returned by read() on a perf event fd,
as specified by attr.read_format:
struct read_format {
{ u64 value;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 id; } && PERF_FORMAT_ID
} && !PERF_FORMAT_GROUP
{ u64 nr;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 value;
{ u64 id; } && PERF_FORMAT_ID
} cntr[nr];
} && PERF_FORMAT_GROUP
};
perf_event_read_format.(enum value) core.sys.linux.perf_event.perf_event_read_format.PERF_FORMAT_TOTAL_TIME_RUNNING = 2uPERF_FORMAT_TOTAL_TIME_RUNNING;
if ((parameter) bool groupedgrouped)
(local variable) core.sys.linux.perf_event.perf_event_attr attrattr.(field) ulong core.sys.linux.perf_event.perf_event_attr.read_formatread_format |= (enum) core.sys.linux.perf_event.perf_event_read_formatThe format of the data returned by read() on a perf event fd,
as specified by attr.read_format:
struct read_format {
{ u64 value;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 id; } && PERF_FORMAT_ID
} && !PERF_FORMAT_GROUP
{ u64 nr;
{ u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
{ u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
{ u64 value;
{ u64 id; } && PERF_FORMAT_ID
} cntr[nr];
} && PERF_FORMAT_GROUP
};
perf_event_read_format.(enum value) core.sys.linux.perf_event.perf_event_read_format.PERF_FORMAT_GROUP = 8uPERF_FORMAT_GROUP;
}
return cast(int) long core.sys.linux.perf_event.perf_event_open(core.sys.linux.perf_event.perf_event_attr* hw_event, int pid, int cpu, int group_fd, ulong flags) nothrow @nogcperf_event_open(&(local variable) core.sys.linux.perf_event.perf_event_attr attrattr, 0, -1, (parameter) int groupFdgroupFd, 0);
}
void void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl(int (parameter) int fdfd, uint (parameter) uint requestrequest, bool (parameter) bool wholeGroupwholeGroup) @trusted
{
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogcioctl((parameter) int fdfd, cast(c_ulong) (parameter) uint requestrequest,
(parameter) bool wholeGroupwholeGroup ? (enum) core.sys.linux.perf_event.perf_event_ioc_flagsperf_event_ioc_flags.(enum value) core.sys.linux.perf_event.perf_event_ioc_flags.PERF_IOC_FLAG_GROUP = 1uPERF_IOC_FLAG_GROUP : 0);
}
long long cpu_pmu_counting_group.readN(int fd, ulong[] buf) @trustedreadN(int (parameter) int fdfd, ulong[] (parameter) ulong[] bufbuf) @trusted => long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread((parameter) int fdfd, (parameter) ulong[] bufbuf.(field) ulong* ulong[].ptrptr, (parameter) ulong[] bufbuf.(field) ulong ulong[].lengthlength * ulong.(constant) ulong ulong.sizeof = 8LUsizeof);
/// A fixed amount of work: multiply-shift-xor mixing, enough retired
/// instructions that counter noise is negligible. `__gshared` sink defeats
/// dead-code elimination.
__gshared ulong (__gshared global) ulong cpu_pmu_counting_group.sinkA fixed amount of work: multiply-shift-xor mixing, enough retired
instructions that counter noise is negligible. __gshared sink defeats
dead-code elimination.
sink;
void void cpu_pmu_counting_group.workload()workload()
{
ulong (local variable) ulong accacc = 0x9E3779B97F4A7C15UL;
foreach ((local variable) ulong ii; 0 .. 3_000_000UL)
(local variable) ulong accacc = ((local variable) ulong accacc + (local variable) ulong ii) * 2654435761UL ^ ((local variable) ulong accacc >> 13);
(__gshared global) ulong cpu_pmu_counting_group.sinkA fixed amount of work: multiply-shift-xor mixing, enough retired
instructions that counter noise is negligible. __gshared sink defeats
dead-code elimination.
sink += (local variable) ulong accacc;
}
int int cpu_pmu_counting_group.run()run()
{
// ---- Demo 1: a fitting group → exact IPC, scale == 1 --------------
// Probe permission once: prefer kernel+user, fall back to user-only.
bool (local variable) bool excludeKernelexcludeKernel = false;
int (local variable) int leaderleader = int cpu_pmu_counting_group.openEvent(ulong config, int groupFd, bool grouped, bool excludeKernel) @trustedOpens one PERF_TYPE_HARDWARE event on the calling thread (pid == 0),
any CPU (cpu == -1). groupFd` == -1` makes it a group leader; a leader
carries the read format (`PERF_FORMAT_GROUP` when grouped``, plus the two
time fields) and starts disabled. Returns the fd, or -1 on failure.
openEvent((enum) core.sys.linux.perf_event.perf_hw_idGeneralized performance event event_id types, used by the
attr.event_id parameter of the sys_perf_event_open()
syscall:
perf_hw_id.(enum value) core.sys.linux.perf_event.perf_hw_id.PERF_COUNT_HW_CPU_CYCLES = 0PERF_COUNT_HW_CPU_CYCLES, -1, true, false);
if ((local variable) int leaderleader < 0)
{
(local variable) bool excludeKernelexcludeKernel = true;
(local variable) int leaderleader = int cpu_pmu_counting_group.openEvent(ulong config, int groupFd, bool grouped, bool excludeKernel) @trustedOpens one PERF_TYPE_HARDWARE event on the calling thread (pid == 0),
any CPU (cpu == -1). groupFd` == -1` makes it a group leader; a leader
carries the read format (`PERF_FORMAT_GROUP` when grouped``, plus the two
time fields) and starts disabled. Returns the fd, or -1 on failure.
openEvent((enum) core.sys.linux.perf_event.perf_hw_idGeneralized performance event event_id types, used by the
attr.event_id parameter of the sys_perf_event_open()
syscall:
perf_hw_id.(enum value) core.sys.linux.perf_event.perf_hw_id.PERF_COUNT_HW_CPU_CYCLES = 0PERF_COUNT_HW_CPU_CYCLES, -1, true, true);
}
if ((local variable) int leaderleader < 0)
{
void std.stdio.writefln!char(in char[] fmt) @safeEquivalent to writef(fmt, args, '\n').
writefln("SKIP: perf_event_open failed — perf_event_paranoid too high, "
~ "seccomp, or no PMU on this host");
return 0;
}
const (local variable) const(int) insnsinsns = int cpu_pmu_counting_group.openEvent(ulong config, int groupFd, bool grouped, bool excludeKernel) @trustedOpens one PERF_TYPE_HARDWARE event on the calling thread (pid == 0),
any CPU (cpu == -1). groupFd` == -1` makes it a group leader; a leader
carries the read format (`PERF_FORMAT_GROUP` when grouped``, plus the two
time fields) and starts disabled. Returns the fd, or -1 on failure.
openEvent((enum) core.sys.linux.perf_event.perf_hw_idGeneralized performance event event_id types, used by the
attr.event_id parameter of the sys_perf_event_open()
syscall:
perf_hw_id.(enum value) core.sys.linux.perf_event.perf_hw_id.PERF_COUNT_HW_INSTRUCTIONS = 1PERF_COUNT_HW_INSTRUCTIONS, (local variable) int leaderleader, true, (local variable) bool excludeKernelexcludeKernel);
if ((local variable) const(int) insnsinsns < 0)
{
void std.stdio.writefln!char(in char[] fmt) @safeEquivalent to writef(fmt, args, '\n').
writefln("SKIP: could not add instructions to the group (errno on member open)");
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) int leaderleader);
return 0;
}
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int leaderleader, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219PERF_EVENT_IOC_RESET, true);
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int leaderleader, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_ENABLE = 9216Ioctls that can be done on a perf event fd:
PERF_EVENT_IOC_ENABLE, true);
void cpu_pmu_counting_group.workload()workload();
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int leaderleader, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217PERF_EVENT_IOC_DISABLE, true);
// Group read: nr, time_enabled, time_running, value[cycles], value[insns].
ulong[5] (local variable) ulong[5] gg;
const (local variable) const(long) gotgot = long cpu_pmu_counting_group.readN(int fd, ulong[] buf) @trustedreadN((local variable) int leaderleader, (local variable) ulong[5] gg[]);
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) const(int) insnsinsns);
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) int leaderleader);
if ((local variable) const(long) gotgot < cast(long)(5 * ulong.(constant) ulong ulong.sizeof = 8LUsizeof))
{
void std.stdio.writefln!(char, const(long))(in char[] fmt, const(long) __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln("SKIP: short group read (%d bytes) — counters unavailable", (local variable) const(long) gotgot);
return 0;
}
const (local variable) const(ulong) nrnr = (local variable) ulong[5] gg[0], (local variable) const(ulong) enabledenabled = (local variable) ulong[5] gg[1], (local variable) const(ulong) runningrunning = (local variable) ulong[5] gg[2], (local variable) const(ulong) cyccyc = (local variable) ulong[5] gg[3], (local variable) const(ulong) insins = (local variable) ulong[5] gg[4];
const (local variable) const(double) groupScalegroupScale = (local variable) const(ulong) runningrunning > 0 ? cast(double) (local variable) const(ulong) enabledenabled / (local variable) const(ulong) runningrunning : double.(constant) double double.nan = nannan;
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln("== Demo 1: fitting group (%s) ==", (local variable) bool excludeKernelexcludeKernel ? "user-only" : "kernel+user");
void std.stdio.writefln!(char, const(ulong), const(ulong), const(ulong), const(double))(in char[] fmt, const(ulong) __param_1, const(ulong) __param_2, const(ulong) __param_3, const(double) __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln(" nr=%d time_enabled=%d ns time_running=%d ns scale=%.4f",
(local variable) const(ulong) nrnr, (local variable) const(ulong) enabledenabled, (local variable) const(ulong) runningrunning, (local variable) const(double) groupScalegroupScale);
void std.stdio.writefln!(char, const(ulong), const(ulong), double)(in char[] fmt, const(ulong) __param_1, const(ulong) __param_2, double __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln(" cycles=%d instructions=%d IPC=%.3f", (local variable) const(ulong) cyccyc, (local variable) const(ulong) insins,
(local variable) const(ulong) cyccyc > 0 ? cast(double) (local variable) const(ulong) insins / (local variable) const(ulong) cyccyc : double.(constant) double double.nan = nannan);
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" (grouped events co-schedule → time_running == time_enabled → exact)");
// ---- Demo 2: oversubscribe the PMCs → multiplexing scaling --------
// N separate single-event groups counting the SAME event over ONE
// workload window. With N > general-purpose counters the kernel rotates
// them, so each sees only part of the window (running < enabled).
enum (constant) int cpu_pmu_counting_group.run.N = 10N = 10;
int[(constant) int cpu_pmu_counting_group.run.N = 10N] (local variable) int[10] fdsfds = -1;
int (local variable) int openedopened = 0;
foreach (ref (parameter) int fdfd; (local variable) int[10] fdsfds)
{
(local variable) int fdfd = int cpu_pmu_counting_group.openEvent(ulong config, int groupFd, bool grouped, bool excludeKernel) @trustedOpens one PERF_TYPE_HARDWARE event on the calling thread (pid == 0),
any CPU (cpu == -1). groupFd` == -1` makes it a group leader; a leader
carries the read format (`PERF_FORMAT_GROUP` when grouped``, plus the two
time fields) and starts disabled. Returns the fd, or -1 on failure.
openEvent((enum) core.sys.linux.perf_event.perf_hw_idGeneralized performance event event_id types, used by the
attr.event_id parameter of the sys_perf_event_open()
syscall:
perf_hw_id.(enum value) core.sys.linux.perf_event.perf_hw_id.PERF_COUNT_HW_INSTRUCTIONS = 1PERF_COUNT_HW_INSTRUCTIONS, -1, false, (local variable) bool excludeKernelexcludeKernel);
if ((local variable) int fdfd >= 0)
(local variable) int openedopened++;
}
if ((local variable) int openedopened == 0)
{
void std.stdio.writefln!char(in char[] fmt) @safeEquivalent to writef(fmt, args, '\n').
writefln("SKIP: oversubscription demo could not open any event");
return 0;
}
foreach ((parameter) int fdfd; (local variable) int[10] fdsfds)
if ((local variable) int fdfd >= 0)
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int fdfd, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219PERF_EVENT_IOC_RESET, false);
foreach ((parameter) int fdfd; (local variable) int[10] fdsfds)
if ((local variable) int fdfd >= 0)
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int fdfd, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_ENABLE = 9216Ioctls that can be done on a perf event fd:
PERF_EVENT_IOC_ENABLE, false);
void cpu_pmu_counting_group.workload()workload();
foreach ((parameter) int fdfd; (local variable) int[10] fdsfds)
if ((local variable) int fdfd >= 0)
void cpu_pmu_counting_group.ctl(int fd, uint request, bool wholeGroup) @trustedctl((local variable) int fdfd, (constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217PERF_EVENT_IOC_DISABLE, false);
void std.stdio.writefln!(char, int, int)(in char[] fmt, int __param_1, int __param_2) @safeEquivalent to writef(fmt, args, '\n').
writefln("\n== Demo 2: %d instruction counters, %d general-purpose PMCs ==", (local variable) int openedopened, 6);
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" ev raw_running_count enabled_ns running_ns scale estimate");
bool (local variable) bool sawMuxsawMux = false;
foreach ((parameter) ulong ii, (parameter) int fdfd; (local variable) int[10] fdsfds)
{
if ((local variable) int fdfd < 0)
continue;
ulong[3] (local variable) ulong[3] ss; // value, time_enabled, time_running
if (long cpu_pmu_counting_group.readN(int fd, ulong[] buf) @trustedreadN((local variable) int fdfd, (local variable) ulong[3] ss[]) >= cast(long)(3 * ulong.(constant) ulong ulong.sizeof = 8LUsizeof))
{
if ((local variable) ulong[3] ss[2] < (local variable) ulong[3] ss[1])
(local variable) bool sawMuxsawMux = true;
if ((local variable) ulong[3] ss[2] == 0)
// Enabled but never got a counter this window: the kernel's
// `<not counted>` state — a zero read is not a measurement.
void std.stdio.writefln!(char, ulong, ulong, ulong, ulong)(in char[] fmt, ulong __param_1, ulong __param_2, ulong __param_3, ulong __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln(" %2d %18d %12d %12d — <not scheduled>",
(local variable) ulong ii, (local variable) ulong[3] ss[0], (local variable) ulong[3] ss[1], (local variable) ulong[3] ss[2]);
else
{
const (local variable) const(double) scsc = cast(double) (local variable) ulong[3] ss[1] / (local variable) ulong[3] ss[2];
void std.stdio.writefln!(char, ulong, ulong, ulong, ulong, const(double), ulong)(in char[] fmt, ulong __param_1, ulong __param_2, ulong __param_3, ulong __param_4, const(double) __param_5, ulong __param_6) @safeEquivalent to writef(fmt, args, '\n').
writefln(" %2d %18d %12d %12d %5.2f %d",
(local variable) ulong ii, (local variable) ulong[3] ss[0], (local variable) ulong[3] ss[1], (local variable) ulong[3] ss[2], (local variable) const(double) scsc, cast(ulong)((local variable) ulong[3] ss[0] * (local variable) const(double) scsc));
}
}
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) int fdfd);
}
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln(" multiplexing observed: %s", (local variable) bool sawMuxsawMux ? "yes (time_running < time_enabled — "
~ "raw counts are partial; the scaled estimate recovers the whole-window value)"
: "no (this PMU has enough counters to co-schedule all events)");
return 0;
}
}
int int D main()main()
{
version (linuxlinux)
return int cpu_pmu_counting_group.run()run();
else
{
import std.stdio : writefln;
writefln("SKIP: perf_event_open is Linux-only");
return 0;
}
}