Performance
PyDotNet uses BenchmarkDotNet to track call overhead, marshaling, zero-copy buffers, and asynchronous coroutine execution. The benchmark project targets .NET 10 and compares equivalent PyDotNet and Python.NET operations.
Run the complete suite:
dotnet run -c Release --project benchmarks/PyDotNet.Benchmarks
Run only PyDotNet call benchmarks:
dotnet run -c Release --project benchmarks/PyDotNet.Benchmarks -- --filter "*PyDotNetBenchmarks.Call*"
Results should be compared on the same machine, power profile, .NET SDK, Python version, architecture, and native dependency set. Treat cross-machine timing differences as informational; allocation changes are usually more portable.
Current hot-path design
- Positional calls use CPython vectorcall and avoid an intermediate Python tuple.
- Argument pointer storage stays on the stack for calls with up to 16 arguments.
- Live wrapper tracking uses weak-key storage without allocating a separate
WeakReferenceper wrapper. - Diagnostics do not create activities or start latency timing unless a listener enables the relevant instrument.
- Source-generated logging avoids formatting allocations when logging is disabled.
The benchmark suite includes zero-argument and 32-argument vectorcall cases so both stack and managed fallback paths remain visible.