Skip to content

Commit 7d4112d

Browse files
committed
fix: isolate probe counters from JIT tier transitions
1 parent 59ed462 commit 7d4112d

4 files changed

Lines changed: 43 additions & 10 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737
uses: actions/upload-artifact@v4
3838
with:
3939
name: full-test-results
40+
overwrite: true
4041
path: ./**/TestResults/*.trx
4142
retention-days: 5
4243

‎.github/workflows/release.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
uses: actions/upload-artifact@v4
4747
with:
4848
name: full-test-results
49+
overwrite: true
4950
path: ./**/TestResults/*.trx
5051
retention-days: 5
5152

‎ManagedCode.MimeTypes.StartupProbe/Program.cs‎

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,37 @@
22
using ManagedCode.MimeTypes;
33

44
var input = args.Length == 0 ? "https://cdn.example.test/assets/photo.png?v=1" : args[0];
5+
var allocationControl = args.Length > 1 && args[1] == "--allocation-control";
56
var mime = MimeHelper.GetMimeType("asset.png");
67
var extensions = MimeHelper.GetExtensions(mime);
78
var knownMimeTypes = MimeHelper.GetKnownMimeTypes();
8-
var before = GC.GetAllocatedBytesForCurrentThread();
9-
for (var index = 0; index < 100_000; index++)
10-
{
11-
mime = MimeHelper.GetMimeType(input);
12-
}
13-
var allocated = GC.GetAllocatedBytesForCurrentThread() - before;
9+
var result = MeasureLookups(input, allocationControl);
1410

15-
Report(mime, extensions.Count, knownMimeTypes.Count, allocated);
11+
Report(result.Mime, extensions.Count, knownMimeTypes.Count, result.Allocated);
1612

17-
// Keep interpolated output in a separate JIT body. Otherwise OSR can initialize
18-
// formatting infrastructure while the lookup allocation counter is running.
13+
// Keep output infrastructure outside the lookup allocation measurement.
1914
[MethodImpl(MethodImplOptions.NoInlining)]
2015
static void Report(string mime, int extensionCount, int knownCount, long allocated)
2116
{
2217
Console.WriteLine($"{mime}|{extensionCount}|{knownCount}|{allocated}");
2318
}
19+
20+
// Only the harness bypasses tiering: the library keeps the requested JIT mode.
21+
// This prevents tier transitions of the measuring loop from polluting its counter.
22+
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
23+
static (string Mime, long Allocated) MeasureLookups(string input, bool allocationControl)
24+
{
25+
var before = GC.GetAllocatedBytesForCurrentThread();
26+
if (allocationControl)
27+
{
28+
GC.KeepAlive(new byte[1024]);
29+
}
30+
31+
var mime = string.Empty;
32+
for (var index = 0; index < 100_000; index++)
33+
{
34+
mime = MimeHelper.GetMimeType(input);
35+
}
36+
37+
return (mime, GC.GetAllocatedBytesForCurrentThread() - before);
38+
}

‎ManagedCode.MimeTypes.Tests/MimeHelperPerformanceTests.cs‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,18 @@ public void ColdProcessLookups_ShouldPreserveAllocationBudgetAcrossJitModes(
147147
result.Allocated.ShouldBeLessThanOrEqualTo(256);
148148
}
149149

150-
private (TimeSpan Duration, long Allocated, string Mime) RunStartupProbe(string? input, string runtimeMode)
150+
[Fact]
151+
[Trait("Category", "Performance")]
152+
public void AllocationProbe_ShouldDetectRealManagedAllocations()
153+
{
154+
var result = RunStartupProbe("assets/photo.png", "default", allocationControl: true);
155+
156+
result.Mime.ShouldBe("image/png");
157+
result.Allocated.ShouldBeGreaterThanOrEqualTo(1024);
158+
}
159+
160+
private (TimeSpan Duration, long Allocated, string Mime) RunStartupProbe(
161+
string? input, string runtimeMode, bool allocationControl = false)
151162
{
152163
var startInfo = new ProcessStartInfo("dotnet")
153164
{
@@ -161,6 +172,11 @@ public void ColdProcessLookups_ShouldPreserveAllocationBudgetAcrossJitModes(
161172
startInfo.ArgumentList.Add(input);
162173
}
163174

175+
if (allocationControl)
176+
{
177+
startInfo.ArgumentList.Add("--allocation-control");
178+
}
179+
164180
if (runtimeMode == "tiered")
165181
{
166182
startInfo.Environment["DOTNET_TieredCompilation"] = "1";

0 commit comments

Comments
 (0)