Open TheKK opened 11 months ago
Thanks @TheKK for looking into this deeply.
I am wondering if this gets resolved if we write asPtrUnsafe in MutArray/Type.hs as follows:
asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> IO b) -> m b
asPtrUnsafe arr f = liftIO $ do
contents <- Unboxed.pin $ arrContents arr
let !ptr = Ptr (byteArrayContents#
(unsafeCoerce# (getMutableByteArray# contents)))
r <- f (ptr `plusPtr` arrStart arr)
touch contents
return r
Basically, just change the function f type to use IO and move liftIO at the top level of this function. If that works, it is a minimal change. Or maybe we can just return IO and remove the MonadIO constraint entirely. Because there not much point using liftIO in this API now, if the user wants they can use it themsleves.
We can also add a benchmark for this.
The solution you suggested sound good to me. I think we could keep MonadIO
constraint there so the interface of asPtrUnsafe
is intact even though it's pre-release API.
I would appreciate if you can find time to create a PR about this.
Sure!
We can add new APIs unsafeAsPtrIO
to use IO monad directly, as we already have unsafeAsPtr.
Since I observed write performance issue in my program, I found that it was caused by
Array Word8
accidentally.Here's the benchmark that could reproduce it. https://gist.github.com/TheKK/251fc1fe24600165ce1b2db922f1ac2d
I tried implementing
asUnsafePtr
withoutMonadIO m
constraint as a reference. Below are the results from my laptop:Marking
arr_asPtrUnsafe
andma_asPtrUnsafe
as NOINLINE makes benchmark, "asPtr/Array", drop to 15 ns. Still pretty fast comparing to "asPtr/Array" which is 118 ns.By looking at the CORE, it's obvious that
Array.asPtrUnsafe
was called by worker wrapper which means one level of indirection.So this should be a real issue that affect all operations of
Array
relates to itsPtr
interface.