"Simon Marlow" <simonmar@microsoft.com> wrote,
I'd like to propose two new functions for the ForeignPtr interface:
mallocForeignPtr :: Storable a => IO (ForeignPtr a) mallocForeignPtrBytes :: Int -> IO (ForeignPtr a)
(the names can change, of course). The implementations are trivial in terms of existing things:
mallocForeignPtr = do p <- malloc newForeignPtr p free
mallocForeignPtrBytes size = do p <- mallocBytes size newForeignPtr p free
However, in GHC we can provide a far more efficient implementation by using pinned ByteArray#s, avoiding the overhead of malloc()/free() and the finalizer. Since this is quite a common idiom when using ForeignPtrs, I think it's a good case to optimise.
I did a little test, and using the above functions gave a 6x improvement in a small example which just repeatedly allocated a new ForeignPtr and passed it to a foreign function.
The GHC implementation is to extend the ForeignPtr type like this:
data ForeignPtr a = ForeignPtr ForeignObj# | MallocPtr (MutableByteArray# RealWorld)
so it does in theory slow down normal ForeignPtrs slightly, but I didn't measure any difference in the limited tests I did.
I vaguely remeber that in the context of the withForeignPtr discussion we where once trying to achieve some similar effect (but couldn't come up with something that would work). Do you remember? Does this, then, effectively solve this old problem? Wouldn't you want newXXX and withXXX variants of the above, too? Cheers, Manuel