pfm4-name-roundtrip.dhover×348all
#!/usr/bin/env dub
/+ dub.sdl:
    name "cpu_pmu_pfm4_name_roundtrip"
    platforms "linux"
    libs "pfm"
    targetPath "build"
+/
/**
 * libpfm4 human-name → `perf_event_attr.{type,config}` round trip, then live count.
 *
 * The *event-naming & encoding* concern of the analysis spine, exercised end to
 * end on this host. libpfm4 is the name-resolution layer under `perf`, PAPI, and
 * many profilers: it owns per-microarchitecture event tables and turns a symbolic
 * string into the `type`/`config`/`exclude_*` fields the `perf_event_open(2)` ABI
 * expects. This probe:
 *
 *   1. `pfm_get_os_event_encoding(str, …, PFM_OS_PERF_EVENT, &arg)` with `arg.attr`
 *      pointing at druntime's `perf_event_attr` — the same struct `perf_event_open`
 *      consumes — so libpfm fills it directly (no hand-built encodings).
 *   2. Encodes four names spanning the naming layers and prints the resulting
 *      `type`/`config` hex plus the fully-qualified string libpfm echoes back:
 *        - `PERF_COUNT_HW_CPU_CYCLES` — a *generic* perf name → `PERF_TYPE_HARDWARE`
 *          (type 0), config 0: the OS-abstracted event, portable across vendors.
 *        - `RETIRED_INSTRUCTIONS` — a *Zen 4-specific* name from libpfm's
 *          `amd64_fam19h_zen4` table → `PERF_TYPE_RAW` (type 4), config `0xc0`
 *          (the raw AMD PMC event-select), proving the per-µarch table is what
 *          supplies the bits.
 *        - `RETIRED_SSE_AVX_FLOPS:ADD_SUB_FLOPS` — a name carrying a *unit mask* →
 *          the umask lands in config bits [15:8] (`0x103`), showing libpfm's
 *          `event:umask` grammar.
 *        - `RETIRED_INSTRUCTIONS:u` — a name carrying a *modifier* → config is
 *          unchanged (`0xc0`) but `attr.exclude_kernel` is set: user/kernel/hv
 *          filtering is lifted OUT of the raw config into the perf_event ABI's
 *          `exclude_*` fields (`pfm_amd64_get_perf_encoding` zeroes the OS/USR
 *          MSR bits; the common perf layer sets the attr fields). This split is
 *          the whole reason `PFM_OS_PERF_EVENT` exists.
 *   3. `perf_event_open`s each encoding on the calling thread and counts a fixed
 *      workload window (integer mixing + scalar SSE FP), proving the encodings
 *      are *live*, not just plausible.
 *
 * Auto-detect caveat (source-verified, load-bearing): stock **libpfm 4.13.0**
 * (the current nixpkgs build) does NOT auto-detect this CPU's core PMU. Its
 * family-19h detect (`lib/pfmlib_amd64.c`) maps only `model == 0x11` to Zen 4, so
 * the Ryzen 9 7940HX (family 25/`0x19`, model **0x61**, Dragon Range) matches no
 * branch, `revision` stays `PFM_PMU_NONE`, and only the software `perf`/`perf_raw`
 * PMUs activate — a bare `pfm_get_os_event_encoding("RETIRED_INSTRUCTIONS", …)`
 * then returns `PFM_ERR_NOTFOUND` (-4). libpfm git HEAD fixes this (`model >= 0x60`).
 * To stay robust we (a) derive the correct table name from `/proc/cpuinfo`
 * ourselves — exactly what a fixed `detect()` would pick — and address events with
 * the explicit `amd64_fam19h_zen4::` prefix, and (b) set `LIBPFM_ENCODE_INACTIVE=1`
 * before `pfm_initialize`, which places even un-detected tables on the searchable
 * list. The lesson for a backend: do not trust libpfm auto-detect on very recent
 * silicon — force the PMU by a name you resolve from CPUID, or require a new libpfm.
 *
 * Companion to docs/research/cpu-pmu/event-naming.md
 *   § "libpfm4: the name→encoding pipeline" and § "The OS-layer split".
 *
 * Run with (nixpkgs libpfm has no pkg-config .pc, and `nix shell` does not run
 * setup hooks, so feed its lib dir through LIBRARY_PATH/LD_LIBRARY_PATH):
 *
 *   P=$(nix eval --raw nixpkgs#libpfm)/lib; \
 *   env LIBRARY_PATH="$P:$LIBRARY_PATH" LD_LIBRARY_PATH="$P:$LD_LIBRARY_PATH" \
 *       dub run --single pfm4-name-roundtrip.d
 *
 * (Adding `libpfm` to the flake devShell's buildInputs would let a plain
 * `dub run --single` resolve `libs "pfm"` via NIX_LDFLAGS — the intended CI path.)
 *
 * Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4, family 25 /
 * model 0x61), `/proc/sys/kernel/perf_event_paranoid` = -1, libpfm 4.13.0
 * (nixpkgs), LDC 1.41 druntime `core.sys.linux.perf_event`.
 *
 * Portability: on a host without libpfm the build fails to link (libpfm is a
 * link-time dependency, like `libdw` in the sibling probes). At runtime, a raised
 * `perf_event_paranoid`, a non-AMD CPU, or any `perf_event_open` failure prints a
 * `SKIP:` line and exits 0 so CI stays green on any host.
 */
module 
(module) cpu_pmu_pfm4_name_roundtrip

libpfm4 human-name → perf_event_attr.{type,config} round trip, then live count.

The event-naming & encoding concern of the analysis spine, exercised end to end on this host. libpfm4 is the name-resolution layer under perf, PAPI, and many profilers: it owns per-microarchitecture event tables and turns a symbolic string into the type/config/exclude_* fields the perf_event_open(2) ABI expects. This probe:

  1. pfm_get_os_event_encoding(str, …, PFM_OS_PERF_EVENT, &arg) with arg.attr pointing at druntime's perf_event_attr — the same struct perf_event_open consumes — so libpfm fills it directly (no hand-built encodings).

  2. Encodes four names spanning the naming layers and prints the resulting type/config hex plus the fully-qualified string libpfm echoes back:

    • PERF_COUNT_HW_CPU_CYCLES — a generic perf name → PERF_TYPE_HARDWARE (type 0), config 0: the OS-abstracted event, portable across vendors.

    • RETIRED_INSTRUCTIONS — a Zen 4-specific name from libpfm's amd64_fam19h_zen4 table → PERF_TYPE_RAW (type 4), config 0xc0 (the raw AMD PMC event-select), proving the per-µarch table is what supplies the bits.

    • RETIRED_SSE_AVX_FLOPS:ADD_SUB_FLOPS — a name carrying a unit mask → the umask lands in config bits 15:8 (0x103), showing libpfm's event:umask grammar.

    • RETIRED_INSTRUCTIONS:u — a name carrying a modifier → config is unchanged (0xc0) but attr.exclude_kernel is set: user/kernel/hv filtering is lifted OUT of the raw config into the perf_event ABI's exclude_* fields (pfm_amd64_get_perf_encoding zeroes the OS/USR MSR bits; the common perf layer sets the attr fields). This split is the whole reason PFM_OS_PERF_EVENT exists.

  3. perf_event_opens each encoding on the calling thread and counts a fixed workload window (integer mixing + scalar SSE FP), proving the encodings are live, not just plausible.

Auto-detect caveat (source-verified, load-bearing): stock libpfm 4.13.0 (the current nixpkgs build) does NOT auto-detect this CPU's core PMU. Its family-19h detect (lib/pfmlib_amd64.c) maps only model == 0x11 to Zen 4, so the Ryzen 9 7940HX (family 25/0x19, model 0x61, Dragon Range) matches no branch, revision stays PFM_PMU_NONE, and only the software perf/perf_raw PMUs activate — a bare pfm_get_os_event_encoding("RETIRED_INSTRUCTIONS", …) then returns PFM_ERR_NOTFOUND (-4). libpfm git HEAD fixes this (model >= 0x60). To stay robust we (a) derive the correct table name from /proc/cpuinfo ourselves — exactly what a fixed detect() would pick — and address events with the explicit amd64_fam19h_zen4:: prefix, and (b) set LIBPFM_ENCODE_INACTIVE=1 before pfm_initialize, which places even un-detected tables on the searchable list. The lesson for a backend: do not trust libpfm auto-detect on very recent silicon — force the PMU by a name you resolve from CPUID, or require a new libpfm.

Companion to docs/research/cpu-pmu/event-naming.md § "libpfm4: the name→encoding pipeline" and § "The OS-layer split".

Run with (nixpkgs libpfm has no pkg-config .pc, and nix shell does not run setup hooks, so feed its lib dir through LIBRARY_PATH/LD_LIBRARY_PATH):

P=eval --raw nixpkgs#libpfm/lib;
env LIBRARY_PATH="$P:$LIBRARY_PATH" LD_LIBRARY_PATH="$P:$LD_LIBRARY_PATH"
dub run --single pfm4-name-roundtrip.d

(Adding libpfm to the flake devShell's buildInputs would let a plain dub run --single resolve libs "pfm" via NIX_LDFLAGS — the intended CI path.)

Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4, family 25 / model 0x61), /proc/sys/kernel/perf_event_paranoid = -1, libpfm 4.13.0 (nixpkgs), LDC 1.41 druntime core.sys.linux.perf_event.

Portability

on a host without libpfm the build fails to link (libpfm is a link-time dependency, like libdw in the sibling probes). At runtime, a raised perf_event_paranoid, a non-AMD CPU, or any perf_event_open failure prints a SKIP: line and exits 0 so CI stays green on any host.

cpu_pmu_pfm4_name_roundtrip
;
version (
linux
linux
)
{ import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.linux
linux
.
(module) core.sys.linux.perf_event

D header file for perf_event_open system call.

Converted from linux userspace header, comments included.

@authorsMax Haughton
perf_event
:
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware 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
,
(alias) cpu_pmu_pfm4_name_roundtrip.perf_event_open = 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 @nogc
perf_event_open
,
(enum) core.sys.linux.perf_event.perf_type_id

attr.type

perf_type_id
,
(enum) core.sys.linux.perf_event.perf_event_read_format

The 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
,
(alias constant) cpu_pmu_pfm4_name_roundtrip.PERF_EVENT_IOC_RESET = int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219
PERF_EVENT_IOC_RESET
,
(alias constant) cpu_pmu_pfm4_name_roundtrip.PERF_EVENT_IOC_ENABLE = int core.sys.linux.perf_event.PERF_EVENT_IOC_ENABLE = 9216

Ioctls that can be done on a perf event fd:

PERF_EVENT_IOC_ENABLE
,
(alias constant) cpu_pmu_pfm4_name_roundtrip.PERF_EVENT_IOC_DISABLE = int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217
PERF_EVENT_IOC_DISABLE
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.unistd

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly@standardsThe Open Group Base Specifications Issue 8, IEEE Std 1003.1, 2024 Edition
unistd
:
(alias) cpu_pmu_pfm4_name_roundtrip.read = long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogc
read
,
(alias) cpu_pmu_pfm4_name_roundtrip.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(package) core.sys.posix.sys
sys
.
(module) core.sys.posix.sys.ioctl

D header file for POSIX.

@copyrightCopyright Alex Rønne Petersen 2011 - 2012.@licenseBoost License 1.0.@authorsAlex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
ioctl
:
(alias) cpu_pmu_pfm4_name_roundtrip.ioctl = int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.stdlib

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
stdlib
:
(alias) cpu_pmu_pfm4_name_roundtrip.setenv = int core.sys.posix.stdlib.setenv(scope const(char*), scope const(char*), int) nothrow @nogc
setenv
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.config

D compatible types that correspond to various basic types in associated C and C++ compilers.

Source

core/stdc/config.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
config
: c_ulong;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.string

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h

Source

core/stdc/string.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
string
:
(alias) cpu_pmu_pfm4_name_roundtrip.strlen = ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
;
import
(package) std
std
.
(module) std.stdio
Category 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:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) cpu_pmu_pfm4_name_roundtrip.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) cpu_pmu_pfm4_name_roundtrip.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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
import
(package) std
std
.
(module) std.string

String handling functions.

Category Functions
Searching
column
indexOf
indexOfAny
indexOfNeither
lastIndexOf
lastIndexOfAny
lastIndexOfNeither
Comparison
isNumeric
Mutation
capitalize
Pruning and Filling
center
chomp
chompPrefix
chop
detabber
detab
entab
entabber
leftJustify
outdent
rightJustify
strip
stripLeft
stripRight
wrap
Substitution
abbrev
soundex
soundexer
succ
tr
translate
Miscellaneous
assumeUTF
fromStringz
lineSplitter
representation
splitLines
toStringz
Objects of types string, wstring, and dstring are value types
and cannot be mutated element-by-element. For using mutation during building
strings, use char[], wchar[], or dchar[]. The xxxstring
types are preferable because they don't exhibit undesired aliasing, thus
making code more robust.

The following functions are publicly imported:

Module Functions
Publicly imported functions
std.algorithm
cmp, std,algorithm,comparison
count, std,algorithm,searching
endsWith, std,algorithm,searching
startsWith, std,algorithm,searching
std.array
join, std,array
replace, std,array
replaceInPlace, std,array
split, std,array
empty, std,array
std.format
format, std,format
sformat, std,format
std.uni
icmp, std,uni
toLower, std,uni
toLowerInPlace, std,uni
toUpper, std,uni
toUpperInPlace, std,uni
There is a rich set of functions for string handling defined in other modules.
Functions related to Unicode and ASCII are found in std.uni
and std.ascii, respectively. Other functions that have a
wider generality than just strings can be found in std.algorithm
and std.range.

Source

std/string.d

@seestd.algorithm and std.range for generic range algorithms , std.ascii for functions that work with ASCII strings , std.uni for functions that work with unicode strings@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis, and David L. 'SpottedTiger' Davis
string
:
(alias template) cpu_pmu_pfm4_name_roundtrip.lineSplitter = std.string.lineSplitter(Flag keepTerm = No.keepTerminator, Range)(Range r) if (hasSlicing!Range && hasLength!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range)

Split an array or slicable range of characters into a range of lines using '\r', '\n', '\v', '\f', "\r\n", lineSep, paraSep and '\u0085' (NEL) as delimiters. If keepTerm is set to Yes.keepTerminator, then the delimiter is included in the slices returned.

Does not throw on invalid UTF; such is simply passed unchanged to the output.

Adheres to Unicode 7.0.

Does not allocate memory.

@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
,
(alias template) cpu_pmu_pfm4_name_roundtrip.startsWith = std.algorithm.searching.startsWith(alias pred = (a, b) => a == b, Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
,
(alias template) cpu_pmu_pfm4_name_roundtrip.strip = std.string.strip(Range)(Range str) if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range))

Strips both leading and trailing whitespace (as defined by isWhite) or as specified in the second argument.

@paramstr string or random access range of characters@paramchars string of characters to be stripped@paramleftChars string of leading characters to be stripped@paramrightChars string of trailing characters to be stripped@returnsslice of str stripped of leading and trailing whitespace or characters as specified in the second argument.@seeGeneric stripping on ranges: strip
strip
;
// ---- libpfm4 (extern(C), verified against $REPOS/c/libpfm4@6870a9f0 // include/perfmon/pfmlib.h + pfmlib_perf_event.h) -------------------- enum
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_OS_PERF_EVENT = 1
PFM_OS_PERF_EVENT
= 1; // pfm_os_t: perf_events attribute subset + PMU
enum
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_PLM0 = 1
PFM_PLM0
= 0x01; // priv level 0 (kernel)
enum
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_PLM3 = 8
PFM_PLM3
= 0x08; // priv level 3/2/1 (user)
enum
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_SUCCESS = 0
PFM_SUCCESS
= 0;
/// `pfm_perf_encode_arg_t` (pfmlib_perf_event.h): 40 bytes on LP64. struct
(struct) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t

pfm_perf_encode_arg_t (pfmlib_perf_event.h): 40 bytes on LP64.

pfm_perf_encode_arg_t
{
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware 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
*
(field) core.sys.linux.perf_event.perf_event_attr* cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.attr
attr
; // in/out: the struct libpfm fills
char**
(field) char** cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.fstr
fstr
; // out: fully-qualified event string
(alias) object.size_t = ulong
size_t
(field) ulong cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.size
size
; // sizeof(*this) — libpfm ABI-checks this
int
(field) int cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.idx
idx
; // out: opaque event id
int
(field) int cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.cpu
cpu
; // out: cpu to program, -1 = unset
int
(field) int cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.flags
flags
; // out: perf_event_open flags
int
(field) int cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.pad0
pad0
;
} extern (C) int
int cpu_pmu_pfm4_name_roundtrip.pfm_initialize()
pfm_initialize
();
extern (C) int
int cpu_pmu_pfm4_name_roundtrip.pfm_get_version()
pfm_get_version
();
extern (C) const(char)*
const(char)* cpu_pmu_pfm4_name_roundtrip.pfm_strerror(int)
pfm_strerror
(int);
extern (C) int
int cpu_pmu_pfm4_name_roundtrip.pfm_get_os_event_encoding(const(char)*, int, int, void*)
pfm_get_os_event_encoding
(const(char)*, int, int, void*);
(alias) object.string = string
string
string cpu_pmu_pfm4_name_roundtrip.cstr(const(char)* p) @trusted
cstr
(const(char)*
(parameter) const(char)* p
p
) @trusted =>
(parameter) const(char)* p
p
is null ? "(null)" : cast(
(alias) object.string = string
string
)
(parameter) const(char)* p
p
[0 ..
ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
(
(parameter) const(char)* p
p
)];
/// Result of one encode. struct
(struct) cpu_pmu_pfm4_name_roundtrip.Encoded

Result of one encode.

Encoded
{ bool
(field) bool cpu_pmu_pfm4_name_roundtrip.Encoded.ok
ok
;
int
(field) int cpu_pmu_pfm4_name_roundtrip.Encoded.err
err
; // pfm_err_t when !ok
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware 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
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
;
(alias) object.string = string
string
(field) string cpu_pmu_pfm4_name_roundtrip.Encoded.fstr
fstr
;
} /// Name → `perf_event_attr` via libpfm. Counting at both priv levels /// (PLM0|PLM3) is the default; per-name `:u`/`:k` modifiers override it.
(struct) cpu_pmu_pfm4_name_roundtrip.Encoded

Result of one encode.

Encoded
cpu_pmu_pfm4_name_roundtrip.Encoded cpu_pmu_pfm4_name_roundtrip.encode(string name) @trusted

Name → perf_event_attr via libpfm. Counting at both priv levels (PLM0|PLM3) is the default; per-name :u/:k modifiers override it.

encode
(
(alias) object.string = string
string
(parameter) string name
name
) @trusted
{
(struct) cpu_pmu_pfm4_name_roundtrip.Encoded

Result of one encode.

Encoded
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
;
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.size

Size of the attr structure, for fwd/bwd compat.

size
=
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware 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 = 112LU
sizeof
;
char*
(local variable) char* fstr
fstr
;
(struct) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t

pfm_perf_encode_arg_t (pfmlib_perf_event.h): 40 bytes on LP64.

pfm_perf_encode_arg_t
(local variable) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t arg
arg
;
(local variable) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t arg
arg
.
(field) core.sys.linux.perf_event.perf_event_attr* cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.attr
attr
= &
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
;
(local variable) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t arg
arg
.
(field) char** cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.fstr
fstr
= &
(local variable) char* fstr
fstr
;
(local variable) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t arg
arg
.
(field) ulong cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.size
size
=
(struct) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t

pfm_perf_encode_arg_t (pfmlib_perf_event.h): 40 bytes on LP64.

pfm_perf_encode_arg_t
.
(constant) ulong cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t.sizeof = 40LU
sizeof
;
const
(local variable) const(int) r
r
=
int cpu_pmu_pfm4_name_roundtrip.pfm_get_os_event_encoding(const(char)*, int, int, void*)
pfm_get_os_event_encoding
(
(
(parameter) string name
name
~ '\0').
(field) immutable(char)* string.ptr
ptr
,
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_PLM0 = 1
PFM_PLM0
|
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_PLM3 = 8
PFM_PLM3
,
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_OS_PERF_EVENT = 1
PFM_OS_PERF_EVENT
, &
(local variable) cpu_pmu_pfm4_name_roundtrip.pfm_perf_encode_arg_t arg
arg
);
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) int cpu_pmu_pfm4_name_roundtrip.Encoded.err
err
=
(local variable) const(int) r
r
;
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) bool cpu_pmu_pfm4_name_roundtrip.Encoded.ok
ok
=
(local variable) const(int) r
r
==
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_SUCCESS = 0
PFM_SUCCESS
;
if (
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) bool cpu_pmu_pfm4_name_roundtrip.Encoded.ok
ok
)
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) string cpu_pmu_pfm4_name_roundtrip.Encoded.fstr
fstr
=
string cpu_pmu_pfm4_name_roundtrip.cstr(const(char)* p) @trusted
cstr
(
(local variable) char* fstr
fstr
).
string object.idup!(immutable(char))(string a) pure nothrow @property @safe

Provide the .idup array property, which creates an immutable duplicate.

idup
;
return
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
;
} // ---- perf_event_open counting (mirrors counting-group.d) ---------------- void
void cpu_pmu_pfm4_name_roundtrip.ctl(int fd, uint request) @trusted
ctl
(int
(parameter) int fd
fd
, uint
(parameter) uint request
request
) @trusted => cast(void)
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(parameter) int fd
fd
, cast(c_ulong)
(parameter) uint request
request
, 0);
long
long cpu_pmu_pfm4_name_roundtrip.readN(int fd, ulong[] buf) @trusted
readN
(int
(parameter) int fd
fd
, ulong[]
(parameter) ulong[] buf
buf
) @trusted =>
long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogc
read
(
(parameter) int fd
fd
,
(parameter) ulong[] buf
buf
.
(field) ulong* ulong[].ptr
ptr
,
(parameter) ulong[] buf
buf
.
(field) ulong ulong[].length
length
* ulong.
(constant) ulong ulong.sizeof = 8LU
sizeof
);
/// A fixed workload: integer mixing (retired instructions) plus scalar SSE /// double arithmetic (SSE/AVX FLOPS — one multiply and one add per iter). /// `__gshared` sinks defeat dead-code elimination. __gshared ulong
(__gshared global) ulong cpu_pmu_pfm4_name_roundtrip.iSink

A fixed workload: integer mixing (retired instructions) plus scalar SSE double arithmetic (SSE/AVX FLOPS — one multiply and one add per iter). __gshared sinks defeat dead-code elimination.

iSink
;
__gshared double
(__gshared global) double cpu_pmu_pfm4_name_roundtrip.fSink
fSink
;
void
void cpu_pmu_pfm4_name_roundtrip.workload()
workload
()
{ ulong
(local variable) ulong acc
acc
= 0x9E3779B97F4A7C15UL;
double
(local variable) double f
f
= 1.0;
foreach (
(local variable) ulong i
i
; 0 .. 3_000_000UL)
{
(local variable) ulong acc
acc
= (
(local variable) ulong acc
acc
+
(local variable) ulong i
i
) * 2654435761UL ^ (
(local variable) ulong acc
acc
>> 13);
(local variable) double f
f
=
(local variable) double f
f
* 1.0000000001 + 0.5; // 1 MULT + 1 ADD_SUB FLOP
}
(__gshared global) ulong cpu_pmu_pfm4_name_roundtrip.iSink

A fixed workload: integer mixing (retired instructions) plus scalar SSE double arithmetic (SSE/AVX FLOPS — one multiply and one add per iter). __gshared sinks defeat dead-code elimination.

iSink
+=
(local variable) ulong acc
acc
;
(__gshared global) double cpu_pmu_pfm4_name_roundtrip.fSink
fSink
+=
(local variable) double f
f
;
} /// Open the already-encoded `attr` on this thread (pid 0, any cpu), run the /// workload, and return the multiplexing-scaled count, or `ulong.max` on /// failure. Adds the two time fields so a rotated counter still scales. ulong
ulong cpu_pmu_pfm4_name_roundtrip.countWith(ref core.sys.linux.perf_event.perf_event_attr attr) @trusted

Open the already-encoded attr on this thread (pid 0, any cpu), run the workload, and return the multiplexing-scaled count, or ulong.max on failure. Adds the two time fields so a rotated counter still scales.

countWith
(ref
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware 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
(parameter) core.sys.linux.perf_event.perf_event_attr attr
attr
) @trusted
{
(parameter) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.read_format
read_format
=
(enum) core.sys.linux.perf_event.perf_event_read_format

The 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 = 1u
PERF_FORMAT_TOTAL_TIME_ENABLED
|
(enum) core.sys.linux.perf_event.perf_event_read_format

The 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 = 2u
PERF_FORMAT_TOTAL_TIME_RUNNING
;
(parameter) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.disabled(ulong v) pure nothrow @nogc @property @safe
disabled
= 1;
(parameter) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.exclude_hv(ulong v) pure nothrow @nogc @property @safe
exclude_hv
= 1;
const
(local variable) const(int) fd
fd
= 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 @nogc
perf_event_open
(&
(parameter) core.sys.linux.perf_event.perf_event_attr attr
attr
, 0, -1, -1, 0);
if (
(local variable) const(int) fd
fd
< 0)
return ulong.
(constant) ulong ulong.max = 18446744073709551615LU
max
;
void cpu_pmu_pfm4_name_roundtrip.ctl(int fd, uint request) @trusted
ctl
(
(local variable) const(int) fd
fd
,
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219
PERF_EVENT_IOC_RESET
);
void cpu_pmu_pfm4_name_roundtrip.ctl(int fd, uint request) @trusted
ctl
(
(local variable) const(int) fd
fd
,
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_ENABLE = 9216

Ioctls that can be done on a perf event fd:

PERF_EVENT_IOC_ENABLE
);
void cpu_pmu_pfm4_name_roundtrip.workload()
workload
();
void cpu_pmu_pfm4_name_roundtrip.ctl(int fd, uint request) @trusted
ctl
(
(local variable) const(int) fd
fd
,
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217
PERF_EVENT_IOC_DISABLE
);
ulong[3]
(local variable) ulong[3] s
s
; // value, time_enabled, time_running
const
(local variable) const(long) got
got
=
long cpu_pmu_pfm4_name_roundtrip.readN(int fd, ulong[] buf) @trusted
readN
(
(local variable) const(int) fd
fd
,
(local variable) ulong[3] s
s
[]);
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) const(int) fd
fd
);
if (
(local variable) const(long) got
got
< cast(long)(3 * ulong.
(constant) ulong ulong.sizeof = 8LU
sizeof
) ||
(local variable) ulong[3] s
s
[2] == 0)
return ulong.
(constant) ulong ulong.max = 18446744073709551615LU
max
;
return
(local variable) ulong[3] s
s
[2] <
(local variable) ulong[3] s
s
[1] ? cast(ulong)(
(local variable) ulong[3] s
s
[0] * (cast(double)
(local variable) ulong[3] s
s
[1] /
(local variable) ulong[3] s
s
[2])) :
(local variable) ulong[3] s
s
[0];
} /// Report one name: encode, print type/config/exclude, then count. void
void cpu_pmu_pfm4_name_roundtrip.report(string label, string name) @trusted

Report one name: encode, print type/config/exclude, then count.

report
(
(alias) object.string = string
string
(parameter) string label
label
,
(alias) object.string = string
string
(parameter) string name
name
) @trusted
{ auto
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
=
cpu_pmu_pfm4_name_roundtrip.Encoded cpu_pmu_pfm4_name_roundtrip.encode(string name) @trusted

Name → perf_event_attr via libpfm. Counting at both priv levels (PLM0|PLM3) is the default; per-name :u/:k modifiers override it.

encode
(
(parameter) string name
name
);
if (!
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) bool cpu_pmu_pfm4_name_roundtrip.Encoded.ok
ok
)
{
void std.stdio.writefln!(char, string, string, string, int)(in char[] fmt, string __param_1, string __param_2, string __param_3, int __param_4) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" %-13s %-42s ENCODE FAILED: %s (%d)",
(parameter) string label
label
,
(parameter) string name
name
,
string cpu_pmu_pfm4_name_roundtrip.cstr(const(char)* p) @trusted
cstr
(
const(char)* cpu_pmu_pfm4_name_roundtrip.pfm_strerror(int)
pfm_strerror
(
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) int cpu_pmu_pfm4_name_roundtrip.Encoded.err
err
)),
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) int cpu_pmu_pfm4_name_roundtrip.Encoded.err
err
);
return; } auto
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
=
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
; // copy: countWith mutates read_format/flags
const
(local variable) const(ulong) cnt
cnt
=
ulong cpu_pmu_pfm4_name_roundtrip.countWith(ref core.sys.linux.perf_event.perf_event_attr attr) @trusted

Open the already-encoded attr on this thread (pid 0, any cpu), run the workload, and return the multiplexing-scaled count, or ulong.max on failure. Adds the two time fields so a rotated counter still scales.

countWith
(
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
);
void std.stdio.writefln!(char, string, string)(in char[] fmt, string __param_1, string __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" %-13s %s",
(parameter) string label
label
,
(parameter) string name
name
);
void std.stdio.writefln!(char, uint, ulong, ulong, ulong)(in char[] fmt, uint __param_1, ulong __param_2, ulong __param_3, ulong __param_4) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" type=%d config=0x%x exclude_user=%d exclude_kernel=%d",
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.type

Major type: hardware/software/tracepoint/etc.

type
,
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.config

Type specific configuration information.

config
,
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
.
ulong core.sys.linux.perf_event.perf_event_attr.exclude_user() const pure nothrow @nogc @property @safe
exclude_user
,
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
.
ulong core.sys.linux.perf_event.perf_event_attr.exclude_kernel() const pure nothrow @nogc @property @safe
exclude_kernel
);
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" fstr=%s",
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded e
e
.
(field) string cpu_pmu_pfm4_name_roundtrip.Encoded.fstr
fstr
);
if (
(local variable) const(ulong) cnt
cnt
== ulong.
(constant) ulong ulong.max = 18446744073709551615LU
max
)
void std.stdio.writefln!char(in char[] fmt) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" count: <perf_event_open/read failed on this host>");
else
void std.stdio.writefln!(char, const(ulong))(in char[] fmt, const(ulong) __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" count over workload window: %d",
(local variable) const(ulong) cnt
cnt
);
} /// Map /proc/cpuinfo (vendor + family + model) to the libpfm core-PMU table /// name — mirroring the *fixed* `amd64_get_revision` (libpfm HEAD). Returns /// null for anything this probe does not have a hand table for (non-AMD, or /// an AMD family we don't enumerate) → the µarch-specific section is skipped.
(alias) object.string = string
string
string cpu_pmu_pfm4_name_roundtrip.amdPmuName() @trusted

Map /proc/cpuinfo (vendor + family + model) to the libpfm core-PMU table name — mirroring the fixed amd64_get_revision (libpfm HEAD). Returns null for anything this probe does not have a hand table for (non-AMD, or an AMD family we don't enumerate) → the µarch-specific section is skipped.

amdPmuName
() @trusted
{ import
(package) std
std
.
(module) std.conv

A one-stop shop for converting values from one type to another.

Category Functions
Generic asOriginalType castFrom parse to toChars bitCast
Strings text wtext dtext writeText writeWText writeDText hexString
Numeric octal roundTo signed unsigned
Exceptions ConvException ConvOverflowException

Source

std/conv.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Shin Fujishiro, Adam D. Ruppe, Kenji Hara
conv
:
(alias template) to = std.conv.to(T)

The to template converts a value from one type _to another. The source type is deduced and the target type must be specified, for example the expression to!int(42.0) converts the number 42 from double _to int. The conversion is "safe", i.e., it checks for overflow; to!int(4.2e10) would throw the ConvOverflowException exception. Overflow checks are only inserted when necessary, e.g., to!double(42) does not do any checking because any int fits in a double.

Conversions from string _to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings _to signed types, the grammar recognized is: $(PRE $(I Integer): $(I Sign UnsignedInteger) $(I UnsignedInteger) $(I Sign): $(B +) $(B -))

For conversion _to unsigned types, the grammar recognized is: $(PRE $(I UnsignedInteger): $(I DecimalDigit) $(I DecimalDigit) $(I UnsignedInteger))

to
;
(alias) object.string = string
string
(local variable) string vendor
vendor
;
int
(local variable) int family
family
= -1,
(local variable) int model
model
= -1;
try { import
(package) std
std
.
(module) std.file

Utilities for manipulating files and scanning directories. Functions in this module handle files as a unit, e.g., read or write one file at a time. For opening files and manipulating them via handles refer to module std.stdio.

Category Functions
General exists isDir isFile isSymlink rename thisExePath
Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir
Files append copy read readText remove slurp write
Symlinks symlink readLink
Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes
Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged
Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace

Source

std/file.d

@copyrightCopyright The D Language Foundation 2007 - 2011.@seeThe official tutorial for an introduction to working with files in D, module std.stdio for opening files and manipulating them via handles, and module std.path for manipulating path strings.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis
file
:
(alias template) readText = std.file.readText(S = string, R)(auto ref R name) if (isSomeString!S && (isSomeFiniteCharInputRange!R || is(StringTypeOf!R)))

Reads and validates (using $(REF validate, std, utf)) a text file. S can be an array of any character type. However, no width or endian conversions are performed. So, if the width or endianness of the characters in the given file differ from the width or endianness of the element type of S, then validation will fail.

    Params:
        S = the string type of the file
        name = string or range of characters representing the file _name

    Returns: Array of characters read.

    Throws: $(LREF FileException) if there is an error reading the file,
            $(REF UTFException, std, utf) on UTF decoding error.

    See_Also: $(REF read, std,file) for reading a binary file.
readText
;
foreach (
(local variable) string line
line
;
string std.file.readText!(string, string)(string name) @safe

Reads and validates (using validate) a text file. S can be an array of any character type. However, no width or endian conversions are performed. So, if the width or endianness of the characters in the given file differ from the width or endianness of the element type of S, then validation will fail.

Examples

Read file with UTF-8 text.

write(deleteme, "abc"); // deleteme is the name of a temporary file
scope(exit) remove(deleteme);
string content = readText(deleteme);
assert(content == "abc");
@paramS the string type of the file@paramname string or range of characters representing the file name@returnsArray of characters read.@throwsFileException if there is an error reading the file, UTFException on UTF decoding error.@seeread for reading a binary file.
readText
("/proc/cpuinfo").
std.string.LineSplitter!(Flag.no, string) std.string.lineSplitter!(Flag.no, immutable(char))(string r) pure nothrow @nogc @safe

Split an array or slicable range of characters into a range of lines using '\r', '\n', '\v', '\f', "\r\n", lineSep, paraSep and '\u0085' (NEL) as delimiters. If keepTerm is set to Yes.keepTerminator, then the delimiter is included in the slices returned.

Does not throw on invalid UTF; such is simply passed unchanged to the output.

Adheres to Unicode 7.0.

Does not allocate memory.

Examples

import std.array : array;

string s = "Hello\nmy\rname\nis";

/* notice the call to 'array' to turn the lazy range created by
lineSplitter comparable to the string[] created by splitLines.
*/
assert(lineSplitter(s).array == splitLines(s));
auto s = "\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\nmon\u2030day\n";
auto lines = s.lineSplitter();
static immutable witness = ["", "peter", "", "paul", "jerry", "ice", "cream", "", "sunday", "mon\u2030day"];
uint i;
foreach (line; lines)
{
    assert(line == witness[i++]);
}
assert(i == witness.length);
@paramr array of chars, wchars, or dchars or a slicable range@paramkeepTerm whether delimiter is included or not in the results@returnsrange of slices of the input range r@seesplitLines splitter splitter
lineSplitter
)
{ if (
(local variable) string line
line
.
bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safe

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
("vendor_id") &&
(local variable) string vendor
vendor
is null)
(local variable) string vendor
vendor
=
(local variable) string line
line
["vendor_id".
(constant) ulong "vendor_id".length = 9LU
length
.. $].
string std.string.strip!(string, char)(string str, const(char)[] chars) pure @safe

Examples

assert(strip("     hello world     ", "x") ==
       "     hello world     ");
assert(strip("     hello world     ", " ") ==
       "hello world");
assert(strip("   xyxyhello worldxyxy     ", "xy ") ==
       "hello world");
assert(strip("\u2020hello\u2020"w, "\u2020"w) == "hello"w);
assert(strip("\U00010001hello\U00010001"d, "\U00010001"d) == "hello"d);
assert(strip(" hello ", "") == " hello ");
strip
(" \t:").
string object.idup!(immutable(char))(string a) pure nothrow @property @safe

Provide the .idup array property, which creates an immutable duplicate.

idup
;
else if (
(local variable) string line
line
.
bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safe

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
("cpu family") &&
(local variable) int family
family
< 0)
(local variable) int family
family
=
(local variable) string line
line
["cpu family".
(constant) ulong "cpu family".length = 10LU
length
.. $].
string std.string.strip!(string, char)(string str, const(char)[] chars) pure @safe

Examples

assert(strip("     hello world     ", "x") ==
       "     hello world     ");
assert(strip("     hello world     ", " ") ==
       "hello world");
assert(strip("   xyxyhello worldxyxy     ", "xy ") ==
       "hello world");
assert(strip("\u2020hello\u2020"w, "\u2020"w) == "hello"w);
assert(strip("\U00010001hello\U00010001"d, "\U00010001"d) == "hello"d);
assert(strip(" hello ", "") == " hello ");
strip
(" \t:").
int std.conv.to!int.to!string(string __param_0) pure @safe

The to template converts a value from one type to another. The source type is deduced and the target type must be specified, for example the expression to`!int(42.0)` converts the number 42 from `double` to `int`. The conversion is "safe", i.e., it checks for overflow; to!int(4.2e10) would throw the ConvOverflowException exception. Overflow checks are only inserted when necessary, e.g., ``to!double(42) does not do any checking because any int fits in a double.

Conversions from string to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings to signed types, the grammar recognized is: Integer: Sign UnsignedInteger UnsignedInteger Sign: + -

For conversion to unsigned types, the grammar recognized is: UnsignedInteger: DecimalDigit DecimalDigit UnsignedInteger

Examples

Converting a value to its own type (useful mostly for generic code) simply returns its argument.

int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14

Converting among numeric types is a safe way to cast them around.

Conversions from floating-point types to integral types allow loss of precision (the fractional part of a floating-point number). The conversion is truncating towards zero, the same way a cast would truncate. (To round a floating point value when casting to an integral, use roundTo.)

import std.exception : assertThrown;

int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));

assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);

When converting strings to numeric types, note that D hexadecimal and binary literals are not handled. Neither the prefixes that indicate the base, nor the horizontal bar used to separate groups of digits are recognized. This also applies to the suffixes that indicate the type.

To work around this, you can specify a radix for conversions involving numbers.

auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);

Conversions from integral types to floating-point types always succeed, but might lose accuracy. The largest integers with a predecessor representable in floating-point format are 2^24-1 for float, 2^53-1 for double, and 2^64-1 for real (when real is 80-bit, e.g. on Intel machines).

// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);

Conversion from string types to char types enforces the input to consist of a single code point, and said code point must fit in the target type. Otherwise, ConvException is thrown.

import std.exception : assertThrown;

assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');

// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');

// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));

Converting an array to another array type works by converting each element in turn. Associative arrays can be converted to associative arrays as long as keys and values can in turn be converted.

import std.string : split;

int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);

Conversions operate transitively, meaning that they work on arrays and associative arrays of any complexity.

This conversion works because to`!short` applies to an `int`, to!wstring applies to a string, to`!string` applies to a `double`, and to!(double[]) applies to an int[]. The conversion might throw an exception because ``to!short might fail the range check.

int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);

Object-to-object conversions by dynamic casting throw exception when the source is non-null and the target is null.

import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));

Stringize conversion from all types is supported.

  • String to string conversion works for any two string types having (char, wchar, dchar) character widths and any combination of qualifiers (mutable, const, or immutable).

  • Converts array (other than strings) to string. Each element is converted by calling ``to!T.

  • Associative array to string conversion. Each element is converted by calling ``to!T.

  • Object to string conversion calls toString against the object or returns "null" if the object is null.

  • Struct to string conversion calls toString against the struct if it is defined.

  • For structs that do not define toString, the conversion to string produces the list of fields.

  • Enumerated types are converted to strings as their symbolic names.

  • Boolean values are converted to "true" or "false".

  • char, wchar, dchar to a string type.

  • Unsigned or signed integers to strings.

    special case

    : Convert integral value to string in radix radix. radix must be a value from 2 to 36. value is treated as a signed value only if radix is 10. The characters A through Z are used to represent values 10 through 36 and their case is determined by the letterCase parameter.

  • All floating point types to all string types.

  • Pointer to string conversions convert the pointer to a size_t value. If pointer is char*, treat it as C-style strings. In that case, this function is @system.

See formatValue on how toString should be defined.

// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");

// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
       to!string(associativeArray) == `["1":2, "0":1]`);

// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");

// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);

auto c = to!(wchar[])(b);
assert(c == "abcx");

Strings can be converted to enum types. The enum member with the same name as the input string is returned. The comparison is case-sensitive.

A ConvException is thrown if the enum does not have the specified member.

import std.exception : assertThrown;

enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to
!int;
else if (
(local variable) string line
line
.
bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safe

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
("model") && !
(local variable) string line
line
.
bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safe

Checks whether the given input range starts with (one of) the given needle(s) or, if no needles are given, if its front element fulfils predicate pred.

For more information about pred see find.

@parampred Predicate to use in comparing the elements of the haystack and the needle(s). Mandatory if no needles are given.@paramdoesThisStart The input range to check.@paramwithOneOfThese The needles against which the range is to be checked, which may be individual elements or input ranges of elements.@paramwithThis The single needle to check, which may be either a single element or an input range of elements.@returns

0 if the needle(s) do not occur at the beginning of the given range; otherwise the position of the matching needle, that is, 1 if the range starts with withOneOfThese[0], 2 if it starts with withOneOfThese[1], and so on.

In the case where doesThisStart starts with multiple of the ranges or elements in withOneOfThese, then the shortest one matches (if there are two which match which are of the same length (e.g. "a" and 'a'), then the left-most of them in the argument list matches).

In the case when no needle parameters are given, return true iff front of doesThisStart fulfils predicate pred.

startsWith
("model name") &&
(local variable) int model
model
< 0)
(local variable) int model
model
=
(local variable) string line
line
["model".
(constant) ulong "model".length = 5LU
length
.. $].
string std.string.strip!(string, char)(string str, const(char)[] chars) pure @safe

Examples

assert(strip("     hello world     ", "x") ==
       "     hello world     ");
assert(strip("     hello world     ", " ") ==
       "hello world");
assert(strip("   xyxyhello worldxyxy     ", "xy ") ==
       "hello world");
assert(strip("\u2020hello\u2020"w, "\u2020"w) == "hello"w);
assert(strip("\U00010001hello\U00010001"d, "\U00010001"d) == "hello"d);
assert(strip(" hello ", "") == " hello ");
strip
(" \t:").
int std.conv.to!int.to!string(string __param_0) pure @safe

The to template converts a value from one type to another. The source type is deduced and the target type must be specified, for example the expression to`!int(42.0)` converts the number 42 from `double` to `int`. The conversion is "safe", i.e., it checks for overflow; to!int(4.2e10) would throw the ConvOverflowException exception. Overflow checks are only inserted when necessary, e.g., ``to!double(42) does not do any checking because any int fits in a double.

Conversions from string to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings to signed types, the grammar recognized is: Integer: Sign UnsignedInteger UnsignedInteger Sign: + -

For conversion to unsigned types, the grammar recognized is: UnsignedInteger: DecimalDigit DecimalDigit UnsignedInteger

Examples

Converting a value to its own type (useful mostly for generic code) simply returns its argument.

int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14

Converting among numeric types is a safe way to cast them around.

Conversions from floating-point types to integral types allow loss of precision (the fractional part of a floating-point number). The conversion is truncating towards zero, the same way a cast would truncate. (To round a floating point value when casting to an integral, use roundTo.)

import std.exception : assertThrown;

int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));

assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);

When converting strings to numeric types, note that D hexadecimal and binary literals are not handled. Neither the prefixes that indicate the base, nor the horizontal bar used to separate groups of digits are recognized. This also applies to the suffixes that indicate the type.

To work around this, you can specify a radix for conversions involving numbers.

auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);

Conversions from integral types to floating-point types always succeed, but might lose accuracy. The largest integers with a predecessor representable in floating-point format are 2^24-1 for float, 2^53-1 for double, and 2^64-1 for real (when real is 80-bit, e.g. on Intel machines).

// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);

Conversion from string types to char types enforces the input to consist of a single code point, and said code point must fit in the target type. Otherwise, ConvException is thrown.

import std.exception : assertThrown;

assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');

// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');

// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));

Converting an array to another array type works by converting each element in turn. Associative arrays can be converted to associative arrays as long as keys and values can in turn be converted.

import std.string : split;

int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);

Conversions operate transitively, meaning that they work on arrays and associative arrays of any complexity.

This conversion works because to`!short` applies to an `int`, to!wstring applies to a string, to`!string` applies to a `double`, and to!(double[]) applies to an int[]. The conversion might throw an exception because ``to!short might fail the range check.

int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);

Object-to-object conversions by dynamic casting throw exception when the source is non-null and the target is null.

import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));

Stringize conversion from all types is supported.

  • String to string conversion works for any two string types having (char, wchar, dchar) character widths and any combination of qualifiers (mutable, const, or immutable).

  • Converts array (other than strings) to string. Each element is converted by calling ``to!T.

  • Associative array to string conversion. Each element is converted by calling ``to!T.

  • Object to string conversion calls toString against the object or returns "null" if the object is null.

  • Struct to string conversion calls toString against the struct if it is defined.

  • For structs that do not define toString, the conversion to string produces the list of fields.

  • Enumerated types are converted to strings as their symbolic names.

  • Boolean values are converted to "true" or "false".

  • char, wchar, dchar to a string type.

  • Unsigned or signed integers to strings.

    special case

    : Convert integral value to string in radix radix. radix must be a value from 2 to 36. value is treated as a signed value only if radix is 10. The characters A through Z are used to represent values 10 through 36 and their case is determined by the letterCase parameter.

  • All floating point types to all string types.

  • Pointer to string conversions convert the pointer to a size_t value. If pointer is char*, treat it as C-style strings. In that case, this function is @system.

See formatValue on how toString should be defined.

// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");

// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
       to!string(associativeArray) == `["1":2, "0":1]`);

// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");

// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);

auto c = to!(wchar[])(b);
assert(c == "abcx");

Strings can be converted to enum types. The enum member with the same name as the input string is returned. The comparison is case-sensitive.

A ConvException is thrown if the enum does not have the specified member.

import std.exception : assertThrown;

enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to
!int;
} } catch (
(class) object.Exception

The base class of all errors that are safe to catch and handle.

In principle, only thrown objects derived from this class are safe to catch inside a catch block. Thrown objects not derived from Exception represent runtime errors that should not be caught, as certain runtime guarantees may not hold, making it unsafe to continue program execution.

Examples

bool gotCaught;
try
{
    throw new Exception("msg");
}
catch (Exception e)
{
    gotCaught = true;
    assert(e.msg == "msg");
}
assert(gotCaught);
Exception
)
return null; if (
(local variable) string vendor
vendor
!= "AuthenticAMD")
return null; switch (
(local variable) int family
family
)
{ case 23: // 17h return
(local variable) int model
model
>= 0x30 ? "amd64_fam17h_zen2" : "amd64_fam17h_zen1";
case 25: // 19h return (
(local variable) int model
model
>= 0x60 || (
(local variable) int model
model
>= 0x10 &&
(local variable) int model
model
<= 0x1f))
? "amd64_fam19h_zen4" : "amd64_fam19h_zen3"; case 26: // 1ah return (
(local variable) int model
model
<= 0x4f || (
(local variable) int model
model
>= 0x60 &&
(local variable) int model
model
<= 0x7f))
? "amd64_fam1ah_zen5" : "amd64_fam1ah_zen6"; default: return null; } } int
int cpu_pmu_pfm4_name_roundtrip.run()
run
()
{ // Work around libpfm 4.13.0's auto-detect gap (see the header): place // un-detected per-µarch tables on the searchable list so an explicit // `pmu::event` prefix resolves. Must precede pfm_initialize.
int core.sys.posix.stdlib.setenv(scope const(char*), scope const(char*), int) nothrow @nogc
setenv
("LIBPFM_ENCODE_INACTIVE", "1", 1);
const
(local variable) const(int) initRc
initRc
=
int cpu_pmu_pfm4_name_roundtrip.pfm_initialize()
pfm_initialize
();
if (
(local variable) const(int) initRc
initRc
!=
(constant) int cpu_pmu_pfm4_name_roundtrip.PFM_SUCCESS = 0
PFM_SUCCESS
)
{
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("SKIP: pfm_initialize failed (%s) — libpfm unusable on this host",
string cpu_pmu_pfm4_name_roundtrip.cstr(const(char)* p) @trusted
cstr
(
const(char)* cpu_pmu_pfm4_name_roundtrip.pfm_strerror(int)
pfm_strerror
(
(local variable) const(int) initRc
initRc
)));
return 0; } const
(local variable) const(int) v
v
=
int cpu_pmu_pfm4_name_roundtrip.pfm_get_version()
pfm_get_version
();
void std.stdio.writefln!(char, const(int), int)(in char[] fmt, const(int) __param_1, int __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("libpfm interface version %d.%d (release: see nixpkgs libpfm)",
(local variable) const(int) v
v
>> 16,
(local variable) const(int) v
v
& 0xffff);
// --- Generic (OS-abstracted) name: resolves via the always-present // `perf` PMU regardless of hardware. ---
void std.stdio.writeln!string(string __param_0) @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n== generic perf name (PERF_TYPE_HARDWARE) ==");
void cpu_pmu_pfm4_name_roundtrip.report(string label, string name) @trusted

Report one name: encode, print type/config/exclude, then count.

report
("generic", "PERF_COUNT_HW_CPU_CYCLES");
// Probe whether we can count at all; if the generic open failed for // permission reasons, everything else will too. { auto
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded probe
probe
=
cpu_pmu_pfm4_name_roundtrip.Encoded cpu_pmu_pfm4_name_roundtrip.encode(string name) @trusted

Name → perf_event_attr via libpfm. Counting at both priv levels (PLM0|PLM3) is the default; per-name :u/:k modifiers override it.

encode
("PERF_COUNT_HW_CPU_CYCLES");
if (
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded probe
probe
.
(field) bool cpu_pmu_pfm4_name_roundtrip.Encoded.ok
ok
)
{ auto
(local variable) core.sys.linux.perf_event.perf_event_attr a
a
=
(local variable) cpu_pmu_pfm4_name_roundtrip.Encoded probe
probe
.
(field) core.sys.linux.perf_event.perf_event_attr cpu_pmu_pfm4_name_roundtrip.Encoded.attr
attr
;
if (
ulong cpu_pmu_pfm4_name_roundtrip.countWith(ref core.sys.linux.perf_event.perf_event_attr attr) @trusted

Open the already-encoded attr on this thread (pid 0, any cpu), run the workload, and return the multiplexing-scaled count, or ulong.max on failure. Adds the two time fields so a rotated counter still scales.

countWith
(
(local variable) core.sys.linux.perf_event.perf_event_attr a
a
) == ulong.
(constant) ulong ulong.max = 18446744073709551615LU
max
)
{
void std.stdio.writefln!char(in char[] fmt) @safe

Equivalent 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; } } } // --- Microarchitecture-specific names via the host's libpfm table. --- const
(local variable) const(string) pmu
pmu
=
string cpu_pmu_pfm4_name_roundtrip.amdPmuName() @trusted

Map /proc/cpuinfo (vendor + family + model) to the libpfm core-PMU table name — mirroring the fixed amd64_get_revision (libpfm HEAD). Returns null for anything this probe does not have a hand table for (non-AMD, or an AMD family we don't enumerate) → the µarch-specific section is skipped.

amdPmuName
();
if (
(local variable) const(string) pmu
pmu
is null)
{
void std.stdio.writeln!string(string __param_0) @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n== µarch-specific names: SKIPPED (no hand table for this CPU; "
~ "generic path above still demonstrates the round trip) =="); return 0; }
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("\n== µarch-specific names via the %s table (PERF_TYPE_RAW) ==",
(local variable) const(string) pmu
pmu
);
void cpu_pmu_pfm4_name_roundtrip.report(string label, string name) @trusted

Report one name: encode, print type/config/exclude, then count.

report
("zen4-native",
(local variable) const(string) pmu
pmu
~ "::RETIRED_INSTRUCTIONS");
void cpu_pmu_pfm4_name_roundtrip.report(string label, string name) @trusted

Report one name: encode, print type/config/exclude, then count.

report
("with-umask",
(local variable) const(string) pmu
pmu
~ "::RETIRED_SSE_AVX_FLOPS:ADD_SUB_FLOPS");
void cpu_pmu_pfm4_name_roundtrip.report(string label, string name) @trusted

Report one name: encode, print type/config/exclude, then count.

report
("with-modifier",
(local variable) const(string) pmu
pmu
~ "::RETIRED_INSTRUCTIONS:u");
void std.stdio.writeln!string(string __param_0) @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("\n (config unchanged between native and :u — user/kernel filtering "
~ "moved into attr.exclude_*, the PFM_OS_PERF_EVENT split.)"); return 0; } } int
int D main()
main
()
{ version (
linux
linux
)
return
int cpu_pmu_pfm4_name_roundtrip.run()
run
();
else { import std.stdio : writefln; writefln("SKIP: libpfm4 / perf_event_open is Linux-only"); return 0; } }