When interpolating a single point, the C/C++ APIs of NeoPDF (~150 ns) is slower than LHAPDF (~70 ns) by a factor of two. A preliminary profiling of the code shows the following results:
┌─────────────────────────────────────┬───────────┐
│ Component │ Time (ns) │
├─────────────────────────────────────┼───────────┤
│ C++ API Total │ 147.23 │
│ ├─ FFI boundary (C++ → Rust) │ ~17 │
│ └─ Rust xfxq2_log │ 129.80 │
│ ├─ Subgrid search (K-d tree) │ 7.37 │
│ ├─ PID lookup (linear) │ 6.69 │
│ └─ Interpolation + framework │ ~116 │
│ ├─ Core interpolation │ 53-65 │
│ └─ Framework overhead │ 51-63 │
│ ├─ Array indexing │ ? │
│ ├─ ForcePositive check│ ? │
│ ├─ Result unwrapping │ ? │
│ └─ Function calls │ ? │
└─────────────────────────────────────┴───────────┘
Essentially, the core interpolation is comparable (if not slightly faster) but the main overhead comes from the infrastructure + framework. This mainly comes from the various abstractions and safety checks. Specifically, NeoPDF uses:
- Rust's
Result<T, E> for error handling
- Bounds-checked array access (which are still present even in release mode)
- Multiple layers of function calls
- Option types for nullable values
One way to circumvent this is to use monomorphism such as const generics to eliminate runtime checks:
impl<const FORCE_POSITIVE: bool> PDF { ... }
When interpolating a single point, the C/C++ APIs of NeoPDF (~150 ns) is slower than LHAPDF (~70 ns) by a factor of two. A preliminary profiling of the code shows the following results:
Essentially, the core interpolation is comparable (if not slightly faster) but the main overhead comes from the infrastructure + framework. This mainly comes from the various abstractions and safety checks. Specifically, NeoPDF uses:
Result<T, E>for error handlingOne way to circumvent this is to use monomorphism such as
const genericsto eliminate runtime checks: