tiny.coz.Runtime
Defined in tiny.coz.
API (20)
Actions
Public operations.
Fields and members
Public fields and members.
allocatorcurrent_thread_startedexperiment_workerexperiment_worker_errorexperiment_worker_optionsexperiment_worker_runningprofile_writerprofile_writer_mutexprofilerprofiler_installedresolve_sample_locationsruntime_start_nssample_threadsampling_handlersource_scope
Source
Source: lib/coz/src/runtime.zig:41
zig
pub const Runtime = struct { allocator: ?std.mem.Allocator = null, profiler: Profiler = .{}, profile_writer: ?*std.Io.Writer = null, profile_writer_mutex: std.atomic.Mutex = .unlocked, source_scope: debug_info.Scope = .{}, resolve_sample_locations: bool = false, runtime_start_ns: u64 = 0, sampling_handler: ?signals.Installed = null, sample_thread: ?*thread.Thread = null, experiment_worker: ?sys.thread.JoinHandle = null, experiment_worker_running: std.atomic.Value(bool) = .init(false), experiment_worker_error: ?anyerror = null, experiment_worker_options: ExperimentStepOptions = .{}, profiler_installed: bool = false, current_thread_started: bool = false, pub fn start(self: *Runtime, allocator: std.mem.Allocator, options: RuntimeOptions) !void { if (self.profiler_installed) return error.RuntimeAlreadyStarted; self.allocator = allocator; self.runtime_start_ns = timestampNs(); errdefer self.shutdown(); installProfiler(allocator, &self.profiler); self.profiler_installed = true; if (options.install_signal_handler) { self.sampling_handler = installSamplingHandler(); } if (options.start_current_thread) { current_thread = try thread.Thread.openAndStartCurrent(options.sampler_options); self.sample_thread = ¤t_thread; self.current_thread_started = true; } self.source_scope = options.source_scope; self.resolve_sample_locations = options.resolve_sample_locations; if (options.experiment_duration_ns) |duration_ns| { self.profiler.experiment_duration_ns = duration_ns; } if (options.profile_writer) |writer| { try self.profiler.writeStartup(writer, self.runtime_start_ns); self.profile_writer = writer; } if (options.start_experiment_worker) { if (self.profile_writer == null) return error.ProfileWriterUnavailable; try self.startExperimentWorker(options.experiment_step_options); } } pub fn startIfAvailable(self: *Runtime, allocator: std.mem.Allocator, options: RuntimeOptions) !bool { self.start(allocator, options) catch |err| { if (runtimeUnavailable(err)) return false; return err; }; return true; } pub fn runExperimentStep(self: *Runtime, options: ExperimentStepOptions) !ExperimentStepResult { return self.runExperimentStepWithWait(options, waitNs, true); } fn runExperimentStepWithWait( self: *Runtime, options: ExperimentStepOptions, wait_fn: sampler.WaitFn, drain_current_thread: bool, ) !ExperimentStepResult { const allocator = self.allocator orelse return error.RuntimeNotStarted; const writer = self.profile_writer orelse return error.ProfileWriterUnavailable; if (drain_current_thread and self.current_thread_started) { _ = try current_thread.processDefault(&self.profiler, waitNs); } lockMutex(&self.profile_writer_mutex); defer self.profile_writer_mutex.unlock(); const result = try self.profiler.runExperimentStep(allocator, writer, options, wait_fn); if (result.emitted) try writer.flush(); return result; } pub fn stop(self: *Runtime) !void { var first_error: ?anyerror = null; var loss_counter: profile.LossCounter = .unsupported; var terminal_status: profile.TerminalStatus = .not_started; self.stopExperimentWorker() catch |err| rememberRuntimeError(&first_error, err); if (self.current_thread_started) { var stopped = true; current_thread.sampler.stop() catch |err| { stopped = false; rememberRuntimeError(&first_error, err); }; var drained = true; _ = current_thread.drainDefault(&self.profiler) catch |err| failed: { drained = false; rememberRuntimeError(&first_error, err); break :failed 0; }; terminal_status = if (!drained) .drain_failed else if (!stopped) .stop_failed else .complete; loss_counter = profileLossCounter(current_thread.sampler.readLossCounter()); current_thread.close(); current_thread = .{}; self.sample_thread = null; self.current_thread_started = false; } if (self.sampling_handler) |*handler| { handler.restore(); self.sampling_handler = null; } if (self.profiler_installed) { uninstallProfiler(&self.profiler); self.profiler_installed = false; } if (self.profile_writer) |writer| { if (self.allocator) |allocator| { lockMutex(&self.profile_writer_mutex); defer self.profile_writer_mutex.unlock(); self.profiler.writeRuntimeAndSamples( allocator, writer, elapsedSinceNs(self.runtime_start_ns), loss_counter, terminal_status, ) catch |err| rememberRuntimeError(&first_error, err); writer.flush() catch |err| rememberRuntimeError(&first_error, err); } self.profile_writer = null; } if (self.allocator) |allocator| { self.profiler.deinit(allocator); self.allocator = null; } self.runtime_start_ns = 0; self.source_scope = .{}; self.resolve_sample_locations = false; if (first_error) |err| return err; } pub fn shutdown(self: *Runtime) void { self.stop() catch {}; } fn startExperimentWorker(self: *Runtime, options: ExperimentStepOptions) !void { if (self.experiment_worker != null) return error.ExperimentWorkerAlreadyStarted; self.experiment_worker_options = options; self.experiment_worker_error = null; self.experiment_worker_running.store(true, .release); errdefer self.experiment_worker_running.store(false, .release); self.experiment_worker = try sys.thread.spawn(experimentWorkerMain, .{self}); } fn stopExperimentWorker(self: *Runtime) !void { if (self.experiment_worker) |worker| { self.experiment_worker_running.store(false, .release); worker.join(); self.experiment_worker = null; } else { self.experiment_worker_running.store(false, .release); } if (self.experiment_worker_error) |err| { self.experiment_worker_error = null; return err; } } fn runExperimentWorkerStepWithWait( self: *Runtime, prng: *std.Random.DefaultPrng, wait_fn: sampler.WaitFn, ) !ExperimentStepResult { var options = self.experiment_worker_options; options.running = &self.experiment_worker_running; if (options.fixed_speedup_percent == null) { const draw_value = prng.random().intRangeAtMost(u64, 0, experiment.Draw.maxDraw()); options.draw = try experiment.Draw.init(draw_value); } return self.runExperimentStepWithWait(options, wait_fn, false); } fn drainSampleThread(self: *Runtime) !usize { if (!self.resolve_sample_locations) return 0; const allocator = self.allocator orelse return 0; const sample_thread = self.sample_thread orelse return 0; return sample_thread.drainResolvedDefault(&self.profiler, allocator, self.source_scope); }};Source: lib/coz/src/root.zig:67
zig
pub const Runtime = runtime.Runtime;Complete caller list for Runtime.start
9 direct callers.
tiny.coz.Runtime.startIfAvailable[method] atlib/coz/src/runtime.zig:95lib.coz.src.runtime.test_runtime_experiment_step_requires_a_started_writer[function] — test source atlib/coz/src/runtime.zig:933in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_experiment_step_writes_profile_events[function] — test source atlib/coz/src/runtime.zig:811in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_experiment_worker_requires_a_profile_writer[function] — test source atlib/coz/src/runtime.zig:947in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_experiment_worker_step_writes_profile_events[function] — test source atlib/coz/src/runtime.zig:877in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_installs_profiler_lifecycle_without_sampling_resources[function] — test source atlib/coz/src/runtime.zig:715in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_starts_and_stops_current_thread_sampler[function] — test source atlib/coz/src/runtime.zig:1011in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_starts_and_stops_experiment_worker[function] — test source atlib/coz/src/runtime.zig:960in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.test_runtime_writes_profile_events_to_supplied_writer[function] — test source atlib/coz/src/runtime.zig:749in nearest public ownerlib.coz.src.runtime
Complete call list for Runtime.start
7 direct calls.
tiny.coz.Profiler.writeStartup[function] atlib/coz/src/profiler.zig:460tiny.coz.Runtime.shutdown[method] atlib/coz/src/runtime.zig:198lib.coz.src.runtime.Runtime.startExperimentWorker[method] — private source atlib/coz/src/runtime.zig:202in nearest public ownerlib.coz.src.runtimetiny.coz.installProfiler[function] atlib/coz/src/runtime.zig:261tiny.coz.installSamplingHandler[function] atlib/coz/src/runtime.zig:257lib.coz.src.runtime.timestampNs[function] — private source atlib/coz/src/runtime.zig:468in nearest public ownerlib.coz.src.runtimetiny.coz.Thread.openAndStartCurrent[function] atlib/coz/src/thread.zig:24
Complete call list for Runtime.stop
8 direct calls.
tiny.coz.Profiler.deinit[method] atlib/coz/src/profiler.zig:68tiny.coz.Profiler.writeRuntimeAndSamples[method] atlib/coz/src/profiler.zig:472lib.coz.src.runtime.Runtime.stopExperimentWorker[method] — private source atlib/coz/src/runtime.zig:212in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.elapsedSinceNs[function] — private source atlib/coz/src/runtime.zig:475in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.lockMutex[function] — private source atlib/coz/src/runtime.zig:439in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.profileLossCounter[function] — private source atlib/coz/src/runtime.zig:483in nearest public ownerlib.coz.src.runtimelib.coz.src.runtime.rememberRuntimeError[function] — private source atlib/coz/src/runtime.zig:479in nearest public ownerlib.coz.src.runtimetiny.coz.uninstallProfiler[function] atlib/coz/src/runtime.zig:272
Audit
| Definitions | 6 |
|---|---|
| Public names | 6 |
| Members | 15 |
| Version | 26.7.0 |
| Revision | daab053ee433 |