I am not an expert in this field, but I looked at the F # implementation of the NativePtr module, and I think that there is no performance associated with converting nativeptr<'a> to nativeint and vice versa.
The implementation uses inline IL, and the embedded IL code does not contain any code - it should just make the F # compiler assume that the value on the stack is of a different type:
let inline ofNativeInt (x:nativeint) = (# "" x : nativeptr<_> #) let inline toNativeInt (x:nativeptr<_>) = (# "" x : nativeint #)
In fact, the NativePtr.add method also uses these two methods - it converts the pointer to nativeint , and then adds a 32-bit integer (times the size of type 'a ).
So, the following function should be in order:
let inline addNativeInt (x:nativeptr<'a>) (n:nativeint) : nativeptr<'a> = (NativePtr.toNativeInt x) + n |> NativePtr.ofNativeInt
All functions used in the code must be built-in, so in the end you will get only one instruction to add (although I have not confirmed this yet). You donโt even have to worry about using the function several times in your code (you can work with nativeptr<'a> all the time and use this function to add).
However, partitioning data can also be an option - as far as I know, the MSR command, which used F # to process some large (> 2 GB) data sets, used this very approach - they split the data into 2 GB blocks (stored in arrays).
source share