Thursday, 21 August 2008

Tip: Calling C functions directly with "noalloc"

In OCaml you can call a C function by writing:

external call_1 : float -> float = "call_1"
then just using call_1. However these calls are not direct. They go via an OCaml runtime function called caml_c_call. This is a tiny bit of assembler, so the overhead isn't large, but it does use a computed jump which on many processors is quite slow.

Luckily this indirection is only needed in order to set up the garbage collector. If your C function won't perform any OCaml allocations, then you don't need this, and you can tell OCaml to jump directly to your C function like this:

external call_2 : float -> float = "call_2" "noalloc"

Let's compare the generated assembly code for the calls in both cases:

Normal "noalloc"

pushl %eax pushl %eax
movl $call_1, %eax call call_2
call caml_c_call addl $4, %esp
addl $4, %esp
movl (%esp), %edx
movl %edx, G(caml_last_return_address)
leal 4(%esp), %edx
movl %edx, G(caml_bottom_of_stack)
jmp *%eax

As you can see, the "noalloc" version is much shorter.


Hezekiah Carty said...

There is also "float" which allows calling C functions with floats completely unboxed. As I understand, though, all values involved must be floats for this to work.

A message from Xavier Leroy on the mailing list is here:

alermo said...


Richard, but where do you find out about this feature? The documentation, I found nothing about it.

Richard Jones said...


"noalloc", and "float" as mentioned by Hezekiah, are not documented in the manual, but are both widely used in the stdlib and in external libraries.