Skip to content

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.

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.

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.

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