sampling-symbolize.dhover×580all
#!/usr/bin/env dub
/+ dub.sdl:
    name "cpu_pmu_sampling_symbolize"
    platforms "linux"
    libs "dw" "elf"
    dflags "-g"
    targetPath "build"
+/
/**
 * Overflow/IP sampling through the `perf_event` mmap ring buffer, then
 * symbolization of the sampled instruction pointers via elfutils `libdwfl`.
 *
 * This is the end-to-end "profiler core": a hardware event (`cycles`) is armed
 * with a target sample *frequency*; on each overflow the kernel writes a
 * `PERF_RECORD_SAMPLE` (carrying the interrupted IP) into a memory-mapped ring
 * buffer. We drain the ring, then hand the *live* process to `libdwfl`
 * (`dwfl_linux_proc_report`, the library's own `/proc/PID/maps` reader) and
 * resolve each IP to module → symbol (`dwfl_module_addrinfo`) → source line
 * (`dwfl_module_getsrc` + `dwfl_lineinfo`).
 *
 * A key, verified subtlety about `PERF_RECORD_MMAP2` (`attr.mmap2 = 1`): the
 * kernel emits it only for executable mappings **created while the event is
 * enabled** — it does NOT re-emit pre-existing code (our own binary, libc).
 * That is why the `perf` tool *synthesizes* `MMAP2` for the already-mapped
 * regions from `/proc/PID/maps` at start, and why `libdwfl`'s
 * `dwfl_linux_proc_report` reads the same file. To make a real captured
 * `MMAP2` visible, we deliberately map `/proc/self/exe` `PROT_EXEC` mid-window;
 * its record's `filename` matches the binary `libdwfl` symbolizes against —
 * tying the two halves of the address-space model together.
 *
 * Companion to docs/research/cpu-pmu/linux-perf-events.md
 *   § "Overflow sampling: the ring buffer, `PERF_RECORD_MMAP2`, and IP
 *      symbolization" and docs/research/cpu-pmu/elfutils.md § "Address →
 *      module → symbol → line".
 *
 * Run with: nix shell nixpkgs#elfutils nixpkgs#pkg-config -c dub run --single sampling-symbolize.d
 *
 * Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4),
 * `/proc/sys/kernel/perf_event_paranoid` = -1, elfutils 0.195 (libdw/libdwfl),
 * LDC 1.41 druntime `core.sys.linux.perf_event`. Linked with the flake
 * stdenv dynamic linker (glibc 2.42) so elfutils 0.195 can resolve
 * `GLIBC_ABI_GNU2_TLS` — see nix/d-toolchain.nix.
 *
 * Portability: any missing capability (`perf_event_open`/`mmap` refused by
 * `perf_event_paranoid`/seccomp, no PMU, non-Linux) prints a `SKIP:` line and
 * exits 0 so CI stays green on any host. A binary with no DWARF line table just
 * prints symbol names without `file:line` — also a success.
 */
module 
(module) cpu_pmu_sampling_symbolize

Overflow/IP sampling through the perf_event mmap ring buffer, then symbolization of the sampled instruction pointers via elfutils libdwfl.

This is the end-to-end "profiler core": a hardware event (cycles) is armed with a target sample frequency; on each overflow the kernel writes a PERF_RECORD_SAMPLE (carrying the interrupted IP) into a memory-mapped ring buffer. We drain the ring, then hand the live process to libdwfl (dwfl_linux_proc_report, the library's own /proc/PID/maps reader) and resolve each IP to module → symbol (dwfl_module_addrinfo) → source line (dwfl_module_getsrc + dwfl_lineinfo).

A key, verified subtlety about PERF_RECORD_MMAP2 (attr.mmap2 = 1): the kernel emits it only for executable mappings created while the event is enabled — it does NOT re-emit pre-existing code (our own binary, libc). That is why the perf tool synthesizes MMAP2 for the already-mapped regions from /proc/PID/maps at start, and why libdwfl's dwfl_linux_proc_report reads the same file. To make a real captured MMAP2 visible, we deliberately map /proc/self/exe PROT_EXEC mid-window; its record's filename matches the binary libdwfl symbolizes against — tying the two halves of the address-space model together.

Companion to docs/research/cpu-pmu/linux-perf-events.md § "Overflow sampling: the ring buffer, PERF_RECORD_MMAP2, and IP symbolization" and docs/research/cpu-pmu/elfutils.md § "Address → module → symbol → line".

Run with: nix shell nixpkgs#elfutils nixpkgs#pkg-config -c dub run --single sampling-symbolize.d

Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4), /proc/sys/kernel/perf_event_paranoid = -1, elfutils 0.195 (libdw/libdwfl), LDC 1.41 druntime core.sys.linux.perf_event. Linked with the flake stdenv dynamic linker (glibc 2.42) so elfutils 0.195 can resolve GLIBC_ABI_GNU2_TLS — see nix/d-toolchain.nix.

Portability

any missing capability (perf_event_open/mmap refused by perf_event_paranoid/seccomp, no PMU, non-Linux) prints a SKIP: line and exits 0 so CI stays green on any host. A binary with no DWARF line table just prints symbol names without file:line — also a success.

cpu_pmu_sampling_symbolize
;
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
;
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_sampling_symbolize.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
,
(alias) cpu_pmu_sampling_symbolize.getpid = int core.sys.posix.unistd.getpid() nothrow @nogc @trusted
getpid
,
(alias) cpu_pmu_sampling_symbolize.sysconf = long core.sys.posix.unistd.sysconf(int) nothrow @nogc @trusted
sysconf
,
(alias enum value) cpu_pmu_sampling_symbolize._SC_PAGESIZE = core.sys.posix.unistd._SC_PAGESIZE = 30
_SC_PAGESIZE
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.fcntl

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
fcntl
: open,
(alias constant) cpu_pmu_sampling_symbolize.O_RDONLY = int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
;
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_sampling_symbolize.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
.
(package) core.sys.posix.sys
sys
.
(module) core.sys.posix.sys.mman

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
mman
:
(alias) cpu_pmu_sampling_symbolize.mmap = void* core.sys.posix.sys.mman.mmap64(void*, ulong, int, int, int, long) nothrow @nogc
mmap
,
(alias) cpu_pmu_sampling_symbolize.munmap = int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogc
munmap
,
(alias constant) cpu_pmu_sampling_symbolize.PROT_READ = int core.sys.posix.sys.mman.PROT_READ = 1
PROT_READ
,
(alias constant) cpu_pmu_sampling_symbolize.PROT_WRITE = int core.sys.posix.sys.mman.PROT_WRITE = 2
PROT_WRITE
,
(alias constant) cpu_pmu_sampling_symbolize.PROT_EXEC = int core.sys.posix.sys.mman.PROT_EXEC = 4
PROT_EXEC
,
(alias constant) cpu_pmu_sampling_symbolize.MAP_SHARED = int core.sys.posix.sys.mman.MAP_SHARED = 1
MAP_SHARED
,
(alias constant) cpu_pmu_sampling_symbolize.MAP_PRIVATE = int core.sys.posix.sys.mman.MAP_PRIVATE = 2
MAP_PRIVATE
,
(alias constant) cpu_pmu_sampling_symbolize.MAP_FAILED = void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
;
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_sampling_symbolize.memcpy = void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
,
(alias) cpu_pmu_sampling_symbolize.strlen = ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
;
import
(package) core
core
.
(module) core.atomic

The atomic module provides basic support for lock-free concurrent programming.

Use the -preview=nosharedaccess compiler flag to detect unsafe individual read or write operations on shared data.

Source

core/atomic.d

Examples

int y = 2;
shared int x = y; // OK

//x++; // read modify write error
x.atomicOp!"+="(1); // OK
//y = x; // read error with preview flag
y = x.atomicLoad(); // OK
assert(y == 3);
//x = 5; // write error with preview flag
x.atomicStore(5); // OK
assert(x.atomicLoad() == 5);
@copyrightCopyright Sean Kelly 2005 - 2016.@licenseBoost License 1.0@authorsSean Kelly, Alex Rønne Petersen, Manu Evans
atomic
:
(alias template) cpu_pmu_sampling_symbolize.atomicLoad = core.atomic.atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) if (!is(T == shared(U), U) && !is(T == shared(inout(U)), U) && !is(T == shared(const(U)), U))

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
,
(alias template) cpu_pmu_sampling_symbolize.atomicStore = core.atomic.atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval) if (!is(T == shared) && !is(V == shared))

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
,
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
;
import
(package) core
core
.
(module) core.time

Module containing core time functionality, such as Duration (which represents a duration of time) or MonoTime (which represents a timestamp of the system's monotonic clock).

Various functions take a string (or strings) to represent a unit of time (e.g. convert!("days", "hours")(numDays)). The valid strings to use with such functions are "years", "months", "weeks", "days", "hours", "minutes", "seconds", "msecs" (milliseconds), "usecs" (microseconds), "hnsecs" (hecto-nanoseconds - i.e. 100 ns) or some subset thereof. There are a few functions that also allow "nsecs", but very little actually has precision greater than hnsecs.

Symbol Description
Types
Duration Represents a duration of time of weeks or less (kept internally as hnsecs). (e.g. 22 days or 700 seconds).
TickDuration DEPRECATED Represents a duration of time in system clock ticks, using the highest precision that the system provides.
MonoTime Represents a monotonic timestamp in system clock ticks, using the highest precision that the system provides.
Functions
convert Generic way of converting between two time units.
dur Allows constructing a Duration from the given time units with the given length.
weeks days hours

minutes seconds msecs

usecs hnsecs nsecs | Convenience aliases for dur. | | abs | Returns the absolute value of a duration. |

From Duration
From TickDuration
From units
To Duration
tickDuration.to, std,conv!Duration()
dur!"msecs"(5) or 5.msecs()

| To TickDuration | duration.to, std,conv!TickDuration() |

  • | TickDuration.from!"msecs"(msecs) |

| To units | duration.total!"days" | tickDuration.msecs | convert!("days", "msecs")(msecs) |

Source

core/time.d

@copyrightCopyright 2010 - 2012@licenseBoost License 1.0.@authorsJonathan M Davis and Kato Shoichi
time
:
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
, msecs;
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_sampling_symbolize.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

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

writefln
,
(alias template) cpu_pmu_sampling_symbolize.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_sampling_symbolize.fromStringz = std.string.fromStringz(Char)(return scope inout(Char)* cString) if (isSomeChar!Char)
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
;
// ---- elfutils libdwfl: extern(C) prototypes declared in-file -------- // (a single-file dub program cannot compile a C shim; we link -ldw -lelf). alias
(alias) cpu_pmu_sampling_symbolize.Dwarf_Addr = ulong
Dwarf_Addr
= ulong;
alias
(alias) cpu_pmu_sampling_symbolize.Dwarf_Word = ulong
Dwarf_Word
= ulong;
alias
(alias) cpu_pmu_sampling_symbolize.GElf_Addr = ulong
GElf_Addr
= ulong;
alias
(alias) cpu_pmu_sampling_symbolize.GElf_Off = ulong
GElf_Off
= ulong;
alias
(alias) cpu_pmu_sampling_symbolize.GElf_Word = uint
GElf_Word
= uint;
/// `Elf64_Sym` (== `GElf_Sym` on LP64) — dwfl fills this; we read `st_value`. struct
(struct) cpu_pmu_sampling_symbolize.GElf_Sym

Elf64_Sym (== GElf_Sym on LP64) — dwfl fills this; we read st_value.

GElf_Sym
{ uint
(field) uint cpu_pmu_sampling_symbolize.GElf_Sym.st_name
st_name
;
ubyte
(field) ubyte cpu_pmu_sampling_symbolize.GElf_Sym.st_info
st_info
;
ubyte
(field) ubyte cpu_pmu_sampling_symbolize.GElf_Sym.st_other
st_other
;
ushort
(field) ushort cpu_pmu_sampling_symbolize.GElf_Sym.st_shndx
st_shndx
;
ulong
(field) ulong cpu_pmu_sampling_symbolize.GElf_Sym.st_value
st_value
;
ulong
(field) ulong cpu_pmu_sampling_symbolize.GElf_Sym.st_size
st_size
;
} struct
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
; // opaque
struct
(struct) cpu_pmu_sampling_symbolize.Dwfl_Module
Dwfl_Module
; // opaque
struct
(struct) cpu_pmu_sampling_symbolize.Dwfl_Line
Dwfl_Line
; // opaque
struct
(struct) cpu_pmu_sampling_symbolize.Elf
Elf
; // opaque
/// `Dwfl_Callbacks` (elfutils@6f8f78c libdwfl/libdwfl.h:72) as four pointers: /// `find_elf`, `find_debuginfo`, `section_address`, `debuginfo_path`. struct
(struct) cpu_pmu_sampling_symbolize.DwflCallbacks

Dwfl_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:72) as four pointers: find_elf, find_debuginfo, section_address, debuginfo_path.

DwflCallbacks
{ void*
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.find_elf
find_elf
;
void*
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.find_debuginfo
find_debuginfo
;
void*
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.section_address
section_address
;
char**
(field) char** cpu_pmu_sampling_symbolize.DwflCallbacks.debuginfo_path
debuginfo_path
;
} extern (C) @nogc nothrow {
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*
cpu_pmu_sampling_symbolize.Dwfl* cpu_pmu_sampling_symbolize.dwfl_begin(const(cpu_pmu_sampling_symbolize.DwflCallbacks)*) nothrow @nogc
dwfl_begin
(const(
(struct) cpu_pmu_sampling_symbolize.DwflCallbacks

Dwfl_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:72) as four pointers: find_elf, find_debuginfo, section_address, debuginfo_path.

DwflCallbacks
)*);
void
void cpu_pmu_sampling_symbolize.dwfl_end(cpu_pmu_sampling_symbolize.Dwfl*) nothrow @nogc
dwfl_end
(
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*);
int
int cpu_pmu_sampling_symbolize.dwfl_linux_proc_report(cpu_pmu_sampling_symbolize.Dwfl*, int pid) nothrow @nogc
dwfl_linux_proc_report
(
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*, int
(parameter) int pid
pid
);
int
int cpu_pmu_sampling_symbolize.dwfl_report_end(cpu_pmu_sampling_symbolize.Dwfl*, void* removed, void* arg) nothrow @nogc
dwfl_report_end
(
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*, void*
(parameter) void* removed
removed
, void*
(parameter) void* arg
arg
);
(struct) cpu_pmu_sampling_symbolize.Dwfl_Module
Dwfl_Module
*
cpu_pmu_sampling_symbolize.Dwfl_Module* cpu_pmu_sampling_symbolize.dwfl_addrmodule(cpu_pmu_sampling_symbolize.Dwfl*, ulong) nothrow @nogc
dwfl_addrmodule
(
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Addr = ulong
Dwarf_Addr
);
const(char)*
const(char)* cpu_pmu_sampling_symbolize.dwfl_module_addrinfo(cpu_pmu_sampling_symbolize.Dwfl_Module*, ulong, ulong*, cpu_pmu_sampling_symbolize.GElf_Sym*, uint*, cpu_pmu_sampling_symbolize.Elf**, ulong*) nothrow @nogc
dwfl_module_addrinfo
(
(struct) cpu_pmu_sampling_symbolize.Dwfl_Module
Dwfl_Module
*,
(alias) cpu_pmu_sampling_symbolize.GElf_Addr = ulong
GElf_Addr
,
(alias) cpu_pmu_sampling_symbolize.GElf_Off = ulong
GElf_Off
*,
(struct) cpu_pmu_sampling_symbolize.GElf_Sym

Elf64_Sym (== GElf_Sym on LP64) — dwfl fills this; we read st_value.

GElf_Sym
*,
(alias) cpu_pmu_sampling_symbolize.GElf_Word = uint
GElf_Word
*,
(struct) cpu_pmu_sampling_symbolize.Elf
Elf
**,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Addr = ulong
Dwarf_Addr
*);
(struct) cpu_pmu_sampling_symbolize.Dwfl_Line
Dwfl_Line
*
cpu_pmu_sampling_symbolize.Dwfl_Line* cpu_pmu_sampling_symbolize.dwfl_module_getsrc(cpu_pmu_sampling_symbolize.Dwfl_Module*, ulong) nothrow @nogc
dwfl_module_getsrc
(
(struct) cpu_pmu_sampling_symbolize.Dwfl_Module
Dwfl_Module
*,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Addr = ulong
Dwarf_Addr
);
const(char)*
const(char)* cpu_pmu_sampling_symbolize.dwfl_lineinfo(cpu_pmu_sampling_symbolize.Dwfl_Line*, ulong*, int*, int*, ulong*, ulong*) nothrow @nogc
dwfl_lineinfo
(
(struct) cpu_pmu_sampling_symbolize.Dwfl_Line
Dwfl_Line
*,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Addr = ulong
Dwarf_Addr
*, int*, int*,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Word = ulong
Dwarf_Word
*,
(alias) cpu_pmu_sampling_symbolize.Dwarf_Word = ulong
Dwarf_Word
*);
// The two standard callbacks we take the address of for DwflCallbacks: int
int cpu_pmu_sampling_symbolize.dwfl_linux_proc_find_elf() nothrow @nogc
dwfl_linux_proc_find_elf
();
int
int cpu_pmu_sampling_symbolize.dwfl_standard_find_debuginfo() nothrow @nogc
dwfl_standard_find_debuginfo
();
} // ---- captured records ----------------------------------------------- struct
(struct) cpu_pmu_sampling_symbolize.Mapping
Mapping
{ ulong
(field) ulong cpu_pmu_sampling_symbolize.Mapping.addr
addr
,
(field) ulong cpu_pmu_sampling_symbolize.Mapping.len
len
,
(field) ulong cpu_pmu_sampling_symbolize.Mapping.pgoff
pgoff
;
uint
(field) uint cpu_pmu_sampling_symbolize.Mapping.prot
prot
;
(alias) object.string = string
string
(field) string cpu_pmu_sampling_symbolize.Mapping.filename
filename
;
} __gshared ulong
(__gshared global) ulong cpu_pmu_sampling_symbolize.sink
sink
;
/// Two deliberately non-inlined hot functions, so sampled IPs land in /// named symbols we can point at. pragma(inline, false) ulong
ulong cpu_pmu_sampling_symbolize.mixHash(ulong x)

Two deliberately non-inlined hot functions, so sampled IPs land in named symbols we can point at.

mixHash
(ulong
(parameter) ulong x
x
)
{ foreach (
(local variable) int _
_
; 0 .. 96)
(parameter) ulong x
x
= (
(parameter) ulong x
x
* 6364136223846793005UL + 1442695040888963407UL) ^ (
(parameter) ulong x
x
>> 29);
return
(parameter) ulong x
x
;
} pragma(inline, false) ulong
ulong cpu_pmu_sampling_symbolize.sumSquares(ulong n)
sumSquares
(ulong
(parameter) ulong n
n
)
{ ulong
(local variable) ulong s
s
= 0;
foreach (
(local variable) ulong i
i
; 0 ..
(parameter) ulong n
n
)
(local variable) ulong s
s
+=
(local variable) ulong i
i
*
(local variable) ulong i
i
;
return
(local variable) ulong s
s
;
} void
void cpu_pmu_sampling_symbolize.workload()
workload
()
{ auto
(local variable) core.time.MonoTimeImpl!(ClockType.normal) deadline
deadline
=
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
+ 500.msecs;
ulong
(local variable) ulong acc
acc
= 0x1234_5678_9ABC_DEF0UL;
while (
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
<
(local variable) core.time.MonoTimeImpl!(ClockType.normal) deadline
deadline
)
{
(local variable) ulong acc
acc
+=
ulong cpu_pmu_sampling_symbolize.mixHash(ulong x)

Two deliberately non-inlined hot functions, so sampled IPs land in named symbols we can point at.

mixHash
(
(local variable) ulong acc
acc
);
(local variable) ulong acc
acc
+=
ulong cpu_pmu_sampling_symbolize.sumSquares(ulong n)
sumSquares
(2048);
}
(__gshared global) ulong cpu_pmu_sampling_symbolize.sink
sink
+=
(local variable) ulong acc
acc
;
} int
int cpu_pmu_sampling_symbolize.run()
run
()
{ const
(local variable) const(ulong) pageSize
pageSize
= cast(
(alias) object.size_t = ulong
size_t
)
long core.sys.posix.unistd.sysconf(int) nothrow @nogc @trusted
sysconf
(
(enum value) core.sys.posix.unistd._SC_PAGESIZE = 30
_SC_PAGESIZE
);
enum
(constant) int cpu_pmu_sampling_symbolize.run.dataPages = 256
dataPages
= 256; // power of two
const
(local variable) const(ulong) dataSize
dataSize
=
(constant) int cpu_pmu_sampling_symbolize.run.dataPages = 256
dataPages
*
(local variable) const(ulong) pageSize
pageSize
;
const
(local variable) const(ulong) mmapSize
mmapSize
= (1 +
(constant) int cpu_pmu_sampling_symbolize.run.dataPages = 256
dataPages
) *
(local variable) const(ulong) pageSize
pageSize
;
// Sampling event: cycles at ~4 kHz, user-space only so every IP is // symbolizable against the process image. IP+TID+TIME per sample; the // kernel also emits MMAP2 for executable mappings (attr.mmap2 = 1).
(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
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
;
(local variable) core.sys.linux.perf_event.perf_event_attr 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
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.type

Major type: hardware/software/tracepoint/etc.

type
=
(enum) core.sys.linux.perf_event.perf_type_id

attr.type

perf_type_id
.
(enum value) core.sys.linux.perf_event.perf_type_id.PERF_TYPE_HARDWARE = 0
PERF_TYPE_HARDWARE
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.config

Type specific configuration information.

config
=
(enum) core.sys.linux.perf_event.perf_hw_id

Generalized 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 = 0
PERF_COUNT_HW_CPU_CYCLES
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.sample_type
sample_type
=
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_IP = 1u
PERF_SAMPLE_IP
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_TID = 2u
PERF_SAMPLE_TID
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_TIME = 4u
PERF_SAMPLE_TIME
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.freq(ulong v) pure nothrow @nogc @property @safe
freq
= 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.sample_freq
sample_freq
= 4000;
(local variable) 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;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.exclude_kernel(ulong v) pure nothrow @nogc @property @safe
exclude_kernel
= 1;
(local variable) 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;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.mmap(ulong v) pure nothrow @nogc @property @safe
mmap
= 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.mmap2(ulong v) pure nothrow @nogc @property @safe
mmap2
= 1;
int
(local variable) int fd
fd
= (() @trusted => 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
(&
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
, 0, -1, -1, 0))();
if (
(local variable) int fd
fd
< 0)
{
void std.stdio.writefln!char(in char[] fmt) @safe

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

writefln
("SKIP: perf_event_open (sampling) failed — perf_event_paranoid, "
~ "seccomp, or no PMU on this host"); return 0; } void*
(local variable) void* base
base
= (() @trusted =>
void* core.sys.posix.sys.mman.mmap64(void*, ulong, int, int, int, long) nothrow @nogc
mmap
(null,
(local variable) const(ulong) mmapSize
mmapSize
,
(constant) int core.sys.posix.sys.mman.PROT_READ = 1
PROT_READ
|
(constant) int core.sys.posix.sys.mman.PROT_WRITE = 2
PROT_WRITE
,
(constant) int core.sys.posix.sys.mman.MAP_SHARED = 1
MAP_SHARED
,
(local variable) int fd
fd
, 0))();
if (
(local variable) void* base
base
is
(constant) void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
)
{
void std.stdio.writefln!char(in char[] fmt) @safe

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

writefln
("SKIP: mmap of the perf ring buffer failed "
~ "(perf_event_mlock_kb too small?)");
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) int fd
fd
);
return 0; } auto
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
= cast(
(struct) core.sys.linux.perf_event.perf_event_mmap_page

Structure of the page that can be mapped via mmap

perf_event_mmap_page
*)
(local variable) void* base
base
;
auto
(local variable) ubyte* dataArea
dataArea
= cast(ubyte*)
(local variable) void* base
base
+
(local variable) const(ulong) pageSize
pageSize
;
// A fresh PROT_EXEC mapping of our own binary, created *inside* the // enabled window, so the kernel emits a real PERF_RECORD_MMAP2 we can // capture (pre-existing code is never re-emitted — see the header note). int
(local variable) int exeFd
exeFd
= (() @trusted => open("/proc/self/exe",
(constant) int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
))();
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219
PERF_EVENT_IOC_RESET
, 0);
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(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
, 0);
void*
(local variable) void* exeMap
exeMap
=
(constant) void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
;
if (
(local variable) int exeFd
exeFd
>= 0)
(local variable) void* exeMap
exeMap
= (() @trusted =>
void* core.sys.posix.sys.mman.mmap64(void*, ulong, int, int, int, long) nothrow @nogc
mmap
(null,
(local variable) const(ulong) pageSize
pageSize
,
(constant) int core.sys.posix.sys.mman.PROT_READ = 1
PROT_READ
|
(constant) int core.sys.posix.sys.mman.PROT_EXEC = 4
PROT_EXEC
,
(constant) int core.sys.posix.sys.mman.MAP_PRIVATE = 2
MAP_PRIVATE
,
(local variable) int exeFd
exeFd
, 0))();
void cpu_pmu_sampling_symbolize.workload()
workload
();
if (
(local variable) void* exeMap
exeMap
!is
(constant) void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
)
(() @trusted =>
int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogc
munmap
(
(local variable) void* exeMap
exeMap
,
(local variable) const(ulong) pageSize
pageSize
))();
if (
(local variable) int exeFd
exeFd
>= 0)
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) int exeFd
exeFd
);
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217
PERF_EVENT_IOC_DISABLE
, 0);
// ---- drain the ring: data_tail .. data_head, wrapping mod dataSize // (the reader-side seqcount contract: acquire-load head, process, then // release-store the new tail). const
(local variable) const(ulong) head
head
=
ulong core.atomic.atomicLoad!(MemoryOrder.acq, ulong)(ref return scope const(ulong) val) pure nothrow @nogc @trusted

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
!(
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
.
(enum value) core.atomic.MemoryOrder.acq = 2

Hoist-load + hoist-store barrier. Corresponds to LLVM AtomicOrdering.Acquire and C++11/C11 memory_order_acquire.

acq
)(
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_head

Control data for the mmap() data buffer.

User-space reading the @data_head value should issue an smp_rmb(), after reading this value.

When the mapping is PROT_WRITE the @data_tail value should be written by userspace to reflect the last read data, after issueing an smp_mb() to separate the data read from the ->data_tail store. In this case the kernel will not over-write unread data.

See perf_output_put_handle() for the data ordering.

data_{offset,size} indicate the location and size of the perf record buffer within the mmapped area.

head in the data section

data_head
);
ulong
(local variable) ulong tail
tail
=
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_tail

user-space written tail

data_tail
;
(struct) cpu_pmu_sampling_symbolize.Mapping
Mapping
[]
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
;
ulong[]
(local variable) ulong[] ips
ips
;
ulong
(local variable) ulong lost
lost
= 0;
ubyte[8192]
(local variable) ubyte[8192] rec
rec
;
void
void cpu_pmu_sampling_symbolize.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(ulong
(parameter) ulong pos
pos
, ubyte*
(parameter) ubyte* dst
dst
,
(alias) object.size_t = ulong
size_t
(parameter) ulong n
n
) @trusted
{ const
(local variable) const(ulong) o
o
=
(parameter) ulong pos
pos
%
(local variable) const(ulong) dataSize
dataSize
;
if (
(local variable) const(ulong) o
o
+
(parameter) ulong n
n
<=
(local variable) const(ulong) dataSize
dataSize
)
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
,
(local variable) ubyte* dataArea
dataArea
+
(local variable) const(ulong) o
o
,
(parameter) ulong n
n
);
else { const
(local variable) const(ulong) first
first
= cast(
(alias) object.size_t = ulong
size_t
)(
(local variable) const(ulong) dataSize
dataSize
-
(local variable) const(ulong) o
o
);
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
,
(local variable) ubyte* dataArea
dataArea
+
(local variable) const(ulong) o
o
,
(local variable) const(ulong) first
first
);
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
+
(local variable) const(ulong) first
first
,
(local variable) ubyte* dataArea
dataArea
,
(parameter) ulong n
n
-
(local variable) const(ulong) first
first
);
} } while (
(local variable) ulong tail
tail
<
(local variable) const(ulong) head
head
)
{
(struct) core.sys.linux.perf_event.perf_event_header
perf_event_header
(local variable) core.sys.linux.perf_event.perf_event_header h
h
;
void cpu_pmu_sampling_symbolize.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(
(local variable) ulong tail
tail
, cast(ubyte*)&
(local variable) core.sys.linux.perf_event.perf_event_header h
h
,
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(constant) ulong core.sys.linux.perf_event.perf_event_header.sizeof = 8LU
sizeof
);
if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
== 0)
break;
(alias) object.size_t = ulong
size_t
(local variable) ulong sz
sz
=
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
;
if (
(local variable) ulong sz
sz
>
(local variable) ubyte[8192] rec
rec
.
(constant) ulong ubyte[8192].length = 8192LU
length
)
(local variable) ulong sz
sz
=
(local variable) ubyte[8192] rec
rec
.
(constant) ulong ubyte[8192].length = 8192LU
length
;
void cpu_pmu_sampling_symbolize.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(
(local variable) ulong tail
tail
,
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
,
(local variable) ulong sz
sz
);
(local variable) ulong tail
tail
+=
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
;
if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) uint core.sys.linux.perf_event.perf_event_header.type
type
==
(enum) core.sys.linux.perf_event.perf_event_type
perf_event_type
.
(enum value) core.sys.linux.perf_event.perf_event_type.PERF_RECORD_SAMPLE = 9
struct {
   struct perf_event_header    header;

   #
   # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
   # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
   # is fixed relative to header.
   #

   { u64            id;      } && PERF_SAMPLE_IDENTIFIER
   { u64            ip;      } && PERF_SAMPLE_IP
   { u32            pid, tid; } && PERF_SAMPLE_TID
   { u64            time;     } && PERF_SAMPLE_TIME
   { u64            addr;     } && PERF_SAMPLE_ADDR
   { u64            id;      } && PERF_SAMPLE_ID
   { u64            stream_id;} && PERF_SAMPLE_STREAM_ID
   { u32            cpu, res; } && PERF_SAMPLE_CPU
   { u64            period;   } && PERF_SAMPLE_PERIOD

   { struct read_format    values;      } && PERF_SAMPLE_READ

   { u64            nr,
     u64            ips[nr];  } && PERF_SAMPLE_CALLCHAIN

   #
   # The RAW record below is opaque data wrt the ABI
   #
   # That is, the ABI doesn't make any promises wrt to
   # the stability of its content, it may vary depending
   # on event, hardware, kernel version and phase of
   # the moon.
   #
   # In other words, PERF_SAMPLE_RAW contents are not an ABI.
   #

   { u32            size;
     char                  data[size];}&& PERF_SAMPLE_RAW

   { u64                   nr;
       { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK

    { u64            abi; # enum perf_sample_regs_abi
      u64            regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER

    { u64            size;
      char            data[size];
      u64            dyn_size; } && PERF_SAMPLE_STACK_USER

   { u64            weight;   } && PERF_SAMPLE_WEIGHT
   { u64            data_src; } && PERF_SAMPLE_DATA_SRC
   { u64            transaction; } && PERF_SAMPLE_TRANSACTION
   { u64            abi; # enum perf_sample_regs_abi
     u64            regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
   { u64            phys_addr;} && PERF_SAMPLE_PHYS_ADDR
};
PERF_RECORD_SAMPLE
)
{ // body: ip(u64), pid(u32), tid(u32), time(u64)
(local variable) ulong[] ips
ips
~= *(() @trusted => cast(ulong*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 8))();
} else if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) uint core.sys.linux.perf_event.perf_event_header.type
type
==
(enum) core.sys.linux.perf_event.perf_event_type
perf_event_type
.
(enum value) core.sys.linux.perf_event.perf_event_type.PERF_RECORD_MMAP2 = 10
The MMAP2 records are an augmented version of MMAP, they add
maj, min, ino numbers to be used to uniquely identify each mapping

struct {
   struct perf_event_header    header;

   u32                pid, tid;
   u64                addr;
   u64                len;
   u64                pgoff;
   u32                maj;
   u32                min;
   u64                ino;
   u64                ino_generation;
   u32                prot, flags;
   char                filename[];
    struct sample_id        sample_id;
};
PERF_RECORD_MMAP2
)
{ // body offsets (after 8-byte header): addr@16 len@24 pgoff@32 // maj@40 min@44 ino@48 ino_gen@56 prot@64 flags@68 filename@72
(struct) cpu_pmu_sampling_symbolize.Mapping
Mapping
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
;
(() @trusted {
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.addr
addr
= *cast(ulong*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 16);
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.len
len
= *cast(ulong*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 24);
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.pgoff
pgoff
= *cast(ulong*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 32);
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) uint cpu_pmu_sampling_symbolize.Mapping.prot
prot
= *cast(uint*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 64);
auto
(local variable) char* fn
fn
= cast(char*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 72);
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) string cpu_pmu_sampling_symbolize.Mapping.filename
filename
=
inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @system
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
(
(local variable) char* fn
fn
).
string object.idup!char(char[] a) pure nothrow @property @safe

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

idup
;
})();
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
~=
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
;
} else if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) uint core.sys.linux.perf_event.perf_event_header.type
type
==
(enum) core.sys.linux.perf_event.perf_event_type
perf_event_type
.
(enum value) core.sys.linux.perf_event.perf_event_type.PERF_RECORD_LOST = 2
struct {
   struct perf_event_header    header;
   u64                id;
   u64                lost;
    struct sample_id        sample_id;
};
PERF_RECORD_LOST
)
(local variable) ulong lost
lost
+= *(() @trusted => cast(ulong*)(
(local variable) ubyte[8192] rec
rec
.
(constant) ubyte* ubyte[8192].ptr = &rec
ptr
+ 8 + 8))(); // id(u64), lost(u64)
}
void core.atomic.atomicStore!(MemoryOrder.rel, ulong, const(ulong))(ref ulong val, const(ulong) newval) pure nothrow @nogc @trusted

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
!(
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
.
(enum value) core.atomic.MemoryOrder.rel = 3

Sink-load + sink-store barrier. Corresponds to LLVM AtomicOrdering.Release and C++11/C11 memory_order_release.

rel
)(
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_tail

user-space written tail

data_tail
,
(local variable) const(ulong) head
head
);
(() @trusted =>
int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogc
munmap
(
(local variable) void* base
base
,
(local variable) const(ulong) mmapSize
mmapSize
))();
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) int fd
fd
);
void std.stdio.writefln!(char, ulong, ulong, string)(in char[] fmt, ulong __param_1, ulong __param_2, string __param_3) @safe

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

writefln
("captured: %d PERF_RECORD_MMAP2 mappings, %d IP samples%s",
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping[].length
length
,
(local variable) ulong[] ips
ips
.
(field) ulong ulong[].length
length
,
(local variable) ulong lost
lost
? " (" ~ "some LOST — ring overflow" ~ ")" : "");
if (
(local variable) ulong[] ips
ips
.
(field) ulong ulong[].length
length
== 0)
{
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
("note: no samples captured (workload too short, or overflow "
~ "interrupts denied) — nothing to symbolize, but the ring path ran"); return 0; } // ---- symbolize via libdwfl: build the module model from the live // process, then addr -> symbol -> line for each IP ------------ __gshared
(struct) cpu_pmu_sampling_symbolize.DwflCallbacks

Dwfl_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:72) as four pointers: find_elf, find_debuginfo, section_address, debuginfo_path.

DwflCallbacks
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
;
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
.
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.find_elf
find_elf
= (() @trusted => cast(void*)&
int cpu_pmu_sampling_symbolize.dwfl_linux_proc_find_elf() nothrow @nogc
dwfl_linux_proc_find_elf
)();
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
.
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.find_debuginfo
find_debuginfo
= (() @trusted => cast(void*)&
int cpu_pmu_sampling_symbolize.dwfl_standard_find_debuginfo() nothrow @nogc
dwfl_standard_find_debuginfo
)();
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
.
(field) void* cpu_pmu_sampling_symbolize.DwflCallbacks.section_address
section_address
= null;
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
.
(field) char** cpu_pmu_sampling_symbolize.DwflCallbacks.debuginfo_path
debuginfo_path
= null;
(struct) cpu_pmu_sampling_symbolize.Dwfl
Dwfl
*
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
= (() @trusted =>
cpu_pmu_sampling_symbolize.Dwfl* cpu_pmu_sampling_symbolize.dwfl_begin(const(cpu_pmu_sampling_symbolize.DwflCallbacks)*) nothrow @nogc
dwfl_begin
(&
(__gshared global) cpu_pmu_sampling_symbolize.DwflCallbacks cpu_pmu_sampling_symbolize.run.cb
cb
))();
bool
(local variable) bool symbolized
symbolized
= false;
int[
(alias) object.string = string
string
]
(local variable) int[string] symCount
symCount
;
(alias) object.string = string
string
[
(alias) object.string = string
string
]
(local variable) string[string] symLine
symLine
; // representative file:line per symbol
ulong[
(alias) object.string = string
string
]
(local variable) ulong[string] symIp
symIp
; // representative IP per symbol
if (
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
!is null)
{ const
(local variable) const(int) rc1
rc1
= (() @trusted =>
int cpu_pmu_sampling_symbolize.dwfl_linux_proc_report(cpu_pmu_sampling_symbolize.Dwfl*, int pid) nothrow @nogc
dwfl_linux_proc_report
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
,
int core.sys.posix.unistd.getpid() nothrow @nogc @trusted
getpid
()))();
const
(local variable) const(int) rc2
rc2
= (() @trusted =>
int cpu_pmu_sampling_symbolize.dwfl_report_end(cpu_pmu_sampling_symbolize.Dwfl*, void* removed, void* arg) nothrow @nogc
dwfl_report_end
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
, null, null))();
if (
(local variable) const(int) rc1
rc1
== 0 &&
(local variable) const(int) rc2
rc2
== 0)
{
(local variable) bool symbolized
symbolized
= true;
foreach (
(parameter) ulong ip
ip
;
(local variable) ulong[] ips
ips
)
{ auto
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Module* mod
mod
= (() @trusted =>
cpu_pmu_sampling_symbolize.Dwfl_Module* cpu_pmu_sampling_symbolize.dwfl_addrmodule(cpu_pmu_sampling_symbolize.Dwfl*, ulong) nothrow @nogc
dwfl_addrmodule
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
,
(local variable) ulong ip
ip
))();
if (
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Module* mod
mod
is null)
{
int* core.internal.newaa._d_aaGetY!(string, int, int[string], string, int, string)(ref scope int[string] aa, string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
symCount
["<no module>"]++;
continue; }
(alias) cpu_pmu_sampling_symbolize.GElf_Off = ulong
GElf_Off
(local variable) ulong off
off
;
(struct) cpu_pmu_sampling_symbolize.GElf_Sym

Elf64_Sym (== GElf_Sym on LP64) — dwfl fills this; we read st_value.

GElf_Sym
(local variable) cpu_pmu_sampling_symbolize.GElf_Sym sym
sym
;
const
(local variable) const(char*) namez
namez
= (() @trusted =>
const(char)* cpu_pmu_sampling_symbolize.dwfl_module_addrinfo(cpu_pmu_sampling_symbolize.Dwfl_Module*, ulong, ulong*, cpu_pmu_sampling_symbolize.GElf_Sym*, uint*, cpu_pmu_sampling_symbolize.Elf**, ulong*) nothrow @nogc
dwfl_module_addrinfo
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Module* mod
mod
,
(local variable) ulong ip
ip
, &
(local variable) ulong off
off
, &
(local variable) cpu_pmu_sampling_symbolize.GElf_Sym sym
sym
, null, null, null))();
(alias) object.string = string
string
(local variable) string name
name
=
(local variable) const(char*) namez
namez
?
inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @system
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
(
(local variable) const(char*) namez
namez
).
string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safe

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

idup
: "<unknown>";
int* core.internal.newaa._d_aaGetY!(string, int, int[string], string, int, string)(ref scope int[string] aa, ref string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
symCount
[
(local variable) string name
name
]++;
if (
(local variable) string name
name
!in
(local variable) ulong[string] symIp
symIp
)
ulong* core.internal.newaa._d_aaGetY!(string, ulong, ulong[string], string, ulong, string)(ref scope ulong[string] aa, ref string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
symIp
[
ulong* core.internal.newaa._d_aaGetY!(string, ulong, ulong[string], string, ulong, string)(ref scope ulong[string] aa, ref string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
name
] =
(local variable) ulong ip
ip
;
if (
(local variable) string name
name
!in
(local variable) string[string] symLine
symLine
)
{ auto
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Line* line
line
= (() @trusted =>
cpu_pmu_sampling_symbolize.Dwfl_Line* cpu_pmu_sampling_symbolize.dwfl_module_getsrc(cpu_pmu_sampling_symbolize.Dwfl_Module*, ulong) nothrow @nogc
dwfl_module_getsrc
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Module* mod
mod
,
(local variable) ulong ip
ip
))();
if (
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Line* line
line
!is null)
{ int
(local variable) int lineno
lineno
;
auto
(local variable) const(char)* srcz
srcz
= (() @trusted =>
const(char)* cpu_pmu_sampling_symbolize.dwfl_lineinfo(cpu_pmu_sampling_symbolize.Dwfl_Line*, ulong*, int*, int*, ulong*, ulong*) nothrow @nogc
dwfl_lineinfo
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl_Line* line
line
, null, &
(local variable) int lineno
lineno
, null, null, null))();
if (
(local variable) const(char)* srcz
srcz
)
{ import
(package) std
std
.
(module) std.path

This module is used to manipulate path strings.

All functions, with the exception of expandTilde (and in some cases absolutePath and relativePath), are pure string manipulation functions; they don't depend on any state outside the program, nor do they perform any actual file system actions. This has the consequence that the module does not make any distinction between a path that points to a directory and a path that points to a file, and it does not know whether or not the object pointed to by the path actually exists in the file system. To differentiate between these cases, use isDir and exists.

Note that on Windows, both the backslash (\) and the slash (/) are in principle valid directory separators. This module treats them both on equal footing, but in cases where a new separator is added, a backslash will be used. Furthermore, the buildNormalizedPath function will replace all slashes with backslashes on that platform.

In general, the functions in this module assume that the input paths are well-formed. (That is, they should not contain invalid characters, they should follow the file system's path format, etc.) The result of calling a function on an ill-formed path is undefined. When there is a chance that a path or a file name is invalid (for instance, when it has been input by the user), it may sometimes be desirable to use the isValidFilename and isValidPath functions to check this.

Most functions do not perform any memory allocations, and if a string is returned, it is usually a slice of an input string. If a function allocates, this is explicitly mentioned in the documentation.

Category Functions
Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde
Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive
Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath
Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension
Other filenameCharCmp filenameCmp globMatch CaseSensitive

Source

std/path.d

@authorsLars Tandle Kyllingstad, Walter Bright, Grzegorz Adam Hankiewicz, Thomas Khne, Andrei Alexandrescu@copyrightCopyright (c) 2000-2014, the authors. All rights reserved.@licenseBoost License 1.0
path
:
(alias template) baseName = std.path.baseName(R)(return scope R path) if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) && !isSomeString!R)

Params: cs = Whether or not suffix matching is case-sensitive. path = A path name. It can be a string, or any random-access range of characters. suffix = An optional suffix to be removed from the file name. Returns: The name of the file in the path name, without any leading directory and with an optional suffix chopped off.

    If `suffix` is specified, it will be compared to `path`
    using `filenameCmp!cs`,
    where `cs` is an optional template parameter determining whether
    the comparison is case sensitive or not.  See the
    $(LREF filenameCmp) documentation for details.

    Note:
    This function $(I only) strips away the specified suffix, which
    doesn't necessarily have to represent an extension.
    To remove the extension from a path, regardless of what the extension
    is, use $(LREF stripExtension).
    To obtain the filename without leading directories and without
    an extension, combine the functions like this:
    ---
    assert(baseName(stripExtension("dir/file.ext")) == "file");
    ---

    Standards:
    This function complies with
    $(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html,
    the POSIX requirements for the 'basename' shell utility)
    (with suitable adaptations for Windows paths).
baseName
;
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
;
string* core.internal.newaa._d_aaGetY!(string, string, string[string], string, string, string)(ref scope string[string] aa, ref string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
symLine
[
string* core.internal.newaa._d_aaGetY!(string, string, string[string], string, string, string)(ref scope string[string] aa, ref string key, out bool found) pure nothrow @safe

Lookup key in aa. Called only from implementation of (aakey) expressions when value is mutable.

@paramaa associative array@paramkey reference to the key value@paramfound returns whether the key was found or a new entry was added@returnsif key was in the aa, a mutable pointer to the existing value. If key was not in the aa, a mutable pointer to newly inserted value which is set to zero
name
] =
string std.path.baseName!(immutable(char))(return scope string path) pure nothrow @nogc @safe

Note

This function only strips away the specified suffix, which doesn't necessarily have to represent an extension. To remove the extension from a path, regardless of what the extension is, use stripExtension. To obtain the filename without leading directories and without an extension, combine the functions like this:

assert(baseName(stripExtension("dir/file.ext")) == "file");
@paramcs Whether or not suffix matching is case-sensitive.@parampath A path name. It can be a string, or any random-access range of characters.@paramsuffix An optional suffix to be removed from the file name.@returns

The name of the file in the path name, without any leading directory and with an optional suffix chopped off.

If suffix is specified, it will be compared to path using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.

@standardsThis function complies with the POSIX requirements for the 'basename' shell utility (with suitable adaptations for Windows paths).
baseName
(
inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @system
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
(
(local variable) const(char)* srcz
srcz
).
string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safe

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

idup
) ~ ":" ~
(local variable) int lineno
lineno
.
string std.conv.to!string.to!int(int __param_0) pure nothrow @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
!
(alias) object.string = string
string
;
} } } } } } if (!
(local variable) bool symbolized
symbolized
)
{
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
("note: libdwfl unavailable/failed to report modules — "
~ "capture succeeded; symbolization skipped"); (() @trusted { if (
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
)
void cpu_pmu_sampling_symbolize.dwfl_end(cpu_pmu_sampling_symbolize.Dwfl*) nothrow @nogc
dwfl_end
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
); })();
return 0; } // Top symbols by sample count. import
(package) std
std
.
(module) std.algorithm

This package implements generic algorithms oriented towards the processing of sequences. Sequences processed by these functions define range-based interfaces. See also Reference on ranges and tutorial on ranges.

Algorithms are categorized into the following submodules:

Submodule Functions

| Searching | all any balancedParens boyerMooreFinder canFind commonPrefix count countUntil endsWith find findAdjacent findAmong findSkip findSplit findSplitAfter findSplitBefore minCount maxCount minElement maxElement minIndex maxIndex minPos maxPos skipOver startsWith until |

| Comparison | among castSwitch clamp cmp either equal isPermutation isSameLength levenshteinDistance levenshteinDistanceAndPath max min mismatch predSwitch |

| Iteration | cache cacheBidirectional chunkBy cumulativeFold each filter filterBidirectional fold group joiner map mean permutations reduce splitWhen splitter substitute sum uniq |

| Sorting | completeSort isPartitioned isSorted isStrictlyMonotonic ordered strictlyOrdered makeIndex merge multiSort nextEvenPermutation nextPermutation nthPermutation partialSort partition partition3 schwartzSort sort topN topNCopy topNIndex |

| Set operations (setops) | cartesianProduct largestPartialIntersection largestPartialIntersectionWeighted multiwayMerge multiwayUnion setDifference setIntersection setSymmetricDifference |

| Mutation | bringToFront copy fill initializeAll move moveAll moveSome moveEmplace moveEmplaceAll moveEmplaceSome remove reverse strip stripLeft stripRight swap swapRanges uninitializedFill |

Many functions in this package are parameterized with a predicate. The predicate may be any suitable callable type (a function, a delegate, a functor, or a lambda), or a compile-time string. The string may consist of any legal D expression that uses the symbol a (for unary functions) or the symbols a and b (for binary functions). These names will NOT interfere with other homonym symbols in user code because they are evaluated in a different context. The default for all binary comparison predicates is "a == b" for unordered operations and "a < b" for ordered operations.

Example

int[] a = ...;
static bool greater(int a, int b)
{
    return a > b;
}
sort!greater(a);           // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a);           // predicate as string
                           // (no ambiguity with array name)
sort(a);                   // no predicate, "a < b" is implicit

Source

std/algorithm/package.d

@copyrightAndrei Alexandrescu 2008-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu
algorithm
:
(alias template) sort = std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)

Sorts a random-access range according to the predicate less.

Performs $(BIGOH r.length * log(r.length)) evaluations of `less`. If `less` involves expensive computations on the _sort key, it may be worthwhile to use $(LREF schwartzSort) instead.

Stable sorting requires hasAssignableElements!Range to be true.

sort returns a $(REF SortedRange, std,range) over the original range, allowing functions that can take advantage of sorted data to know that the range is sorted and adjust accordingly. The $(REF SortedRange, std,range) is a wrapper around the original range, so both it and the original range are sorted. Other functions can't know that the original range has been sorted, but they $(I can) know that $(REF SortedRange, std,range) has been sorted.

Preconditions:

The predicate is expected to satisfy certain rules in order for sort to behave as expected - otherwise, the program may fail on certain inputs (but not others) when not compiled in release mode, due to the cursory assumeSorted check. Specifically, sort expects less(a,b) && less(b,c) to imply less(a,c) (transitivity), and, conversely, !less(a,b) && !less(b,c) to imply !less(a,c). Note that the default predicate ("a < b") does not always satisfy these conditions for floating point types, because the expression will always be false when either a or b is NaN. Use $(REF cmp, std,math) instead.

Params: less = The predicate to sort by. ss = The swapping strategy to use. r = The range to sort.

Returns: The initial range wrapped as a SortedRange with the predicate binaryFun!less.

Algorithms: $(HTTP en.wikipedia.org/wiki/Introsort, Introsort) is used for unstable sorting and $(HTTP en.wikipedia.org/wiki/Timsort, Timsort) is used for stable sorting. Each algorithm has benefits beyond stability. Introsort is generally faster but Timsort may achieve greater speeds on data with low entropy or if predicate calls are expensive. Introsort performs no allocations whereas Timsort will perform one or more allocations per call. Both algorithms have $(BIGOH n log n) worst-case time complexity.

See_Also: $(REF assumeSorted, std,range)$(BR) $(REF SortedRange, std,range)$(BR) $(REF SwapStrategy, std,algorithm,mutation)$(BR) $(REF binaryFun, std,functional)

sort
;
import
(package) std
std
.
(module) std.array

Functions and types that manipulate built-in arrays and associative arrays.

This module provides all kinds of functions to create, manipulate or convert arrays:

Function Name Description

| array | Returns a copy of the input in a newly allocated dynamic array. | | appender | Returns a new Appender or RefAppender initialized with a given array. | | assocArray | Returns a newly allocated associative array from a range/ranges of keys and values. | | byPair | Construct a range iterating over an associative array by key/value tuples. | | insertInPlace | Inserts into an existing array at a given position. | | join | Concatenates a range of ranges into one array. | | minimallyInitializedArray | Returns a new array of type T. | | replace | Returns a new array with all occurrences of a certain subrange replaced. | | replaceFirst | Returns a new array with the first occurrence of a certain subrange replaced. | | replaceInPlace | Replaces all occurrences of a certain subrange and puts the result into a given array. | | replaceInto | Replaces all occurrences of a certain subrange and puts the result into an output range. | | replaceLast | Returns a new array with the last occurrence of a certain subrange replaced. | | replaceSlice | Returns a new array with a given slice replaced. | | replicate | Creates a new array out of several copies of an input array or range. | | sameHead | Checks if the initial segments of two arrays refer to the same place in memory. | | sameTail | Checks if the final segments of two arrays refer to the same place in memory. | | split | Eagerly split a range or string into an array. | | staticArray | Creates a new static array from given data. | | uninitializedArray | Returns a new array of type T without initializing its elements. |

Source

std/array.d

@copyrightCopyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu and Jonathan M Davis
array
:
(alias template) array = std.array.array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)

Allocates an array and initializes it with copies of the elements of range r.

Narrow strings are handled as follows:

  • If autodecoding is turned on (default), then they are handled as a separate overload.

  • If autodecoding is turned off, then this is equivalent to duplicating the array.

Params: r = range (or aggregate with opApply function) whose elements are copied into the allocated array Returns: allocated and initialized array

array
;
auto
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair[] rows
rows
=
(local variable) int[string] symCount
symCount
.
object.byKeyValue!(int[string], string, int).Result object.byKeyValue!(int[string], string, int)(int[string] aa) pure nothrow @nogc @safe

Returns a forward range which will iterate over the key-value pairs of the associative array. The returned pairs are represented by an opaque type with .key and .value properties for accessing references to the key and value of the pair, respectively.

If structural changes are made to the array (removing or adding keys), all ranges previously obtained through this function are invalidated. The following example program will dereference a null pointer:

 import std.stdio : writeln;

 auto dict = ["k1": 1, "k2": 2];
 auto kvRange = dict.byKeyValue;
 dict.clear;
 writeln(kvRange.front.key, ": ", kvRange.front.value);    // Segmentation fault

Note that this is a low-level interface to iterating over the associative array and is not compatible with the Tuple type in Phobos. For compatibility with Tuple, use std.array.byPair instead.

@paramaa The associative array.@returnsA forward range referencing the pairs of the associative array.
byKeyValue
.
object.byKeyValue!(int[string], string, int).Result.front.Pair[] std.array.array!(object.byKeyValue!(int[string], string, int).Result)(object.byKeyValue!(int[string], string, int).Result r) pure nothrow @safe

Allocates an array and initializes it with copies of the elements of range r.

Narrow strings are handled as follows:

  • If autodecoding is turned on (default), then they are handled as a separate overload.

  • If autodecoding is turned off, then this is equivalent to duplicating the array.

@paramr range (or aggregate with opApply function) whose elements are copied into the allocated array@returnsallocated and initialized array
array
;
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair[] rows
rows
.
cpu_pmu_sampling_symbolize.run.SortedRange!(Pair[], __lambda_L359_C20, SortedRangeOptions.assumeSorted) cpu_pmu_sampling_symbolize.run.sort!((a, b) => a.value > b.value, SwapStrategy.unstable, object.byKeyValue!(int[string], string, int).Result.front.Pair[])(object.byKeyValue!(int[string], string, int).Result.front.Pair[] r) pure nothrow @nogc @safe

Sorts a random-access range according to the predicate less.

Performs O(r.length * log(r.length)) evaluations of less. If less involves expensive computations on the sort key, it may be worthwhile to use schwartzSort instead.

Stable sorting requires hasAssignableElements!Range to be true.

sort returns a SortedRange over the original range, allowing functions that can take advantage of sorted data to know that the range is sorted and adjust accordingly. The SortedRange is a wrapper around the original range, so both it and the original range are sorted. Other functions can't know that the original range has been sorted, but they can know that SortedRange has been sorted.

Preconditions

The predicate is expected to satisfy certain rules in order for sort to behave as expected - otherwise, the program may fail on certain inputs (but not others) when not compiled in release mode, due to the cursory assumeSorted check. Specifically, sort expects less(a,b) && less(b,c) to imply less(a,c) (transitivity), and, conversely, !less(a,b) && !less(b,c) to imply !less(a,c). Note that the default predicate ("a < b") does not always satisfy these conditions for floating point types, because the expression will always be false when either a or b is NaN. Use cmp instead.

Algorithms

Introsort is used for unstable sorting and Timsort is used for stable sorting. Each algorithm has benefits beyond stability. Introsort is generally faster but Timsort may achieve greater speeds on data with low entropy or if predicate calls are expensive. Introsort performs no allocations whereas Timsort will perform one or more allocations per call. Both algorithms have O(n log n) worst-case time complexity.

Examples

int[] array = [ 1, 2, 3, 4 ];

// sort in descending order
array.sort!("a > b");
assert(array == [ 4, 3, 2, 1 ]);

// sort in ascending order
array.sort();
assert(array == [ 1, 2, 3, 4 ]);

// sort with reusable comparator and chain
alias myComp = (x, y) => x > y;
assert(array.sort!(myComp).release == [ 4, 3, 2, 1 ]);
// Showcase stable sorting
import std.algorithm.mutation : SwapStrategy;
string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words);
assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
// Sorting floating-point numbers in presence of NaN
double[] numbers = [-0.0, 3.0, -2.0, double.nan, 0.0, -double.nan];

import std.algorithm.comparison : equal;
import std.math.operations : cmp;
import std.math.traits : isIdentical;

sort!((a, b) => cmp(a, b) < 0)(numbers);

double[] sorted = [-double.nan, -2.0, -0.0, 0.0, 3.0, double.nan];
assert(numbers.equal!isIdentical(sorted));
@paramless The predicate to sort by.@paramss The swapping strategy to use.@paramr The range to sort.@returnsThe initial range wrapped as a SortedRange with the predicate binaryFun!less.@see

assumeSorted

SortedRange

SwapStrategy

binaryFun

sort
!((a, b) => a.value > b.value);
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
("top self-symbols (dwfl: name — samples — file:line):");
(alias) object.size_t = ulong
size_t
(local variable) ulong shown
shown
= 0;
foreach (
(parameter) object.byKeyValue!(int[string], string, int).Result.front.Pair r
r
;
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair[] rows
rows
)
{
void std.stdio.writefln!(char, string, int, string)(in char[] fmt, string __param_1, int __param_2, string __param_3) @safe

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

writefln
(" %-28s %6d %s",
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair r
r
.
string object.byKeyValue!(int[string], string, int).Result.front.Pair.key() inout pure nothrow @nogc @property ref @trusted
key
,
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair r
r
.
int object.byKeyValue!(int[string], string, int).Result.front.Pair.value() inout pure nothrow @nogc @property ref @trusted
value
,
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair r
r
.
string object.byKeyValue!(int[string], string, int).Result.front.Pair.key() inout pure nothrow @nogc @property ref @trusted
key
in
(local variable) string[string] symLine
symLine
?
(local variable) string* __aaget843
symLine
[
(local variable) string* __aaget843
r
.
string object.byKeyValue!(int[string], string, int).Result.front.Pair.key() inout pure nothrow @nogc @property ref @trusted
key
] : "(no DWARF line info)");
if (++
(local variable) ulong shown
shown
>= 8)
break; } // ---- the captured PERF_RECORD_MMAP2 stream ----------------------- import
(package) std
std
.
(module) std.path

This module is used to manipulate path strings.

All functions, with the exception of expandTilde (and in some cases absolutePath and relativePath), are pure string manipulation functions; they don't depend on any state outside the program, nor do they perform any actual file system actions. This has the consequence that the module does not make any distinction between a path that points to a directory and a path that points to a file, and it does not know whether or not the object pointed to by the path actually exists in the file system. To differentiate between these cases, use isDir and exists.

Note that on Windows, both the backslash (\) and the slash (/) are in principle valid directory separators. This module treats them both on equal footing, but in cases where a new separator is added, a backslash will be used. Furthermore, the buildNormalizedPath function will replace all slashes with backslashes on that platform.

In general, the functions in this module assume that the input paths are well-formed. (That is, they should not contain invalid characters, they should follow the file system's path format, etc.) The result of calling a function on an ill-formed path is undefined. When there is a chance that a path or a file name is invalid (for instance, when it has been input by the user), it may sometimes be desirable to use the isValidFilename and isValidPath functions to check this.

Most functions do not perform any memory allocations, and if a string is returned, it is usually a slice of an input string. If a function allocates, this is explicitly mentioned in the documentation.

Category Functions
Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde
Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive
Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath
Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension
Other filenameCharCmp filenameCmp globMatch CaseSensitive

Source

std/path.d

@authorsLars Tandle Kyllingstad, Walter Bright, Grzegorz Adam Hankiewicz, Thomas Khne, Andrei Alexandrescu@copyrightCopyright (c) 2000-2014, the authors. All rights reserved.@licenseBoost License 1.0
path
:
(alias template) baseName = std.path.baseName(R)(return scope R path) if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) && !isSomeString!R)

Params: cs = Whether or not suffix matching is case-sensitive. path = A path name. It can be a string, or any random-access range of characters. suffix = An optional suffix to be removed from the file name. Returns: The name of the file in the path name, without any leading directory and with an optional suffix chopped off.

    If `suffix` is specified, it will be compared to `path`
    using `filenameCmp!cs`,
    where `cs` is an optional template parameter determining whether
    the comparison is case sensitive or not.  See the
    $(LREF filenameCmp) documentation for details.

    Note:
    This function $(I only) strips away the specified suffix, which
    doesn't necessarily have to represent an extension.
    To remove the extension from a path, regardless of what the extension
    is, use $(LREF stripExtension).
    To obtain the filename without leading directories and without
    an extension, combine the functions like this:
    ---
    assert(baseName(stripExtension("dir/file.ext")) == "file");
    ---

    Standards:
    This function complies with
    $(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html,
    the POSIX requirements for the 'basename' shell utility)
    (with suitable adaptations for Windows paths).
baseName
;
void std.stdio.writefln!(char, ulong)(in char[] fmt, ulong __param_1) @safe

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

writefln
("\nPERF_RECORD_MMAP2 captured during the window: %d record(s)",
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping[].length
length
);
foreach (ref
(parameter) cpu_pmu_sampling_symbolize.Mapping m
m
;
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
)
void std.stdio.writefln!(char, ulong, ulong, ulong, uint, string)(in char[] fmt, ulong __param_1, ulong __param_2, ulong __param_3, uint __param_4, string __param_5) @safe

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

writefln
(" [0x%x, 0x%x) pgoff=0x%x prot=0x%x %s",
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.addr
addr
,
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.addr
addr
+
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.len
len
,
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping.pgoff
pgoff
,
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) uint cpu_pmu_sampling_symbolize.Mapping.prot
prot
,
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) string cpu_pmu_sampling_symbolize.Mapping.filename
filename
);
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
(" (the kernel re-emits MMAP2 only for mappings made while enabled; "
~ "pre-existing code is recovered from /proc/PID/maps — what dwfl reads.)"); // Tie the two halves together: the deliberate exe mapping's filename is // the same binary libdwfl symbolized our functions against.
(alias) object.string = string
string
(local variable) string hot
hot
=
(local variable) object.byKeyValue!(int[string], string, int).Result.front.Pair[] rows
rows
[0].
string object.byKeyValue!(int[string], string, int).Result.front.Pair.key() inout pure nothrow @nogc @property ref @trusted
key
;
enum
(constant) string cpu_pmu_sampling_symbolize.run.exeName = "cpu_pmu_sampling_symbolize"
exeName
= "cpu_pmu_sampling_symbolize"; // matches dub's `name`
bool
(local variable) bool exeSeen
exeSeen
= false;
foreach (ref
(parameter) cpu_pmu_sampling_symbolize.Mapping m
m
;
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
)
if (
(local variable) cpu_pmu_sampling_symbolize.Mapping m
m
.
(field) string cpu_pmu_sampling_symbolize.Mapping.filename
filename
.
string std.path.baseName!(immutable(char))(return scope string path) pure nothrow @nogc @safe

Note

This function only strips away the specified suffix, which doesn't necessarily have to represent an extension. To remove the extension from a path, regardless of what the extension is, use stripExtension. To obtain the filename without leading directories and without an extension, combine the functions like this:

assert(baseName(stripExtension("dir/file.ext")) == "file");
@paramcs Whether or not suffix matching is case-sensitive.@parampath A path name. It can be a string, or any random-access range of characters.@paramsuffix An optional suffix to be removed from the file name.@returns

The name of the file in the path name, without any leading directory and with an optional suffix chopped off.

If suffix is specified, it will be compared to path using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.

@standardsThis function complies with the POSIX requirements for the 'basename' shell utility (with suitable adaptations for Windows paths).
baseName
==
(constant) string cpu_pmu_sampling_symbolize.run.exeName = "cpu_pmu_sampling_symbolize"
exeName
)
{
(local variable) bool exeSeen
exeSeen
= true;
break; } if (
(local variable) bool exeSeen
exeSeen
&&
(local variable) string hot
hot
in
(local variable) ulong[string] symIp
symIp
)
void std.stdio.writefln!(char, string, ulong, string)(in char[] fmt, string __param_1, ulong __param_2, string __param_3) @safe

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

writefln
("model check: hottest symbol %s (IP 0x%x) was symbolized by libdwfl, "
~ "and a captured MMAP2 names the same image (%s).",
(local variable) string hot
hot
,
(local variable) ulong* __aaget859
symIp
[
(local variable) ulong* __aaget859
hot
],
(constant) string cpu_pmu_sampling_symbolize.run.exeName = "cpu_pmu_sampling_symbolize"
exeName
);
else if (
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
.
(field) ulong cpu_pmu_sampling_symbolize.Mapping[].length
length
)
void std.stdio.writefln!(char, string)(in char[] fmt, string __param_1) @safe

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

writefln
("model check: captured MMAP2 for %s; symbolization via /proc/self/maps.",
(local variable) cpu_pmu_sampling_symbolize.Mapping[] maps
maps
[0].
(field) string cpu_pmu_sampling_symbolize.Mapping.filename
filename
.
string std.path.baseName!(immutable(char))(return scope string path) pure nothrow @nogc @safe

Note

This function only strips away the specified suffix, which doesn't necessarily have to represent an extension. To remove the extension from a path, regardless of what the extension is, use stripExtension. To obtain the filename without leading directories and without an extension, combine the functions like this:

assert(baseName(stripExtension("dir/file.ext")) == "file");
@paramcs Whether or not suffix matching is case-sensitive.@parampath A path name. It can be a string, or any random-access range of characters.@paramsuffix An optional suffix to be removed from the file name.@returns

The name of the file in the path name, without any leading directory and with an optional suffix chopped off.

If suffix is specified, it will be compared to path using filenameCmp!cs, where cs is an optional template parameter determining whether the comparison is case sensitive or not. See the filenameCmp documentation for details.

@standardsThis function complies with the POSIX requirements for the 'basename' shell utility (with suitable adaptations for Windows paths).
baseName
);
else
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
("model check: no MMAP2 captured this window — symbolization still "
~ "succeeded via /proc/self/maps (the pre-existing-mapping path)."); (() @trusted =>
void cpu_pmu_sampling_symbolize.dwfl_end(cpu_pmu_sampling_symbolize.Dwfl*) nothrow @nogc
dwfl_end
(
(local variable) cpu_pmu_sampling_symbolize.Dwfl* dwfl
dwfl
))();
return 0; } } int
int D main()
main
()
{ version (
linux
linux
)
return
int cpu_pmu_sampling_symbolize.run()
run
();
else { import std.stdio : writefln; writefln("SKIP: perf_event sampling is Linux-only"); return 0; } }