LeanProfiler

2.1. Keep names stable and put variation in metadata🔗

An event name answers “what work was this?” Metadata answers “under which conditions?” A stable name makes runs comparable even when the module, shape, or backend changes.

span "model.forward" runAttention (metadata := {
  phase := some "forward"
  activity := some "operator"
  backend := some backendName
  dtype := some dtypeName
  device := some deviceName
  moduleName := some "encoder.block.0"
  graphNode := some nodeName
  stepIndex := some step
  inputShapes := #[inputShape]
  outputShapes := #[outputShape]
})

LeanProfiler uses the following fields as the summary key:

name, phase, activity, backend, dtype, device, module

Those fields split rows because they commonly identify meaningfully different implementations. A CPU and CUDA forward pass should not be averaged together, and neither should two modules whose costs need to be compared.

Step, graph node, and shape arrays remain attached to individual trace events. Putting a step number in the grouping key would create one summary row per iteration. Putting arbitrary shapes in the key could do the same for variable-length inputs. The trace is where those details belong; the summary is where repeated observations become a distribution.

When another dimension really does define a separate benchmark population, use a stable name or one of the grouping fields deliberately. Do not encode an entire JSON payload into an event name.