Here u
stands for unsigned. Concerning their safety, it is a very different story. Any compiler primitive is an internal tool and is not for the casual user. First of all they are untyped, and of course, no bound checks are done. But later on it.
No, even with flambda and O3.
It is useful when you want to have an extra type safety without sacrificing performance,
type modulus = Modulus of int [@@unboxed]
Will have the same representation as int
but it would be hard for you to confuse int
with modulus
, for example.
Yep, but not the -dparsetree
, I was talking about -dcmm
, -dlinear
and lots of -d
from flambda could be very insightful. (the -dparstree
option outputs the source code as it is parsed, we’re interested in the code that is generated). See the output of ocamlopt -help
for more options.
At some point packet buffers have to be passed to the user and I don’t think going the C route (having the user preallocate an array and then just filling in the array in the driver) is very OCaml-y.
I would have a pool of abstract iovec
data structures, which will be bigarrays underneath the hood. They all will be preallocated during the driver initialization time, based on drivers parameters. The same as Linux kernel is doing, basically.
This will work out of the box, if you will do bigarray copying/blitting the primitives that will do this will release the runtime. So you can use plain OCaml threads which maps to native threads and copy in parallel as many buffers as you like. Of course, you will need to implement some synchronization, as usual.
Safety in OCaml
A feature is unsafe if it may break type system or bypass array bounds check.
- any usage of Obj.magic is unsafe and should be reserved for standard library implementers.
- any usage of a primitive is even more unsafe, and even more fragile.
So if not sure, you should rely on some library that provides high-level constructs that are based on those primitives. (Basically, it should be either OCaml standard library or Janestreet Base/Core).
What is OCamlish
Let’s not confuse low-level programming with unsafe features or non-idiomatic style. OCaml is an excellent language for low-level and system programming. It suits excellent into real-time and HPC environment. It requires, however, some understanding of how it works, and careful design of the interface. The same as with other languages, different contexts imply different styles. That’s true even for C. So low-level programming is not non-idiomatic for OCaml, see for example this book, as well as lots of examples from the Mirage team. With all that said, it is non-idiomatic to apply the high-level style to low-level code. So no arrays, strings, allocations, records, and other high-level sugar in the low-level code. You can still use the full power of OCaml, especially relying heavily on abstract data types to protect your invariants, and on GADT to make typesafe flags and enumerations.
Speaking on GADT, I’ve seen somewhere in your code that you’re using variants with payloads. You can easily substitute it with GADT, without a payload, which won’t require any allocations, e.g.,
type 'a opt =
| Debug : unit opt
| TTL : int opt
| Threshold : float opt
let setopt (type t) (opt : t opt) (arg:t) = match opt with
| Debug -> printf "enabled debugging"
| TTL -> printf "set TTL to %d" arg
| Threshold -> printf "set threshold to %g" arg;;
To summarize, an idiomatic OCaml code could be efficient, but you have to change your style. And that is not to say, that you’re no longer coding OCaml, in fact, you should be even more OCamlish than ever, and use more types, more modules, more abstractions, because you have more invariants to protect.