ForeignPtr performance.

John Meacham john at
Sat Jul 17 00:30:53 EDT 2004

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 ()])  

by caching the frequently used Addr in a place where it may be unboxed
and hiding the details only needed when finalizing or garbage
collecting, I think we can bring ForeignPtrs up to the speed (if not
space) performance of plain old Ptr's.


[2] FP should be strict yet boxed so ForeignPtrs may be unboxed in
various places without duplicating the rarely used bookkeeping info.

touchForeignPtr (ForeignPtr _ fp) = 
        IO $ \s -> case touch# fp s of s -> (# s, () #)
is good enough to keep things alive.
this is also why it is safe to UNPACK the IORefs in FP

John Meacham - ⑆⑆john⑈ 

More information about the Glasgow-haskell-users mailing list