Skip to content

Perf

Namespace Nfty.Core.Diagnostics in assembly Nfty.Core.

public static class Perf

A tiny always-available profiler: named scopes, wall time, and managed allocation.

Off by default and free when off — Perf.Measure() returns a struct whose Dispose does nothing, so an unenabled scope costs one branch and no allocation. Turn it on with the NFTY_PERF=1 environment variable, or from code with Perf.Enable(), which is what the benchmark tests do.

Deliberately not BenchmarkDotNet: this measures whole user-facing operations inside the real app (opening a Set, realizing a row of thumbnails) rather than micro-benchmarking a method in isolation, and it has to be able to run in a GUI process. It is a stopwatch and a dictionary, which is the right size for the question.

Properties

Enabled

public static bool Enabled { get; }

Whether measurement is running. Read on every scope, so it is a plain field.

Methods

Disable()

public static void Disable();

Turns measurement off. Collected totals are kept so a report can still be read.

Enable()

public static void Enable();

Turns measurement on and clears whatever was collected before.

Measure(string)

public static Perf.Scope Measure(string name);

Measures the enclosing block.

Parameters

  • name (string) - The scope's name; totals accumulate per name.

Returns. A scope to dispose at the end of the block. Disposing a disabled scope does nothing.

Example

using var _ = Perf.Measure("SetReader.Read");

Report()

public static string Report();

The snapshot as a fixed-width table.

Returns. One line per scope, plus a header. Empty string when nothing was measured.

Remarks

Formatted the way Stats/'s reports are — invariant, so two runs on two machines can be diffed.

Reset()

public static void Reset();

Discards every collected total.

Snapshot()

public static IReadOnlyList<PerfEntry> Snapshot();

Everything measured so far, slowest total first.

Returns. One entry per scope name.