added scopes

This commit is contained in:
peterino2 2025-10-31 00:36:14 -07:00
parent b5dad13bd7
commit c7cfa18ce9
1 changed files with 131 additions and 0 deletions

131
lib/p2/src/structures/pscopes.zig vendored Normal file
View File

@ -0,0 +1,131 @@
// pscopes
//
// a tiny scope based profiling library
//
// as well as contains info for arbitrary timestamping and timestamp resolution
const timestampTicks = if (builtin.target.cpu.arch == .x86_64) aarch64_ticks else rdtsc;
pub inline fn rdtsc_fenced() u64 {
var hi: u32 = 0;
var low: u32 = 0;
asm (
\\rdtsc
\\mfence
: [low] "={eax}" (low),
[hi] "={edx}" (hi),
);
return (@as(u64, hi) << 32) | @as(u64, low);
}
// rdtsc actually gets read
pub inline fn rdtsc() u64 {
var hi: u32 = 0;
var low: u32 = 0;
asm (
\\rdtsc
: [low] "={eax}" (low),
[hi] "={edx}" (hi),
);
return (@as(u64, hi) << 32) | @as(u64, low);
}
fn aarch64_ticks() u64 {
return asm volatile ("mrs %[ret], CNTVCT_EL0"
: [ret] "=r" (-> u64),
);
}
fn aarch64_freq() u64 {
return asm volatile ("mrs %[ret], CNTFRQ_EL0"
: [ret] "=r" (-> u64),
);
}
pub const TimingScope = struct {
// value in tsc ticks
startTsc: u64,
endTsc: ?u64 = null,
context: *ScopesContext,
pub inline fn init(c: *ScopesContext) @This() {
return .{
.startTsc = rdtsc(),
.context = c,
};
}
pub fn duration(self: *@This()) ?f64 {
_ = self;
}
pub inline fn end(self: *@This()) void {
self.endTsc = rdtsc();
}
};
pub const ScopesContext = struct {
allocator: std.mem.Allocator,
ticksPerMs: ?f64 = null,
timer: std.time.Timer,
pub fn timingScope(self: *@This()) TimingScope {
_ = self;
}
// calibrates the ticks per second divider.
// spins for 1 ms then compares against the monotonic timer
// should be called once every second
pub fn calibrate(self: *@This()) void {
if (builtin.target.cpu.arch == .x86_64) {
self.timer.reset();
const startStamp = rdtsc();
while (self.timer.read() < std.time.ns_per_ms) {}
const endStamp = rdtsc();
self.ticksPerMs = @floatFromInt((endStamp - startStamp));
} else if (builtin.target.cpu.arch == .aarch64) {
self.ticksPerMs = @as(f64, @floatFromInt(aarch64_freq())) / 1000;
} else {
// not ticking
// unreachable;
}
}
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.timer = try std.time.Timer.start(),
};
return self;
}
pub fn destroy(self: *@This()) void {
self.allocator.destroy(self);
}
};
test "calibrate scoes" {
const allocator = std.testing.allocator;
const scopes = try ScopesContext.create(allocator);
defer scopes.destroy();
scopes.calibrate();
std.debug.print("calibration ticksPerMs = {d}\n", .{scopes.ticksPerMs.?});
scopes.calibrate();
std.debug.print("calibration ticksPerMs = {d}\n", .{scopes.ticksPerMs.?});
scopes.calibrate();
std.debug.print("calibration ticksPerMs = {d}\n", .{scopes.ticksPerMs.?});
scopes.calibrate();
std.debug.print("calibration ticksPerMs = {d}\n", .{scopes.ticksPerMs.?});
scopes.calibrate();
std.debug.print("calibration ticksPerMs = {d}\n", .{scopes.ticksPerMs.?});
}
const std = @import("std");
const builtin = @import("builtin");