
Hey everyone! Do you have any suggestions for how I might allocate an aligned block of memory that I can pin while making foreign calls, but leave unpinned the rest of the time to potentially improve allocation and garbage collector performance? Or is this even a good idea? Thanks, Greg

gcross:
Hey everyone! Do you have any suggestions for how I might allocate an aligned block of memory that I can pin while making foreign calls, but leave unpinned the rest of the time to potentially improve allocation and garbage collector performance? Or is this even a good idea?
There's no pinned/unpinned memory. You have to pick one. * Use a ForeignPtr to allocate pinned memory (mallocForeignPtr) if you want it mostly poinned. Otherwise, you'll need to copy from unpinned to pinned. -- Don

Thanks, Don. What made me think that this might be possible was the existence of Foreign.StablePtr, since that seems to take a Haskell expression and pin it down. Could this mechanism be harness to pin down arrays, or am I misunderstanding how it works? (Is StablePtr really just making a copy of the expression behind the scenes?) My motivation for this is that I will be sweeping back and forth along a data structure that is chain of memory blocks (essentially a pointed list), with ~ 10 to 1000 beads. At any given time I am only working with and updating one bead on the chain, so I am wondering if trying to use unpinned memory for the beads not in use would help by speeding up allocations and allowing the g.c. to rearrange their layout in memory. Each bead has a few memory chunks ranging from ~ 100 bytes to possibly up to tens of kilobytes, depending on a scaling parameter on my algorithm. Any thoughts? Cheers, Greg On Nov 11, 2009, at 1:18 PM, Don Stewart wrote:
gcross:
Hey everyone! Do you have any suggestions for how I might allocate an aligned block of memory that I can pin while making foreign calls, but leave unpinned the rest of the time to potentially improve allocation and garbage collector performance? Or is this even a good idea?
There's no pinned/unpinned memory. You have to pick one.
* Use a ForeignPtr to allocate pinned memory (mallocForeignPtr)
if you want it mostly poinned. Otherwise, you'll need to copy from unpinned to pinned.
-- Don

gcross:
Thanks, Don. What made me think that this might be possible was the existence of Foreign.StablePtr, since that seems to take a Haskell expression and pin it down. Could this mechanism be harness to pin down arrays, or am I misunderstanding how it works? (Is StablePtr really just making a copy of the expression behind the scenes?)
That doesn't make the memory actually stable, it just keeps a dynamic association between a stable pointer and the actual memory address, so you can look up where a block of memory has moved to, keying only with a pointer-sized value.
My motivation for this is that I will be sweeping back and forth along a data structure that is chain of memory blocks (essentially a pointed list), with ~ 10 to 1000 beads. At any given time I am only working with and updating one bead on the chain, so I am wondering if trying to use unpinned memory for the beads not in use would help by speeding up allocations and allowing the g.c. to rearrange their layout in memory. Each bead has a few memory chunks ranging from ~ 100 bytes to possibly up to tens of kilobytes, depending on a scaling parameter on my algorithm.
If there are many small chunks, unpinned memory is better. Might be ok to copy into pinned memory for the foreign call. -- Don

Hello Gregory, Thursday, November 12, 2009, 12:14:56 AM, you wrote:
Hey everyone! Do you have any suggestions for how I might allocate an aligned block of memory that I can pin while making foreign calls, but leave unpinned the rest of the time to potentially improve allocation and garbage collector performance? Or is this even a good idea?
if your call FFI function marked as unsafe, you may expect that memory block wouldn't moved across call. it's better to ask ghc gurus about details. just an example where memcpy used across non-pinned arrays: freezeSTUArray :: Ix i => STUArray s i e -> ST s (UArray i e) freezeSTUArray (STUArray l u n marr#) = ST $ \s1# -> case sizeofMutableByteArray# marr# of { n# -> case newByteArray# n# s1# of { (# s2#, marr'# #) -> case memcpy_freeze marr'# marr# (fromIntegral (I# n#)) of { IO m -> case unsafeCoerce# m s2# of { (# s3#, _ #) -> case unsafeFreezeByteArray# marr'# s3# of { (# s4#, arr# #) -> (# s4#, UArray l u n arr# #) }}}}} foreign import ccall unsafe "memcpy" memcpy_freeze :: MutableByteArray# s -> MutableByteArray# s -> CSize -> IO (Ptr a) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Wed, 2009-11-11 at 13:14 -0800, Gregory Crosswhite wrote:
Hey everyone! Do you have any suggestions for how I might allocate an aligned block of memory that I can pin while making foreign calls, but leave unpinned the rest of the time to potentially improve allocation and garbage collector performance? Or is this even a good idea?
GHC's memory management does not have any support for temporarily pinning a heap object. Heap objects must start out pinned or unpinned and that cannot be changed later (the current impl uses separate sections of the heap for pinned vs unpinned). As Don says, you can copy from an unpinned to a fresh pinned ByteArray#. If you're prepared to rely on internal properties of GHC's memory manager, then you can use the fact that currently ByteArray#s over a certain size are always pinned. This means that for small unpinned arrays you can just copy when it comes to a foreign call, and for larger ones you can rely on them being pinned. As I said though, this is not a portable technique. Duncan
participants (4)
-
Bulat Ziganshin
-
Don Stewart
-
Duncan Coutts
-
Gregory Crosswhite