Skip to content

Perf: Generate typed HandleCall<T1,T2,...> overloads to eliminate argument boxing #5389

@thomhurst

Description

@thomhurst

Summary

TUnit.Mocks currently boxes all method arguments into object?[] on every mock invocation:

// Generated today:
public int Add(int a, int b)
{
    var __argsArray = new object?[] { a, b };  // allocation + boxing per call
    return _engine.HandleCallWithReturn<int>(memberId, "Add", __argsArray, 0);
}

This is the primary reason Imposter beats us on invocation benchmarks (~35% faster for single calls, ~31% for 100 calls).

Proposal

Generate arity-specific HandleCall overloads that avoid the object?[] entirely:

// Generated with this change:
public int Add(int a, int b)
{
    return _engine.HandleCallWithReturn<int, int, int>(memberId, "Add", a, b, 0);
}

The engine would have generic overloads like:

public TReturn HandleCallWithReturn<TReturn, T1, T2>(int memberId, string name, T1 arg1, T2 arg2, TReturn defaultValue)

Argument matching would also need typed overloads or a way to match without boxing (e.g., IArgumentMatcher<T>).

Scope

  • Source generator changes in MockImplBuilder to emit typed dispatch
  • New generic HandleCall overloads in MockEngine (up to ~8 type params, fallback to array for more)
  • Typed IArgumentMatcher<T> interface for zero-boxing matching
  • Typed CallRecord or deferred boxing for call history

Benchmark Targets

Benchmark Current Target
Invocation (single) 387 ns / 176 B <280 ns / <168 B
Invocation (100x) 37.7 μs / 18 KB <28 μs / <16 KB
Callback 683 ns / 3.2 KB <450 ns / <2.5 KB

Complexity

High — requires coordinated generator + runtime changes. This is a follow-up to the lower-hanging optimizations (deferred call recording, copy-on-write snapshots, conditional sequencing).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions