Skip to content

perf: pre-size setup dispatch tables to FastMockInteractions member count#773

Merged
vbreuss merged 2 commits into
mainfrom
perf/presize-setup-dispatch-tables
May 11, 2026
Merged

perf: pre-size setup dispatch tables to FastMockInteractions member count#773
vbreuss merged 2 commits into
mainfrom
perf/presize-setup-dispatch-tables

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented May 11, 2026

The outer table started at size memberId+1, forcing a realloc + Array.Copy when a later setup targeted a higher-numbered member. The generator already knows the total member count and exposes it via FastMockInteractions.Buffers.Length, so use that as the initial size on first allocation. Subsequent setups never need to grow the outer table.

Saves one outer-table allocation plus the Array.Copy per fresh mock when setups touch multiple members. Applies to the method, indexer, property, and event dispatch tables.

…ount

The outer table started at size memberId+1, forcing a realloc + Array.Copy
when a later setup targeted a higher-numbered member. The generator
already knows the total member count and exposes it via
FastMockInteractions.Buffers.Length, so use that as the initial size on
first allocation. Subsequent setups never need to grow the outer table.

Saves one outer-table allocation plus the Array.Copy per fresh mock when
setups touch multiple members. Applies to the method, indexer, property,
and event dispatch tables.
@vbreuss vbreuss self-assigned this May 11, 2026
Copilot AI review requested due to automatic review settings May 11, 2026 00:25
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves setup registration performance in MockRegistry by pre-sizing the per-member setup dispatch tables using the generator-known mocked member count (via FastMockInteractions.Buffers.Length), avoiding a first-time resize/copy when setups target higher-numbered member ids.

Changes:

  • Add a GetMemberCountHint() helper that returns FastMockInteractions.Buffers.Length when available.
  • Use the hint on first allocation of method/indexer/property/event setup dispatch tables to reduce reallocations and Array.Copy.

Comment thread Source/Mockolate/MockRegistry.Setup.cs Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Test Results

    24 files  ±0      24 suites  ±0   10m 14s ⏱️ + 1m 25s
 4 086 tests ±0   4 084 ✅ ±0  2 💤 ±0  0 ❌ ±0 
26 388 runs  ±0  26 384 ✅ ±0  4 💤 ±0  0 ❌ ±0 

Results for commit b3be8a2. ± Comparison against base commit 0bb1ef9.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

CreateMock Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 65.98 ns 0.212 ns 0.199 ns 1.03 440 B 1.00
Mockolate 64.23 ns 0.606 ns 0.537 ns 1.00 440 B 1.00
Imposter 295.56 ns 9.685 ns 9.059 ns 4.60 2248 B 5.11
TUnitMocks 41.42 ns 1.265 ns 1.184 ns 0.64 224 B 0.51
Moq 1,518.21 ns 13.545 ns 12.670 ns 23.64 2096 B 4.76
NSubstitute 2,113.25 ns 43.452 ns 40.645 ns 32.90 5048 B 11.47
FakeItEasy 1,923.36 ns 57.262 ns 53.563 ns 29.95 2763 B 6.28
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 3.39GHz), 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v4

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Event Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 353.6 ns 7.98 ns 7.46 ns 1.05 1.78 KB 1.00
Mockolate 336.5 ns 11.03 ns 10.32 ns 1.00 1.78 KB 1.00
Imposter 1,400.3 ns 21.72 ns 20.32 ns 4.16 8.8 KB 4.94
TUnitMocks 203.0 ns 2.94 ns 2.61 ns 0.60 1.37 KB 0.77
Moq 14,813.6 ns 34.33 ns 30.43 ns 44.06 12.51 KB 7.02
NSubstitute 5,830.1 ns 76.21 ns 67.56 ns 17.34 9.05 KB 5.08
FakeItEasy 189,429.1 ns 2,088.67 ns 1,851.55 ns 563.43 15.26 KB 8.57
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Indexer N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 968.8 ns 16.01 ns 14.98 ns 0.99 3.81 KB 1.00
Mockolate 1 977.3 ns 6.82 ns 6.04 ns 1.00 3.82 KB 1.00
Imposter 1 962.7 ns 5.72 ns 5.07 ns 0.99 5.16 KB 1.35
Moq 1 216,126.1 ns 857.29 ns 759.96 ns 221.17 20.37 KB 5.33
NSubstitute 1 9,314.8 ns 19.62 ns 17.39 ns 9.53 12.78 KB 3.35
FakeItEasy 1 12,302.3 ns 24.06 ns 20.09 ns 12.59 13.63 KB 3.57
baseline* 10 2,572.8 ns 14.48 ns 13.54 ns 1.03 4.87 KB 1.00
Mockolate 10 2,497.7 ns 9.17 ns 8.13 ns 1.00 4.88 KB 1.00
Imposter 10 2,181.2 ns 6.40 ns 5.99 ns 0.87 7.97 KB 1.63
Moq 10 229,335.7 ns 398.33 ns 353.10 ns 91.82 29.89 KB 6.13
NSubstitute 10 22,896.7 ns 52.82 ns 46.82 ns 9.17 25.58 KB 5.25
FakeItEasy 10 25,367.6 ns 87.21 ns 77.31 ns 10.16 32.97 KB 6.76
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 395.2 ns 4.18 ns 3.91 ns 1.04 2.04 KB 1.00
Mockolate 1 381.7 ns 3.06 ns 2.86 ns 1.00 2.04 KB 1.00
Imposter 1 533.1 ns 4.31 ns 3.60 ns 1.40 4.04 KB 1.98
TUnitMocks 1 673.1 ns 9.40 ns 8.79 ns 1.76 2.9 KB 1.42
Moq 1 133,764.0 ns 860.25 ns 762.59 ns 350.44 14.59 KB 7.15
NSubstitute 1 5,357.5 ns 97.88 ns 91.56 ns 14.04 9.12 KB 4.47
FakeItEasy 1 5,863.7 ns 105.55 ns 98.73 ns 15.36 8.27 KB 4.06
baseline* 10 819.0 ns 3.54 ns 3.31 ns 1.26 2.25 KB 1.00
Mockolate 10 650.8 ns 6.59 ns 6.17 ns 1.00 2.25 KB 1.00
Imposter 10 1,123.1 ns 25.75 ns 24.08 ns 1.73 5.52 KB 2.45
TUnitMocks 10 1,783.6 ns 24.11 ns 21.37 ns 2.74 4.49 KB 2.00
Moq 10 138,055.7 ns 1,021.38 ns 955.40 ns 212.14 18.48 KB 8.21
NSubstitute 10 8,018.3 ns 99.75 ns 93.31 ns 12.32 12.07 KB 5.37
FakeItEasy 10 9,077.6 ns 167.37 ns 156.56 ns 13.95 15.65 KB 6.95
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Property N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 613.2 ns 7.02 ns 6.57 ns 1.01 2.46 KB 1.00
Mockolate 1 609.9 ns 13.33 ns 12.47 ns 1.00 2.47 KB 1.00
Imposter 1 559.1 ns 15.87 ns 14.85 ns 0.92 3.13 KB 1.27
TUnitMocks 1 817.3 ns 8.44 ns 7.90 ns 1.34 2.51 KB 1.02
Moq 1 12,299.7 ns 87.10 ns 77.22 ns 20.17 10.39 KB 4.21
NSubstitute 1 8,058.8 ns 20.54 ns 18.20 ns 13.22 11.45 KB 4.64
FakeItEasy 1 8,829.5 ns 87.47 ns 81.82 ns 14.48 11.24 KB 4.55
baseline* 10 1,175.3 ns 5.59 ns 5.23 ns 1.02 2.95 KB 1.00
Mockolate 10 1,147.0 ns 19.75 ns 18.47 ns 1.00 2.96 KB 1.00
Imposter 10 1,279.9 ns 19.97 ns 18.68 ns 1.12 4.67 KB 1.58
TUnitMocks 10 2,317.3 ns 13.79 ns 12.22 ns 2.02 4.66 KB 1.58
Moq 10 19,657.7 ns 41.97 ns 37.21 ns 17.14 18.28 KB 6.17
NSubstitute 10 18,508.7 ns 82.95 ns 77.59 ns 16.14 21.08 KB 7.12
FakeItEasy 10 20,741.0 ns 155.80 ns 138.11 ns 18.09 30.81 KB 10.40
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Callback Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 255.1 ns 3.55 ns 3.32 ns 0.73 1.68 KB 1.00
Mockolate 347.7 ns 7.24 ns 6.04 ns 1.00 1.68 KB 1.00
Imposter 433.1 ns 3.17 ns 2.97 ns 1.25 2.38 KB 1.42
TUnitMocks 615.7 ns 2.06 ns 1.93 ns 1.77 2.63 KB 1.56
Moq 98,369.4 ns 211.64 ns 187.61 ns 282.97 8.88 KB 5.29
NSubstitute 4,491.6 ns 34.24 ns 32.03 ns 12.92 7.74 KB 4.61
FakeItEasy 4,805.4 ns 42.05 ns 37.28 ns 13.82 6.81 KB 4.05

baseline* rows show the corresponding Mockolate benchmark from the most recent successful main branch build with results, for regression comparison.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 11, 2026 00:35
@vbreuss vbreuss enabled auto-merge (squash) May 11, 2026 00:36
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@sonarqubecloud
Copy link
Copy Markdown

@vbreuss vbreuss merged commit 5496cb5 into main May 11, 2026
21 checks passed
@vbreuss vbreuss deleted the perf/presize-setup-dispatch-tables branch May 11, 2026 00:43
github-actions Bot added a commit that referenced this pull request May 11, 2026
… FastMockInteractions member count (#773) by Valentin Breuß
github-actions Bot added a commit that referenced this pull request May 11, 2026
… FastMockInteractions member count (#773) by Valentin Breuß
@github-actions
Copy link
Copy Markdown

This is addressed in release v3.2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants