Skip to content

Instantly share code, notes, and snippets.

@opentechnologist
Created July 23, 2025 00:56
Show Gist options
  • Save opentechnologist/1f7f7f442b94769432a2ed55722e7907 to your computer and use it in GitHub Desktop.
Save opentechnologist/1f7f7f442b94769432a2ed55722e7907 to your computer and use it in GitHub Desktop.
a small c# project with a custom class that keeps track of different elapsed times - useful for determining how long a particular piece of code is running.
using System;
using System.Collections.Generic;
namespace Elapsed
{
public class ElapsedTimeService
{
public class ElapsedTime
{
public DateTime? Last { get; set; }
public long? Ticks { get; set; }
public long Count { get; set; }
public TimeSpan? Min { get; set; }
public TimeSpan? Max { get; set; }
public TimeSpan? Total { get; set; }
public TimeSpan? Average { get; set; }
}
private readonly Dictionary<string, ElapsedTime> ElapsedTimes;
public ElapsedTimeService()
{
ElapsedTimes = new Dictionary<string, ElapsedTime>();
}
public void Mark(string label)
{
ElapsedTime elapsed;
if (!ElapsedTimes.TryGetValue(label, out elapsed))
{
elapsed = new ElapsedTime
{
Last = DateTime.Now,
Ticks = 0,
Count = 0,
Min = null,
Max = null,
Total = null,
Average = null
};
ElapsedTimes[label] = elapsed;
return;
}
if (elapsed.Last.HasValue)
{
var now = DateTime.Now;
TimeSpan interval = now - elapsed.Last.Value;
if (!elapsed.Min.HasValue || interval < elapsed.Min.Value)
elapsed.Min = interval;
if (!elapsed.Max.HasValue || interval > elapsed.Max.Value)
elapsed.Max = interval;
if (!elapsed.Total.HasValue)
elapsed.Total = TimeSpan.Zero;
if (!elapsed.Average.HasValue)
elapsed.Average = TimeSpan.Zero;
elapsed.Count++;
elapsed.Total += interval;
elapsed.Ticks += interval.Ticks;
long? aveTicks = elapsed.Ticks / elapsed.Count;
elapsed.Average = TimeSpan.FromTicks(Convert.ToInt64(aveTicks));
elapsed.Last = now;
return;
}
elapsed.Last = DateTime.Now;
}
public ElapsedTime Get(string label)
{
ElapsedTime elapsed;
if (ElapsedTimes.TryGetValue(label, out elapsed))
return elapsed;
throw new KeyNotFoundException(label);
}
public void Stop(string label)
{
if (ElapsedTimes.ContainsKey(label))
{
ElapsedTimes.Remove(label);
return;
}
throw new KeyNotFoundException(label);
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using Elapsed;
namespace MainPackage
{
public class MainClass
{
public static void Main(string[] args)
{
ElapsedTimeService elapsed = new ElapsedTimeService();
Random random = new Random();
string outer_label = "OUTER_LOOP";
string inner_label = "INNER_LOOP";
int outer_count = 10;
int inner_count = 3;
// initial time marks
elapsed.Mark(outer_label);
elapsed.Mark(inner_label);
for (int i = 0; i < outer_count; i++)
{
Console.WriteLine("---");
Console.WriteLine(string.Format("Outer Iteration ({0})", i+1));
for (int j = 0; j < inner_count; j++)
{
Console.WriteLine(string.Format("\tInner Iteration ({0})", j+1));
Thread.Sleep(random.Next(500, 3000)); // simulate inner processing
elapsed.Mark(inner_label); // calculate inner elapsed time
}
ShowElapsedTimes(elapsed.Get(inner_label), "\t\t");
Thread.Sleep(random.Next(500, 3000)); // simulate outer processing
elapsed.Mark(outer_label); // calculate outer elapsed time
}
Console.WriteLine("---");
ShowElapsedTimes(elapsed.Get(outer_label));
elapsed.Stop(outer_label);
elapsed.Stop(inner_label);
}
private static void ShowElapsedTimes(ElapsedTimeService.ElapsedTime _elapsed, string tabs = "")
{
Console.WriteLine(string.Format("{0}Count ({1})", tabs, _elapsed.Count));
Console.WriteLine(string.Format("{0}Total ({1})", tabs, _elapsed.Total));
Console.WriteLine(string.Format("{0}Average ({1})", tabs, _elapsed.Average));
Console.WriteLine(string.Format("{0}Min ({1})", tabs, _elapsed.Min));
Console.WriteLine(string.Format("{0}Max ({1})", tabs, _elapsed.Max));
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
Sdk="Microsoft.NET.Sdk"
DefaultTargets="Build"
>
<PropertyGroup>
<AssemblyName>main</AssemblyName>
<OutputPath>bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="main.cs" />
<Compile Include="Elapsed.cs" />
</ItemGroup>
<Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe">
<Output TaskParameter="OutputAssembly" ItemName="OutputFile" />
</Csc>
<Message Text="Generated file: @(OutputFile)" Condition="Exists('@(OutputFile)')" />
</Target>
<Target Name="Clean" >
<Delete Files="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment