ManagedCode.TimeSeries
10.0.0
Prefix Reserved
dotnet add package ManagedCode.TimeSeries --version 10.0.0
NuGet\Install-Package ManagedCode.TimeSeries -Version 10.0.0
<PackageReference Include="ManagedCode.TimeSeries" Version="10.0.0" />
<PackageVersion Include="ManagedCode.TimeSeries" Version="10.0.0" />
<PackageReference Include="ManagedCode.TimeSeries" />
paket add ManagedCode.TimeSeries --version 10.0.0
#r "nuget: ManagedCode.TimeSeries, 10.0.0"
#:package ManagedCode.TimeSeries@10.0.0
#addin nuget:?package=ManagedCode.TimeSeries&version=10.0.0
#tool nuget:?package=ManagedCode.TimeSeries&version=10.0.0

ManagedCode.TimeSeries
Lock-free, allocation-conscious, thread-safe time-series primitives for building fast counters, rolling analytics, and metric pipelines in .NET 10 / C# 14.
| Package | NuGet |
|---|---|
| Core library |
What is this library?
ManagedCode.TimeSeries is a high-performance .NET time series metrics library. It provides optimized, time-bucketed collections to aggregate events into time series:
- Accumulators store raw events per time bucket (queue per bucket).
- Summers store aggregated values per time bucket (sum/min/max/replace).
- Groups manage many series by key (per endpoint, per customer, per shard, etc.).
It's designed for high-throughput analytics: clicks, tokens, CPU usage, money, events, and any numeric telemetry.
Why use it?
- Lock-free ingestion for high write rates.
- Thread-safe reads/writes for multi-threaded pipelines.
- UTC-normalized timestamps for deterministic ordering.
- Grouped series for multi-tenant metrics.
- Orleans-friendly converters and System.Text.Json helpers.
Common use cases
- Web analytics (page views, clicks, conversion funnels).
- Infrastructure metrics (CPU, memory, latency, tokens).
- Billing counters (money, usage, events per window).
Concepts (quick mental model)
- SampleInterval: bucket size (e.g., 1s, 10s, 1m).
- Samples/Buckets: ordered view of buckets keyed by UTC timestamps (
Bucketsis an alias ofSamples). - MaxSamplesCount: maximum bucket count per series;
0means unbounded (this is not the event count). - DataCount: total events processed (not the number of buckets).
- UTC normalized: you can pass any
DateTimeOffset, but values are normalized to UTC internally; offsets are not stored. - Thread-safe: concurrent reads/writes are supported across all public types.
Install
dotnet add package ManagedCode.TimeSeries
Quickstart
1) Make a rolling accumulator (store raw events)
using ManagedCode.TimeSeries.Accumulators;
var requests = new IntTimeSeriesAccumulator(
sampleInterval: TimeSpan.FromSeconds(5),
maxSamplesCount: 60); // 60 buckets -> 5 minutes at 5s interval
// Use current time (UTC internally)
requests.Record(1);
requests.Record(1);
Console.WriteLine($"Buckets: {requests.Samples.Count}");
Console.WriteLine($"Events: {requests.DataCount}");
2) Make a summer (store aggregates per bucket)
using ManagedCode.TimeSeries.Summers;
using ManagedCode.TimeSeries.Extensions;
var latency = new NumberTimeSeriesSummer<decimal>(TimeSpan.FromMilliseconds(500));
latency.Record(12.4m);
latency.Record(9.6m);
Console.WriteLine($"Sum: {latency.Sum()}");
Console.WriteLine($"Avg: {latency.Average():F2}");
Console.WriteLine($"Min/Max: {latency.Min()} / {latency.Max()}");
3) Track many keys at once (grouped series)
using ManagedCode.TimeSeries.Accumulators;
using ManagedCode.TimeSeries.Extensions;
var perEndpoint = new IntGroupTimeSeriesAccumulator(
sampleInterval: TimeSpan.FromSeconds(1),
maxSamplesCount: 300,
deleteOverdueSamples: true);
perEndpoint.AddNewData("/home", 1);
perEndpoint.AddNewData("/checkout", 1);
foreach (var (endpoint, accumulator) in perEndpoint.Snapshot())
{
Console.WriteLine($"{endpoint}: {accumulator.DataCount} hits");
}
4) Serialize/deserialize with System.Text.Json
using ManagedCode.TimeSeries.Accumulators;
using ManagedCode.TimeSeries.Serialization;
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(1), maxSamplesCount: 10);
series.AddNewData(1);
series.AddNewData(2);
var json = TimeSeriesJsonSerializer.SerializeAccumulator<int, IntTimeSeriesAccumulator>(series);
var restored = TimeSeriesJsonSerializer.DeserializeAccumulator<int, IntTimeSeriesAccumulator>(json);
Console.WriteLine(restored.DataCount); // same as original
5) Orleans serialization (v9)
Converters in ManagedCode.TimeSeries.Orleans are marked with [RegisterConverter] and are auto-registered when the
assembly is loaded. Reference the package from your silo and client projects so the converters are available.
Converters are provided for int/float/double accumulators, summers, and grouped series, plus generic numeric summers.
Time handling (DateTimeOffset vs DateTime)
- Public APIs accept
DateTimeOffsetso callers can pass any offset they have. - Internally, timestamps are normalized to UTC (offset zero) for speed and determinism.
- If you need to preserve offsets, store them separately alongside your metric data.
- If you do not need custom timestamps, use
Record(value)orAddNewData(value)and let the library useDateTime.UtcNow.
Accumulators vs Summers
| Type | Stored per bucket | Best for |
|---|---|---|
| Accumulator | ConcurrentQueue<T> |
raw event lists, replay, exact values |
| Summer | T (aggregated) |
fast stats, memory-efficient counters |
Performance tips
- Keep
MaxSamplesCountreasonable to limit memory. - Use
Record(value)(orAddNewData(value)) unless you must pass custom timestamps. - Use summers for high-volume metrics (they avoid storing every event).
- Avoid locks in code that touches these structures.
Design notes
- Accumulators use
ConcurrentQueue<T>to remain lock-free and thread-safe under concurrent writes. - Even in single-threaded runtimes, timers and background cleanup can introduce concurrency.
- If you need single-thread-only storage, consider using summers or ask for a dedicated single-thread accumulator.
Architecture
- See
docs/Architecture/Overview.mdfor detailed workflows, data model, and module boundaries.
Development Workflow
dotnet restore ManagedCode.TimeSeries.slnx
dotnet build ManagedCode.TimeSeries.slnx --configuration Release
dotnet format ManagedCode.TimeSeries.slnx
dotnet build ManagedCode.TimeSeries.slnx --configuration Release
dotnet test ManagedCode.TimeSeries.Tests/ManagedCode.TimeSeries.Tests.csproj --configuration Release
Extensibility
| Scenario | Hook |
|---|---|
| Custom numeric type | Implement INumber<T> and use NumberTimeSeriesSummer<T> |
| Different aggregation | Use Strategy or implement a custom summer |
| Serialization | System.Text.Json helpers in ManagedCode.TimeSeries.Serialization |
Contributing
- Restore/build/test using the commands above.
- Keep new APIs covered with tests (see existing samples in
ManagedCode.TimeSeries.Tests). - Keep hot paths lock-free; only introduce locking when unavoidable and document the trade-off.
- Update this README if you change behavior or public APIs.
License
MIT (c) ManagedCode SAS.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on ManagedCode.TimeSeries:
| Package | Downloads |
|---|---|
|
ManagedCode.Keda.Orleans.Scaler.Client
Keda |
|
|
ManagedCode.Keda.Orleans.Scaler
Keda |
|
|
ManagedCode.TimeSeries.Orleans
TimeSeries |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.0 | 64 | 1/11/2026 |
| 0.0.20 | 260 | 10/19/2025 |
| 0.0.18 | 819 | 5/17/2023 |
| 0.0.17 | 12,322 | 12/9/2022 |
| 0.0.16 | 413 | 12/9/2022 |
| 0.0.15 | 443 | 12/9/2022 |
| 0.0.12 | 1,996 | 10/11/2022 |
| 0.0.11 | 542 | 10/11/2022 |
| 0.0.10 | 829 | 10/10/2022 |
| 0.0.9 | 1,302 | 10/10/2022 |
| 0.0.8 | 768 | 10/10/2022 |
| 0.0.7 | 776 | 10/10/2022 |
| 0.0.6 | 1,335 | 10/10/2022 |
| 0.0.5 | 845 | 10/10/2022 |
| 0.0.4 | 1,869 | 10/3/2022 |
| 0.0.3 | 2,888 | 9/23/2022 |
| 0.0.2 | 2,663 | 9/19/2022 |
| 0.0.1 | 608 | 9/19/2022 |