---
title: SAIF.Framework.CodeTimer architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.CodeTimer
reference_type: package
---

# SAIF.Framework.CodeTimer architecture

SAIF.Framework.CodeTimer is a lightweight, in-process, hierarchical code-timing/profiling utility exposed through a static `CodeTimer` façade. It captures named/method timing entries in process-wide static state and can render the results as an `XDocument` or to the console; it has no dependency on the SAIF BOF business-object framework and no web/UI layer in the compiled assembly.

## Responsibilities
- Provide a static entry point (`CodeTimer`) for starting, stopping, and resetting named or method-scoped timers, optionally organized in a hierarchical parent/child key structure. (`CodeTimer.cs`)
- Gate timing collection through a global enable switch (`CodeTimer.Enabled`) and an optional per-method `CodeTimerAttribute` flag. (`CodeTimer.cs`, `CodeTimerAttribute.cs`)
- Accumulate per-timer statistics (elapsed, shortest, longest, quantity, captured spans) in `CodeTimerEntry` records held in a static dictionary. (`CodeTimerEntry.cs`)
- Transform the flat, `;`-delimited hierarchical key space into a tree of `CodeTimerItem` nodes and serialize that tree to XML (`CodeTimerResult.OutputXml`) or console text (`CodeTimerResult.OutputConsole`). (`CodeTimerResult.cs`, `CodeTimerItem.cs`)
- Provide a simple value type (`CustomTimeSpan`) capturing one timed span's start/stop/duration, and a non-generic comparer (`CodeTimerItemSorter`) for ordering result items by name/elapsed/quantity/average. (`CustomTimeSpan.cs`, `CodeTimerItemSorter.cs`)

## Component boundaries
- `CodeTimer` (static class): public façade and sole externally visible responsibility of the library; owns the static `Dictionary<string, CodeTimerEntry> data` field and coordinates start/stop/reset/results operations. (`CodeTimer.cs`)
- `CodeTimerAttribute`: method-level attribute type used purely as declarative metadata (`[CodeTimer(enabled)]`) read via reflection by `CodeTimer`; has no behavior of its own. (`CodeTimerAttribute.cs`)
- `CodeTimerEntry`: internal-mutation-state model for one timer (name, quantity, start/stop timestamps, longest/shortest/elapsed, span history); `Start()`/`Stop()` are `internal`, so lifecycle control stays within the assembly. (`CodeTimerEntry.cs`)
- `CodeTimerResult` (internal class): reporting/transformation boundary — consumes the raw entry dictionary and produces the `CodeTimerItem` tree and its XML/console renderings; not part of the public surface. (`CodeTimerResult.cs`)
- `CodeTimerItem`: hierarchical result/data-transfer node used only for reporting output, not for live timing state. (`CodeTimerItem.cs`)
- `CodeTimerItemSorter`: supporting comparer boundary for ordering `CodeTimerItem` collections; depends on the WinForms `SortOrder` enum only, with no other WinForms coupling. (`CodeTimerItemSorter.cs`)
- `CustomTimeSpan`: minimal value holder for one timed interval, used inside `CodeTimerEntry`'s span history and surfaced in XML output when requested. (`CustomTimeSpan.cs`)

## Interaction model
- Callers invoke `CodeTimer.Start(MethodBase, ...)` and `CodeTimer.Stop(MethodBase, ...)`, which resolve a hierarchical key (via `GetCodeTimerParent`) and, if gating checks pass, create/update a `CodeTimerEntry` in the static `data` dictionary. (`CodeTimer.cs`)
- `CodeTimer.Reset()` clears `data` entirely, and `CodeTimer.Results()`/`Results(bool)` hand the dictionary to an internal `CodeTimerResult`, which splits each hierarchical key on `;` (`CreateItems`) to build a `CodeTimerItem` tree, then serializes it via `OutputXml` (or `OutputConsole`, reachable only by direct internal call, not through the public `CodeTimer` API). (`CodeTimer.cs`, `CodeTimerResult.cs`)
- All state is process-wide/AppDomain-wide static state on `CodeTimer`, not scoped per request or thread, and there is no locking around access to `data`, so concurrent calls from multiple threads could race*. (`CodeTimer.cs`)
- Gating is two-layered: the global `CodeTimer.Enabled` field is checked in the private key-based `Start(string)` overload, and the per-method `CodeTimerAttribute.Enabled` flag is checked (via reflection) in the public `MethodBase`-based `Start`/`Stop` overloads. (`CodeTimer.cs`, `CodeTimerAttribute.cs`)

The following diagram shows high-level component interactions within the compiled assembly.

```mermaid
flowchart TD
	Caller["Calling code<br>(instrumented methods)"] --> CT["CodeTimer<br>(static façade)"]
	CT --> Attr["CodeTimerAttribute<br>(per-method gate, via reflection)"]
	CT --> Data["Static Dictionary<string, CodeTimerEntry><br>(process-wide state)"]
	Data --> Entry["CodeTimerEntry<br>(per-timer state)"]
	Entry --> Span["CustomTimeSpan<br>(captured span history)"]
	CT --> Result["CodeTimerResult<br>(internal, reporting)"]
	Result --> Item["CodeTimerItem<br>(hierarchical result tree)"]
	Item --> Sorter["CodeTimerItemSorter<br>(ordering)"]
	Result --> XmlOut["XDocument output<br>(CodeTimer.Results)"]
	Result --> ConsoleOut["Console output<br>(internal-only, not exposed via CodeTimer)"]
```

## Sequence diagram
The following diagram shows the primary start/stop/results sequence for a timed method call.

```mermaid
sequenceDiagram
	participant Caller
	participant CodeTimer
	participant CodeTimerEntry
	participant CodeTimerResult
	Caller->>CodeTimer: Start(MethodBase)
	CodeTimer->>CodeTimer: Check Enabled and CodeTimerAttribute
	CodeTimer->>CodeTimerEntry: Start()
	Caller->>CodeTimer: Stop(MethodBase)
	CodeTimer->>CodeTimerEntry: Stop(isFinal)
	Caller->>CodeTimer: Results()
	CodeTimer->>CodeTimerResult: new CodeTimerResult(data)
	CodeTimerResult->>CodeTimerResult: CreateItems() / OutputXml()
	CodeTimerResult-->>CodeTimer: XDocument
	CodeTimer-->>Caller: XDocument (or null if no data)
```

## Design constraints
- The compiled `SAIF.Framework.CodeTimer.csproj` `<Compile>` item group includes only `CodeTimer.cs`, `CodeTimerAttribute.cs`, `CodeTimerEntry.cs`, `CodeTimerItem.cs`, `CodeTimerItemSorter.cs`, `CodeTimerResult.cs`, `CustomTimeSpan.cs`, and `Properties\AssemblyInfo.cs`. (`SAIF.Framework.CodeTimer.csproj`)
- `CodeTimerModel.cs`, `CodeTimerResults.cs`, and `CodeTimerResults.Designer.cs` exist on disk in the same folder but are **not** referenced by any `<Compile>` element and are therefore excluded from the compiled project — they are orphaned/stale code, not active architecture. They implement a WinForms results viewer (`CodeTimerResults : Form` using `Aga.Controls.Tree.TreeViewAdv`) and a supporting `ITreeModel` adapter (`CodeTimerModel`), and they reference members (`entry.sw`, `entry.timesstarted`, a differently-shaped `CodeTimerItem` constructor, `CodeTimeritemschildren`) that do not exist on the current, compiled `CodeTimerEntry`/`CodeTimerItem` classes, indicating they would not compile if re-added to the project**. (`CodeTimerModel.cs`, `CodeTimerResults.cs`, `CodeTimerResults.Designer.cs`)
- Because the WinForms viewer files are excluded from the build, the vendored `Aga.Controls` tree-view control library is an unused dependency relative to the built assembly — it is referenced only by the orphaned files, not by any compiled type. (`CodeTimerModel.cs`, `CodeTimerResults.cs`)
- The one live-code call site for the WinForms viewer, `(new CodeTimerResults(data)).ShowDialog();` in `CodeTimer.cs`, is commented out and therefore excluded from active behavior. (`CodeTimer.cs`)
- `System.Windows.Forms` remains a referenced framework assembly for the compiled project solely for the `SortOrder` enum used by `CodeTimerItemSorter`; no live UI/Form code is compiled into the assembly. (`CodeTimerItemSorter.cs`)
- All timer state is process-wide/AppDomain-wide static state with no synchronization, so the library is not safe for concurrent multi-threaded timer usage without external coordination*. (`CodeTimer.cs`)
- The library does not inherit from or reference any SAIF BOF business-object framework types (`clsBusinessBase`, `clsBusinessCollectionBase`, `IBusinessCriteria`), and has no ASP.NET/web layer.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimer.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerAttribute.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerEntry.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerItem.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerItemSorter.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerResult.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CustomTimeSpan.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerModel.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerResults.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\CodeTimerResults.Designer.cs
- SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer\SAIF.Framework.CodeTimer.csproj
