Performance benchmarks
Same machine, same payload, same BenchmarkDotNet run. ArgusLogs is compared with Microsoft.Extensions.Logging plus a Serilog file sink. Lower time and lower memory is better. Start with the two fair pairs — then use the full tables if you want every number from the run.
What the numbers say
- One log line: ArgusLog.Info averages 360 ns vs 1,158 ns for ILogger + Serilog — about 3.2× faster. Memory is close (668 B vs 632 B).
- Automatic method logging: Argus [LogMethod] averages 621 ns vs 4,802 ns for the same ENTER / parameters / return / EXIT written by hand with ILogger — about 7.7× faster and 1.6× less memory.
- Argus [LogMethod] writes two file events. Even then it is still faster than one Serilog Information line (621 ns vs 1,158 ns).
How to read this comparison
- Ratio is mean(current) ÷ mean(Serilog Information). 1.00 is the baseline. Below 1.00 is faster. Above 1.00 is slower.
- A fair pair logs the same work. Two ENTER+EXIT events are not the same job as one Information line.
- The Debug row is a filter-out check (no file write). It is not a write-speed comparison.
Fair pair 1 — one log line
Both write one Information-level line with the same order and user ids: Processed order 1842 for user 77.
ArgusLog.Info vs ILogger + Serilog Information
| Metric | ArgusLog.Info | ILogger + Serilog |
|---|---|---|
| Mean time | 359.68 ns | 1,158.03 ns |
| Ratio vs Serilog | 0.31 — 3.2× faster | 1.00 — baseline |
| Allocated | 668 B | 632 B |
| Alloc ratio | 1.06 | 1.00 |
| Min → max | 82.06 ns → 525.66 ns | 1,119 ns → 1,219 ns |
| Median | 406.83 ns | 1,146 ns |
| StdDev | 149.52 ns (13.15%) | 0.037 µs (1.01%) |
| 99.9% CI | [133.63 ns; 585.74 ns] | [1.102 µs; 1.214 µs] |
| Samples (N) | 10 | 10 |
| Verdict | Faster. Memory almost the same. | Baseline for this pair |
Fair pair 2 — method enter and exit
Both log the same method-boundary data: entry, parameters, return value, exit, and duration. Argus does this with [LogMethod]. The ILogger side writes the same events by hand.
Argus [LogMethod] vs ILogger method-boundary equivalent
| Metric | Argus [LogMethod] | ILogger equivalent |
|---|---|---|
| Mean time | 620.97 ns | 4,801.51 ns |
| Ratio vs Serilog Information | 0.54 — still 1.9× faster than one Serilog line | 4.15 — 4.2× slower than one Serilog line |
| Allocated | 2,043 B | 3,310 B |
| Alloc ratio | 3.23 | 5.24 |
| Min → max | 601.74 ns → 637.20 ns | 4.719 µs → 4.908 µs |
| Median | 622.23 ns | 4.791 µs |
| StdDev | 12.23 ns (0.70%) | 0.071 µs (0.52%) |
| 99.9% CI | [597.58 ns; 644.36 ns] | [4.666 µs; 4.937 µs] |
| Samples (N) | 8 | 8 |
| Verdict | 7.7× faster, 1.6× less memory | Same work, slower and heavier |
Full run — all five methods
BenchmarkDotNet summary. Ratio and Alloc Ratio are versus ILogger + Serilog Information (the baseline).
Job=Bench · InProcessNoEmit · 8192 invocations · 10 iterations · 3 warmups
| Method | Mean | Ratio | In plain English | Allocated | Alloc ratio |
|---|---|---|---|---|---|
| ILogger + Serilog file (Information template) | 1,158.03 ns | 1.00 | Baseline — one file write | 632 B | 1.00 |
| ArgusLog.Info file (same payload) | 359.68 ns | 0.31 | 3.2× faster, similar memory | 668 B | 1.06 |
| ILogger + Serilog filtered Debug (no write) | 71.94 ns | 0.06 | No file write — filtered out | 149 B | 0.24 |
| Argus [LogMethod] weaved ProcessOrder | 620.97 ns | 0.54 | Two writes, still 1.9× faster than baseline | 2,043 B | 3.23 |
| ILogger LogMethod-equivalent ProcessOrder | 4,801.51 ns | 4.15 | Same work as [LogMethod], 7.7× slower than Argus | 3,310 B | 5.24 |
Spread, not just the mean
Min, median, max, standard deviation, sample count, and 99.9% confidence interval from the same run.
Detailed results — 99.9% CI
| Method | Mean | Min | Median | Max | StdDev | N | 99.9% CI |
|---|---|---|---|---|---|---|---|
| ILogger + Serilog Information | 1.158 µs | 1.119 µs | 1.146 µs | 1.219 µs | 0.037 µs (1.01%) | 10 | [1.102 µs; 1.214 µs] |
| ArgusLog.Info | 359.68 ns | 82.06 ns | 406.83 ns | 525.66 ns | 149.52 ns (13.15%) | 10 | [133.63 ns; 585.74 ns] |
| ILogger Debug (filtered) | 71.94 ns | 69.06 ns | 71.98 ns | 74.68 ns | 1.69 ns (0.78%) | 9 | [69.10 ns; 74.79 ns] |
| Argus [LogMethod] | 620.97 ns | 601.74 ns | 622.23 ns | 637.20 ns | 12.23 ns (0.70%) | 8 | [597.58 ns; 644.36 ns] |
| ILogger method-boundary equivalent | 4.802 µs | 4.719 µs | 4.791 µs | 4.908 µs | 0.071 µs (0.52%) | 8 | [4.666 µs; 4.937 µs] |
What each method actually does
Same ProcessOrder payload (orderId 1842, userId 77). File I/O is included for every write.
Workload
| Method | Library | File writes | What is logged |
|---|---|---|---|
| ILogger + Serilog Information | Serilog via ILogger | 1 | One Information line with order and user ids |
| ArgusLog.Info | ArgusLogs | 1 | One Info line with the same payload |
| ILogger Debug (filtered) | Serilog via ILogger | 0 | Debug call dropped by MinimumLevel.Information |
| Argus [LogMethod] | ArgusLogs DataAnnotation | 2 | Weaved ProcessOrder: ENTER, parameters, return, EXIT + duration |
| ILogger method-boundary equivalent | Serilog via ILogger | 2 | Hand-written ENTER, parameters, return, EXIT + duration |
How the test was run
Independent Release run. In-process toolchain so the signed ArgusLogs.dll next to the app is used.
Environment
| Item | Value |
|---|---|
| Machine | Apple M4 Pro, 1 CPU, 14 logical and 14 physical cores |
| OS | macOS 26.6.1 (25G76) |
| SDK / runtime | .NET SDK 10.0.102 · host .NET 10.0.2 Arm64 RyuJIT |
| Tool | BenchmarkDotNet 0.15.4 |
| Job | InProcessNoEmit · InvocationCount=8192 · IterationCount=10 · WarmupCount=3 · UnrollFactor=16 · LaunchCount=1 |
| Argus sink | JSON file, console off |
| Serilog sink | File, Information minimum, buffered |
| Payload | ProcessOrder(orderId: 1842, userId: 77) |
| Run time | 21.47 s, 5 benchmarks |