[Haskell-cafe] how to write an haskell binding

Bulat Ziganshin bulat.ziganshin at gmail.com
Tue Jun 27 01:55:25 EDT 2006

Hello Brian,

Tuesday, June 27, 2006, 2:43:15 AM, you wrote:

> achieve a goal. One other thing to bear in mind is that foreign calls are
> extremely slow, so for example it is much faster to use the 
> Foreign.Marshal.Array and Foreign.C.String functions to allocate and 
> populate a temporary array with the contents of a list, and send the pointer
> to this array to C with one foreign call, than to send each element of the
> list with multiple foreign calls (eg to paste only 19K of text from the
> Windows clipboard to my app took over 1 minute!!!

he-he-he :)  just add "unsafe" specifier:

foreign import ccall unsafe  "Compression.h CanonizeCompressionMethod"
   c_CanonizeCompressionMethod   :: CMethod -> CMethod -> IO Int

afair, it was 60k or 600k calls/second on my 1 GHz CPU

in http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/rts-libs/multi-thread.html
there is description why "safe" calls are so slow:

Presently, GHC handles 'safe' C calls by effectively emitting the
following code sequence: 

    ...save thread state...
    t = suspendThread();
    r = foo(arg1,...,argn);
    ...restore thread state...
    return r;

After having squirreled away the state of a Haskell thread,
Schedule.c:suspendThread() is called which puts the current thread on
a list [Schedule.c:suspended_ccalling_threads] containing threads that
are currently blocked waiting for external calls to complete (this is
done for the purposes of finding roots when garbage collecting).

In addition to putting the Haskell thread on
suspended_ccalling_threads, suspendThread() now also does the following: 

- Instructs the Task Manager to make sure that there's a another
native thread waiting in the wings to take over the execution of
Haskell threads. This might entail creating a new worker thread or
re-using one that's currently waiting for more work to do. The Task
Manager section presents the functionality provided by this subsystem.    

- Releases its capability to execute within the RTS. By doing so,
another worker thread will become unblocked and start executing code
within the RTS. See the Capability section for details.

- suspendThread() returns a token which is used to identify the
Haskell thread that was added to suspended_ccalling_threads. This is
done so that once the external call has completed, we know what
Haskell thread to pull off the suspended_ccalling_threads list.

Upon return from suspendThread(), the OS thread is free of its RTS
executing responsibility, and can now invoke the external call.
Meanwhile, the other worker thread that have now gained access to the
RTS will continue executing Concurrent Haskell code. Concurrent
'stuff' is happening!    

Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com

More information about the Haskell-Cafe mailing list