switch the buffer type to bytes instead of bigarray/cstruct - #153
Conversation
|
Does benchmarking show an improvement? |
|
"Better", but I'm working on quantifying this. Stay tuned. |
|
I ran some benchmarks against both branches, and the microbenchmarks show:
|
It only gets overwritten if there's enough data to fill the buffer. Otherwise you're leaking private data. Could have a I'm wondering if we should have an |
|
I'm thinking that if the caller library provides buffers that are 2kb+, then we avoid this issue as the caller can design how to provide memory that meets their own criteria. All we need to do in uring is to verify that any buffer coming in is of a suitable size, which seems like a cheap check to do. |
We need a custom bigarray here in order to alias an existing bytes buffer in the heap. We need to ensure that no copy of the bytes is made, but also that the bytes arent freed while the bigarray (and any slices thereof) are also still live. A 'normal' bigarray cant express this aliasing. A CAML_BA_EXTERNAL bigarray doesnt do any lifetime tracking, while a CAML_BA_MANAGED bigarray has the runtime call free() which would corrupt the heap when the storage is `bytes`. We therefore allocate the bigarray as CAML_BA_MANAGED | CAML_BA_SUBARRAY with a hand-built proxy attached at creation. This is morally ok since the bigarray is indeed a subarray, just not of another bigarray! Managed mode allows every derived bigarray slice to be tracked via the runtime's proxy. Pre-attaching the proxy with a NULL data pointer halts the free paths when the refcount reaches zero, while the BA_MANAGED status stops free being called on the bytes. Keeping the bytes alive is then done purely on the OCaml side. A finaliser closure that captures the bytes is attached to the original bigarray, and serves as the GC root. When the original becomes unreachable while the proxy refcount shows other family members are still live, the finaliser re-registers itself on the same value. The chain terminates when the refcount is 0, after which the bytes become collectable as normal since the bigarray will be GCed. This only works if the bytes themselves dont move, which is guaranteed by the OCaml 5 runtime minimum size. Phew!
|
@talex5 wrote:
This took a few iterations, but I have a glorious hack in 4116ced that does successfully alias non-moving bytes. It create a proxy managed bigarray and a finaliser that ties the bytes to the bigarray. This scheme has the advantage that there's no performance impact if bigarrays aren't used (which is our eventual end goal). Still stress testing it but it doesn't seem to obviously crash... |
This is a surprisingly small diff, since most of what we need to do is just make sure the backing
bytesis >2KB.