Re: ForeignPtr performance
Bulat Ziganshin wrote: Hello Scott, Sunday, December 16, 2007, 11:57:33 PM, you wrote: My question is: what exactly does GHC.Prim.touch# do? This appears to it's a no-op (for ghc 6.6+ at least). its only task is to notify ghc optimizer that data were accessed so it doesn't free the memory Yes, exactly. touch# generates no code, but it is vitally important because if the ForeignPtr is referencing data in the heap (like mallocForeignPtrBytes does), it prevents the data from being GC'd before the operation completes. Cheers, Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re[2]: ForeignPtr performance
Hello Simon, Monday, December 17, 2007, 1:33:19 PM, you wrote: My question is: what exactly does GHC.Prim.touch# do? This appears to it's a no-op (for ghc 6.6+ at least). its only task is to notify ghc optimizer that data were accessed so it doesn't free the memory Yes, exactly. touch# generates no code, but it is vitally important because if the ForeignPtr is referencing data in the heap (like mallocForeignPtrBytes does), it prevents the data from being GC'd before the operation completes. a bit more details for Scott: generated code is like this: ptr - unsafeForeignPtrToPtr fptr yourAction ptr touch# fptr without touch, the *last* action where fptr involved is its conversion to ptr. GHC Runtime (not optimizer as i said) have no idea that ptr and fptr is the same object, so after conversion it feels free to dispose object pointed by fptr if GC occurs. this means that during execution of your action data pointed by fptr/ptr may be suddenly freed, allocated by other object, bang! the touch pseudo-action is performed *after* your action and references fptr again. so Runtime thinks there is one more usage of fptr after yourAction and it doesn't dispose this chunk of memory if GC occurs during your action (unfortunately it's not mentioned anywhere on the Web) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Re[2]: ForeignPtr performance
Thanks for the response guys. I'm still curious as to the specific mechanism by which a strictly compile-time function affects the run-time behavior of the GC. Bulat says that touch# makes the runtime aware that the fptr object is still in use, but how does it do this if, at runtime, it doesn't do anything? Does if affect the scheduling of collections? Does it mark the fptr object with some flag when its allocated? What if, for example, if I put the touch# behind a branch that is conditional on run-time values? How would this affect things? I'm sure the answer to this is detailed and involves a lot of specifics about GHC that I probably won't grasp, and maybe it isn't appropriate for the whole list, but if there happens to be a short answer, or there's a reference you can point me to, I'd appreciate it. Thanks, Scott On Dec 17, 2007 4:12 AM, Bulat Ziganshin [EMAIL PROTECTED] wrote: Hello Simon, Monday, December 17, 2007, 1:33:19 PM, you wrote: My question is: what exactly does GHC.Prim.touch# do? This appears to it's a no-op (for ghc 6.6+ at least). its only task is to notify ghc optimizer that data were accessed so it doesn't free the memory Yes, exactly. touch# generates no code, but it is vitally important because if the ForeignPtr is referencing data in the heap (like mallocForeignPtrBytes does), it prevents the data from being GC'd before the operation completes. a bit more details for Scott: generated code is like this: ptr - unsafeForeignPtrToPtr fptr yourAction ptr touch# fptr without touch, the *last* action where fptr involved is its conversion to ptr. GHC Runtime (not optimizer as i said) have no idea that ptr and fptr is the same object, so after conversion it feels free to dispose object pointed by fptr if GC occurs. this means that during execution of your action data pointed by fptr/ptr may be suddenly freed, allocated by other object, bang! the touch pseudo-action is performed *after* your action and references fptr again. so Runtime thinks there is one more usage of fptr after yourAction and it doesn't dispose this chunk of memory if GC occurs during your action (unfortunately it's not mentioned anywhere on the Web) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: ForeignPtr performance
Scott Dillard wrote: Thanks for the response guys. I'm still curious as to the specific mechanism by which a strictly compile-time function affects the run-time behavior of the GC. Bulat says that touch# makes the runtime aware that the fptr object is still in use, but how does it do this if, at runtime, it doesn't do anything? Does if affect the scheduling of collections? Does it mark the fptr object with some flag when its allocated? What if, for example, if I put the touch# behind a branch that is conditional on run-time values? How would this affect things? It's not as complicated as you think. touch# takes a single argument, and does nothing with it; it's only purpose is to ensure that the value passed as its argument is alive as far as the rest of the compiler and runtime is concerned. There's no special mechanism at work here: touch# is just like an ordinary IO operation, except that its implementation is empty, and the compiler cannot use this fact for optimisation purposes. The compiler therefore arranges that the argument to touch# is available, just as it would for any other function. Cheers, Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: ForeignPtr performance
On Mon, Dec 17, 2007 at 02:12:31PM +0300, Bulat Ziganshin wrote: Hello Simon, Monday, December 17, 2007, 1:33:19 PM, you wrote: My question is: what exactly does GHC.Prim.touch# do? This appears to it's a no-op (for ghc 6.6+ at least). its only task is to notify ghc optimizer that data were accessed so it doesn't free the memory Yes, exactly. touch# generates no code, but it is vitally important because if the ForeignPtr is referencing data in the heap (like mallocForeignPtrBytes does), it prevents the data from being GC'd before the operation completes. a bit more details for Scott: generated code is like this: ptr - unsafeForeignPtrToPtr fptr yourAction ptr touch# fptr without touch, the *last* action where fptr involved is its conversion to ptr. GHC Runtime (not optimizer as i said) have no idea that ptr and fptr is the same object, so after conversion it feels free to dispose object pointed by fptr if GC occurs. this means that during execution of your action data pointed by fptr/ptr may be suddenly freed, allocated by other object, bang! I'd like to elaborate that ptr, as far as the GC is concerned is *not a pointer at all*, it is an integer memory address. So it doesn't keep anything alive, you need to hold on to fptr if you want the value to exist. Stefan signature.asc Description: Digital signature ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
ForeignPtr performance
Hi, I do a lot of programming with small compound objects, things like 3d vectors or RGBA tuples for images. For performance reasons, I keep them in StorableArrays, since there is no way to use these things with UArrays. (But that's a topic for another thread.) Some how the notion got into my head that StorableArrays were slow, I think from old versions of GHC. So I've gotten into the habit of using withStorableArray and peek/poke to work on my arrays. This, as you can imagine, is cumbersome. Not only because of the extra typing, but also because I have to do everything in the IO monad, even if the array is read-only. So I'm thinking about writing my own IArray instance using ForeignPtr for storage and unsafePerformIO for access. I did a little experiment, comparing forM_ [0..lots] $ \i - withForeignPtr fp $ \p - pokeElemOff p i i to withForeignPtr fp $ \p - forM_ [0..lots] $ \i - pokeElemOff p i i And there seemed to be no difference in running time, which is great. So I'm thinking of making unsafeAt something like unsafeAt (MyArray fp) i = unsafePerformIO $ withForeignPtr fp $ \p - peekElemOff p i My question is: what exactly does GHC.Prim.touch# do? This appears to be the critical function of withForeignPtr, and if I write my IArray instance as above, I have no way to float this touch# out of my loops, as I currently do using withStorableArray. It appears from my simple experiment that touch# does nothing at runtime. But maybe this is only because no memory is allocated inside my simple loop? Maybe if I write non-trivial loops, then touch# will actually cost something? Intensely curious, Scott ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: ForeignPtr performance
Hello Scott, Sunday, December 16, 2007, 11:57:33 PM, you wrote: My question is: what exactly does GHC.Prim.touch# do? This appears to it's a no-op (for ghc 6.6+ at least). its only task is to notify ghc optimizer that data were accessed so it doesn't free the memory -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: ForeignPtr performance.
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 ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
ForeignPtr performance.
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. John [2] FP should be strict yet boxed so ForeignPtrs may be unboxed in various places without duplicating the rarely used bookkeeping info. hopefully 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 - repetae.netjohn ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users