interoptopus_backend_cpython 0.14.25

Generates CPython bindings.
Documentation
import ctypes
import reference_project as r
import time

N = 1_000_000

r.init_lib("../../../../target/release/interoptopus_reference_project.dll")

def bench(file, name, f, reference = 0):
    start = time.perf_counter()

    for i in range(N):
        f()

    end = time.perf_counter()
    nanos = (end-start) * 1000 * 1000 * 1000
    nanos_per_single = (nanos / N) - reference

    name = f"`{name}`"

    if reference > 0:
        print("|", name.ljust(50), "| {:,.0f} |".format(nanos_per_single), file=file)

    return nanos_per_single


ptr = (ctypes.c_int64 * 100)(100, 2, 3)
empty = r.Empty()


with open("BENCHMARK_RESULTS.md", 'w') as f:
    print("""
    
# FFI Call Overheads

The numbers below are to help FFI design decisions by giving order-of-magnitude estimates how
expensive certain constructs are.

Times were determined by running the given construct 1M times, taking the elapsed time in ticks,
and computing the cost per 1k invocations.


## System

The following system was used:    
    
```
System: i9-9900K, 32 GB RAM; Windows 10
rustc: stable (i.e., 1.53 or later)
profile: --release
Python: 3.10.0
```
    
## Results

| Construct | ns per call |
| --- | --- |""", file=f)

    reference = bench(f, "Baseline (already subtracted)", lambda: 0)
    bench(f, "primitive_void()", lambda: r.primitive_void(), reference)
    bench(f, "primitive_u8(0)", lambda: r.primitive_u8(0), reference)
    bench(f, "primitive_u16(0)", lambda: r.primitive_u16(0), reference)
    bench(f, "primitive_u32(0)", lambda: r.primitive_u32(0), reference)
    bench(f, "primitive_u64(0)", lambda: r.primitive_u64(0), reference)
    bench(f, "many_args_5(0, 0, 0, 0, 0)", lambda: r.many_args_5(0, 0, 0, 0, 0), reference)
    bench(f, "ptr(x)", lambda: r.ptr(ptr), reference)
    bench(f, "tupled(r.Tupled())", lambda: r.tupled(r.Tupled()), reference)
    bench(f, "complex_args_1(r.Vec3f32(), empty)", lambda: r.complex_args_1(r.Vec3f32(), empty), reference)
    bench(f, "callback(lambda x: x, 0)", lambda: r.callback(lambda x: x, 0), reference)
    bench(f, "pattern_ffi_slice_delegate(lambda x: x[0])", lambda: r.pattern_ffi_slice_delegate(lambda x: x[0]), reference)
    # bench("pattern_ffi_slice_delegate_huge(lambda x: x[0])", lambda: r.pattern_ffi_slice_delegate_huge(lambda x: x[0]), reference) # ??