In this code, we’re allocating a custom block that represents a large handle (allocated by a C library). The C handle is actually 9000 bytes (yes, it’s grown a bit in the last 6 years). Only a pointer to the C handle (4 or 8 bytes) is stored inside the custom block.
This code works fine.
I wonder however if I’m using caml_alloc_custom_mem correctly here. The documentation, and even the code, is not very clear at all. It seems like maybe the sizeof and 5000 parameters should be swapped?
Or maybe using the function is wrong. caml_alloc_custom also lets you hint about the resources needed, so should we use that instead? If so, what’s the difference between the size, mem and max parameters of this function?
Thanks - I think looking at those examples, we are actually using the API correctly. A question I still have is why caml_alloc_custom_mem exists at all, what is the difference from caml_alloc_custom?
caml_alloc_custom was the original function. But it was really tedious to use, as you had to guess what to pass as the fourth argument, and more often than not, people would get this argument wrong, thus causing runtime performances to drop heavily. (I am looking at you, iterators in Lablgtk!) caml_alloc_custom_mem gives a much more intuitive meaning to the arguments (though a bit less flexible), which avoids the issue entirely.
Another important point is that the GC pacing specified by caml_alloc_custom_mem is user-adjustable using the custom_major_ratio, custom_minor_ratio, and custom_minor_max_size parameters via Gc.set, giving caml_alloc_custom_mem an advantage when used in libraries.
For controlling resource usage that isn’t memory but is still dictated by the GC lifetime of a custom block (I’m not saying that is a good idea), then caml_alloc_custom gives better control. And the parameters of caml_alloc_custom_mem are unitless but interpreted as proportional to the heap size, so make less sense for non-memory resources.
For info, there are also uses of caml_alloc_custom_mem in Z3. In that situation custom blocks are used to manage reference-counted C objects. It is not possible to known the amount of off-heap memory that freeing such a custom block will release, but the parameters are still useful as scaling factors to adjust the GC pacing.