
On 17 July 2004 05:31, John Meacham wrote:
So, I was looking at the implementation of ForeignPtr's in an attempt to determine why they were slow, and have an idea to speed them up..
right now we have:
ForeignPtr a = ForeignPtr ForeignObj# !(IORef [IO ()]) | MallocPtr (MutableByteArray# RealWorld) !(IORef [IO ()])
and I think the inderection caused by the disjunction is what is messing things up, not allowing ForeignPtrs to be inlined even in strict contexts as the discriminator must still be examined. so how bout something like
data ForeignPtr a = ForeignPtr Addr# !FP -- note FP should be strict but BOXED [2] data FP = ForeignPtrObj ForeignObj# {-# UNPACK #-} !(IORef [IO ()]) | MallocPtr (MutableByteArray# RealWorld) {-# UNPACK #-} !(IORef [IO ()])
At first I thought this wasn't safe, but having thought about it some more I now think it might be. The reason it is safe is because all ForeignPtr access happens inside withForeignPtr, which is ended by touch#. The implementation of touch# is invisible to the compiler, so GHC's optimiser *must* ensure that the FP stays alive until the touch#, and hence the ForeignObj# also stays alive. Interestingly, unless I'm being stupid (entirely possible) this implies that we don't actually need ForeignObj# at all! This would do: data FP = ForeignPtrObj {-# UNPACK #-} !(IORef [IO ()]) | MallocPtr (MutableByteArray# RealWorld) {-# UNPACK #-} !(IORef [IO ()]) And in the ForeignPtrObj case, we place the finalizer on the IORef (we need an atomic object with well-defined allocation semantics on which to place the finalizer - just placing it on the FP wouldn't do). Getting rid of ForeignObj# is a serious win. Deleting code and improving performance at the same time rarely happens these days! Would you like to try this out? Cheers, Simon
participants (1)
-
Simon Marlow