ForeignPtr performance.
Simon Marlow
simonmar at microsoft.com
Mon Jul 19 05:35:02 EDT 2004
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
More information about the Glasgow-haskell-users
mailing list