Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Alan Schmitt <alan.schmitt@polytechnique.org>
To: "lwn" <lwn@lwn.net>, caml-list@inria.fr
Subject: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News
Date: Tue, 04 Aug 2026 09:44:24 +0200	[thread overview]
Message-ID: <m2ldamnxd3.fsf@mac-03220211.irisa.fr> (raw)


[-- Attachment #1.1.1: Type: text/plain, Size: 32711 bytes --]

Hello

Here is the latest OCaml Weekly News, for the week of July 28 to August
04, 2026.

Table of Contents
─────────────────

SQLite rewritten in Pure OCaml with Claude Code for use in Mirage Unikernels
New opam packages available : CamlSurf and Gles3
bcfg, a Boringly Simple ConFiGuration format
Introcaml (alpha): Polymorphic Printing and Introspection for OCaml
Learnings from benchmarking OxCaml-flavoured SWAR memchr
OCaml Runtime Meeting: Mon, July 6 @ 10:00 UTC (10:00 London/Cambridge, 11:00 Paris, 7pm Sydney)
Old CWN


SQLite rewritten in Pure OCaml with Claude Code for use in Mirage Unikernels
════════════════════════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/sqlite-rewritten-in-pure-ocaml-with-claude-code-for-use-in-mirage-unikernels/18401/1>


Tej Pochiraju announced
───────────────────────

  Hi all,

  For an internal project, I recently ported SQLite to pure OCaml for
  use within Mirage. Please find the [repo here]. Please note this is
  *AI generated* code - I designed and set up the test harness (Jepsen +
  SQLite parity) but didn't write any of the code.

  Beyond standard relational tables, there's fledgling support for
  column oriented tables to use in OLAP type queries. While already
  fairly capable, I expect this will see more commits as I make progress
  on the larger project.

  The larger goal is a full-fledged IoT based workflow framework I am
  building for use at my company, IoTReady.com. Our current framework is
  JS based and uses SQLite + Parquet as DBs. I wanted something similar
  but suitable for running within Mirage to meet some security and
  isolation density requirements. That framework is WIP and may not be
  released publicly.

  Hope this is useful to someone else too. Feel free to file feature
  requests and issues.

  Tej


[repo here] <https://github.com/tejpochiraju/granary>


New opam packages available : CamlSurf and Gles3
════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/new-opam-packages-available-camlsurf-gles3/18404/1>


Christophe Raffalli announced
─────────────────────────────

  Dear Camlers,

  I am pleased to announce the latest version of *Gles3* and a new
  available software *CamlSurf*


CamlSurf.1.0
╌╌╌╌╌╌╌╌╌╌╌╌

  <https://github.com/craff/CamlSurf>

  CamlSurf is a software written using Gles3 that allows visualization
  of implicit surfaces and curves. You write a small script defining
  your surfaces and curves, then run one or more scripts with
  `CamlSurf_x11 script' or `CamlSurf_wayland script'.

  To install, `opam install CamlSurf_x11' or `opam install
  CamlSurf_wayland' should work (after `opam update').

  See <https://raffalli.eu/CamlSurf> for the documentation and a nice
  video.


Gles3.20260725
╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  <https://github.com/craff/gles3>

  Gles3 is an interface to open GLES3.2 and EGL to do graphic
  programming. The main novelty compared to the previous version from
  2016 are:

  • Support for two backends : x11 and wayland. windows (wgl) and macos
    (cocoa) backends are planned, volunteers are welcome.
  • Support for a lot of architectures : all the architectures provided
    by the opam-ci including freebsd and macos using quartzx as X server
    should work.  One exception is win32, but actually it should build
    using x11 too. If I a volunteer can give it a try and tell me the
    msys2 or cygwin package list, I would do an update.  Although it
    compiles on opam-ci, there might be bugs when running the
    examples. Bug report are welcome!
  • Multiple window : the new version can handle several windows. The
    simplest solution in that case is to run each event-loop in its own
    domain (see examples/windows). This is only because of that example
    that we require OCaml 5. Compilation from source should work on
    OCaml 4.14 too except for that example.
  • Basic support to load a font and convert a text to a texture.
  • Cleaned / extended examples, for instance a new example shows how to
    write a shader to get the 3D coordinates of a clicked pixel
    (allowing for precise object movement using the mouse)


bcfg, a Boringly Simple ConFiGuration format
════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/ann-bcfg-a-boringly-simple-configuration-format/18405/1>


Calascibetta Romain announced
─────────────────────────────

  I am pleased to announce the first release of [`bcfg'], a tool and
  library for manipulating and generating configuration files in the
  [Simple ConFiGuration file format] (B stands for “boringly”). The
  `bcfg' project stems from Léo Andrès’s (@ancolie) [scfg] project (see
  <https://discuss.ocaml.org/t/ann-first-release-of-scfg/9249>), but
  aims to go a step further:
  • it extends the syntax so that non-UTF-8 strings are accepted in a
    form similar to that specified in RFC822 (including
    _folding-whitespace_)
  • the dependency set has also been reduced to use only `ocamllex'
    instead of `sedlex', which is perfectly capable of handling UTF-8
    strings
  • the distribution includes a `bcfgt' library based on @dbuenzli’s
    [jsont] design and a draft implementation of @swrup on `scfg'
  • the tool has been extended to include a linter (allowing
    configuration files to be reformatted) as well as a "`jq'-style"
    query tool to extract information from an expression and a
    configuration file
  • the ability to stream serialisation and deserialisation (as can be
    done with XML and the SAX model)

  The tools are also available on our apt.robur.coop repository via [our
  reproducible infrastructure]:
  ┌────
  │ $ curl -fsSL https://apt.robur.coop/gpg.pub | gpg --dearmor > /usr/share/keyrings/apt.robur.coop.gpg
  │ $ echo "deb [signed-by=/usr/share/keyrings/apt.robur.coop.gpg] https://apt.robur.coop debian-13 main" \
  │   | sudo tee /etc/apt/sources.list.d/robur.list
  │ $ sudo apt update
  │ $ sudo apt install bcfg
  └────

  We recommend reading the [bcfg documentation] to learn more about this
  format, these libraries and these tools, in the hope that we might
  also resolve or further complicate the existential questions regarding
  the world’s best configuration format.

  <https://us1.discourse-cdn.com/flex020/uploads/ocaml/original/2X/a/a2d5a1751cf967114b36a25ce73ab4f86050e68c.png>


[`bcfg'] <https://github.com/robur-coop/bcfg>

[Simple ConFiGuration file format] <https://git.sr.ht/~emersion/scfg>

[scfg] <https://forge.kumikode.org/kumikode/scfg>

[jsont] <https://github.com/dbuenzli/jsont>

[our reproducible infrastructure] <https://builder.robur.coop>

[bcfg documentation] <https://docs.osau.re/local/bcfg/Bcfg/index.html>


Introcaml (alpha): Polymorphic Printing and Introspection for OCaml
═══════════════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/ann-introcaml-alpha-polymorphic-printing-and-introspection-for-ocaml/18407/1>


Frédéric Bour announced
───────────────────────

  We are excited to share an alpha preview of *Introcaml*, an extension
  of OCaml 5.5.0 that brings the power of toplevel-style introspection
  directly into user programs.


What is Introcaml?
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  The OCaml toplevel has long been able to print arbitrary values
  without requiring explicit printer functions. However, this capability
  was internal to the toplevel. *Introcaml* brings this machinery into
  the standard library, enabling polymorphic printing and structural
  introspection of values of any type.

  By recovering structure from metadata embedded in compiled code,
  Introcaml allows you to inspect complex data structures, even those
  hidden behind abstraction barriers, without writing tedious `pp'
  functions.


🚀 How to Try It
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  Introcaml is available via opam. The recommended way to test the alpha
  version is to create a specific switch:

  ┌────
  │ opam switch create 5.5.0+introcaml
  └────


◊ Key Capabilities:

  • Polymorphic printing: Print any value regardless of its type,
    including abstract types.
  • Fully integrated with the toplevel, the debugger, the
    bytecode/native compilers, and their respective dynamic linkers.


◊ Code Examples

  ┌────
  │ open Introspect.Print
  │ 
  │ (* 1. Simple polymorphic printing *)
  │ type config = { host : string; port : int; debug : bool }
  │ print_any_endline { host = "localhost"; port = 8080; debug = true };;
  │ (* Output: {host = "localhost"; port = 8080; debug = true} *)
  │ 
  │ (* 2. Breaking through abstraction *)
  │ module M = Map.Make(Int)
  │ print_any_endline (M.of_list [1, "one"; 2, "two"]);;
  │ (* Output: Node {l = Empty; v = 1; d = "one"; r = Node {l = Empty; v = 2; d = "two"; r = Empty; h = 1}; h = 2} *)
  │ 
  │ (* 3. Quick 'n' Dirty printing with Introspect.P *)
  │ open Introspect.P
  │ let month = "August"
  │ let year = 2026
  │ let () = println ["Welcome to "; month; " "; year; "!"]
  │ (* Output: Welcome to August 2026! *)
  └────

  —


🛠 How it Works
╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  Introcaml implements a probabilistic metadata recovery scheme designed
  for high performance:

  1. *Reserved bits:* It stores a "tag" in the reserved header bits of
      OCaml objects.
  2. *Index:* A side-database (`Introspect.Index.t') maps these tags to
      a *descriptor* (`Introspect.Desc.t'), which describes the
      syntactic representation of the value.
  3. *Zero overhead:* The compilation scheme is designed so that
      overhead is negligible in bytecode and virtually nonexistent in
      native mode.


◊ The [`Introspect'] API

  The new `Introspect' module provides several layers of access:

  *Low-level (for tool authors):*

  • `Desc': The representation of structural descriptors.
  • `Index': The mapping from object headers to descriptors.
  • `Dyn': A dynamic view of OCaml objects guided by descriptors,
    allowing for programmatic traversal (ideal for custom debug tools).

  *High-level (for general use):*

  • `Print': A `Format'-based polymorphic printing API.
  • `P': A convenience module for "quick and dirty" generic printing.

  —


  [`Introspect']
  <https://github.com/let-def/ocaml/blob/introcaml-550/stdlib/introspect.mli>


🔍 Integration with existing printers
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  Previously, printing an opaque type in the toplevel or the debugger
  would simply result in `<abstr>'. Now, these tools use type-directed
  printing by default but seamlessly switch to tag-based printing when
  encountering opaque constructions.

  ┌────
  │ # let h = Hashtbl.create 3;;
  │ val h : ('_weak3, '_weak4) Hashtbl.t =
  │   <abstr>
  │     {size = 0; data = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  │      seed = 0; initial_size = 16}
  └────

  —


⚠️ Limitations & Current Status (Alpha)
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  As this is an alpha release, there are several known limitations. Some
  are temporary, while others are inherent to the design:

  • *Architecture & Compiler:*
    ‣ Does not support 32-bit architectures. (Tested on x86_64 and
      arm64).
    ‣ Not compatible with Flambda.
    ‣ `js_of_ocaml' is currently unsupported (though a fix is
      straightforward).
  • *Metadata Constraints:*
    ‣ *Constants:* Due to limited space for metadata, some constants
       cannot be printed (e.g., `print_any None' may print `0', but
       `println [None]' will likely succeed because the list wrapper
       provides metadata).
    ‣ *Poly-variants:* These are approximated (e.g., `print_any `A' may
       print `65 or `A').
    ‣ *FFI:* Values originating from the FFI are not tagged and will be
       printed as raw tuples/values unless wrapped in a tagged
       structure. (Note: FFI compatibility is entirely preserved).
  • *Marshalling:* Tags are not preserved during marshalling by
     default. To preserve them, you must opt-in using the
     `Reserved_bits' flag:

    ┌────
    │ let roundtrip flags x = Marshal.from_string (Marshal.to_string x flags) 0;;
    │ println [roundtrip [Reserved_bits] (ref 1)];; (* Output: {contents = 1} *)
    └────
  • *Object Size:* By reserving 22 bits for metadata, the maximum length
     for arrays is \~4 billion elements and for strings is 32GB.

  —

  *Acknowledgements:* This work is funded by the [Ahrefs Grant Program
  for OCaml].

  Kudos to Çağdaş Bozman et al. for the original work on `ocp-memprof',
  which provided the idea and infrastructure for repurposing header
  bits, and many thanks to the maintainers who have preserved this
  capability.

  🤖 *Note:* No robots were harmed during the design and implementation
  of this feature, though their help was solicited for testing and
  proof-reading.


[Ahrefs Grant Program for OCaml]
<https://discuss.ocaml.org/t/ahrefs-grant-program-for-ocaml>


Learnings from benchmarking OxCaml-flavoured SWAR memchr
════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/learnings-from-benchmarking-oxcaml-flavoured-swar-memchr/18411/1>


Keith discussed
───────────────

  /Editor’s note: there were many long replies to this post, please
  follow the link above for the full discussion./

  Hi everyone, just wanted to share a benchmarking project that I had
  created over the past few days for testing out OxCaml:

  <https://github.com/KiChjang/ml-memchr>

  I come from 10+ years of Rust, started hacking on it when it still had
  the Ruby-inspired closure syntax where parameters denoted by the two
  pipes are written inside of the block instead of outside of it
  (i.e. `{|arg| statements;}' instead of `|arg| { statements;
  }'). Certainly not the earliest batch, but early enough to know that
  before Rust was self-hosted, the compiler was written in OCaml, which
  is why I'm really interested in seeing how OCaml is "learning from its
  child". I had a brief stint in writing OCaml at a startup, but that
  was too short of a time to consider myself familiar with it.

  The README.md of the repo does a fairly good job in explaining the
  intricate details, and admittedly AI was used to write it, but what AI
  cannot tell you is the experience of writing it. Yes, I used AI, but
  no, I did not let it write everything, because one of the aims of this
  exercise is to help me learn both OCaml and OxCaml.

  Let's go through the good, the bad and the ugly parts of coding in
  OxCaml. Bear in mind that some of these points are due to me being an
  OCaml noob and am still learning things about the language.


The Good
╌╌╌╌╌╌╌╌

  *The conciseness and the compile-times*. I'm absolutely floored by
   just how elegant idiomatic OCaml source code looks. Everything just
   works without much ceremony: no braces nor brackets, no random `fn'
   keywords, and most importantly no cruft that gets in the way – you
   just `let there = light', and `there' was `light'. Not only that, the
   compile-verify-rewrite loop is quite fast, precisely because compile
   times are amazingly fast, so fast that even `utop' exists as a REPL,
   allowing me to test ideas out before committing to them. These aren't
   things that a Rustacean is used to: normally what happens is that
   whenever I encounter a new crate, I rely on docs.rs for documentation
   about the features coming from the crate, or spend time creating a
   new unit test and compiling it to see how it works. I can really now
   see why OCaml developers would want to continue writing OCaml despite
   it not being one of the most popular languages out there.

  *Dune*. This sort of ties back into the previous point on conciseness:
   build configuration is really just tuples/s-expressions. While I can
   still pretty much achieve the same effects in Rust with `Cargo.toml',
   everything being s-expressions in dune means that there really isn't
   much overhead. I now come to think of this style as *minimally yet
   sufficiently concise*, e.g. the brackets in an s-expression is the
   minimal structure around data, and semantics simply just fall out
   from what you put between the brackets. Integration with C is pretty
   seamless as well, along with Rust, though the latter still requires
   teaching dune to use cargo, which doesn't really strike me as
   surprising as C is much more well-established as the lingua franca in
   systems programming.

  *`[@@zero_alloc]'*. This is what OxCaml brings to the table and it
   delivers right away – mark your `val~s with it in your interface
   definitions, and it'll immediately try and catch any possible
   allocations that you make within your function. I'm used to zero-cost
   abstractions so being made aware that some language features aren't
   free in terms of allocations was quite new to me (I'm looking at you,
   ~option'). It makes sense upon closer inspection, but the initial
   surprise is still there – I guess I'm just really not used to
   thinking that nice language features have non-trivial costs
   associated with them. Anyway, the annotation certainly took a page
   from Rust, where the check happens *all at compilation time*, so code
   that compiles with that annotation is guaranteed not to allocate
   anything by the compiler. I love my parents.

  *Mutable local variables*. I know enough OCaml to know that the
   standard way is to use `'a ref', but seeing how `mutable' just works
   exactly the way I thought without much fanfare was quite nice. It
   also doesn't require using the `!' prefix when "dereferencing" the
   variable to read its value; the only downside is that it still does
   require `<-' for assignment. That's inevitable, since `=' has been
   overloaded with too much meaning; in fact, the odd one out here is
   logical equality, since let-bindings and record fields are arguably
   both in the same category of assignment operators.

  *Unboxed tuples and records*. They just work as expected, even in
   patterns. You really just need to prefix everything with `#', and
   it'll work, e.g. the common pattern that I often use in Rust when I
   need to return or bind two or more values at the same time is to use
   tuples, and in OxCaml it's pretty much the same:

  ┌────
  │ let #(a, b) = if cond then #(#8L, foo) else #(#3L, bar)
  └────

  *Automatic byte alignment*. OCaml strings and byte arrays are
   automatically aligned to a whole number of words, so I never need to
   worry about misalignment when reading the final partial word, nor
   requiring a prologue to first advance bytes so that it lands on a
   word boundary.


The Bad
╌╌╌╌╌╌╌

  *Functionality incompleteness*. This may just be a result of OxCaml
   still being a fairly new language extension, but some basic
   operations just aren't there when I reach out for them during
   development – logical infix operators, bit shifting, and even
   comparison infix operators. Some of them are not even in stdlib at
   all, but rather part of the compiler intrinsics – I had to dig
   `Bytes.unsafe_get_in64_ne_indexed_by_int64' out from the compiler
   source code in order to know that such functionalities even existed,
   and an unsafe load for unsigned `int8' currently doesn't exist even
   as an intrinsic anywhere. On the other hand, I get why the
   polymorphic infix operators don't work – `'a' has the `value' layout,
   and `int64#' has `bits64', and structural comparison between the two
   just wouldn't work. It would be so great if the polymorphic operators
   also ignores the layout that the arguments have as long as they
   match.

  *Performance impacts on certain functions*. Specifically, the ones
   that mix-and-match parameters with their boxed and unboxed
   counterparts. This may not actually affect anything, but I've been
   lied to by Claude so many times that I have to put this up, because
   intuitively speaking, unboxing and especially boxing has a
   non-negligible cost associated with them, and
   e.g. `Int64_u.shift_{left,right}' requires me to use an unboxed 2nd
   argument to indicate how many bits I want to shift by. I've been told
   that boxing for comparison using `Int64_u.compare' doesn't allocate
   anything despite having to compare the resulting boxed integer, and
   Claude says the disassembly from `memchr.a' proves it:

  ┌────
  │ Int64_u.(compare ((to_int i) + 8) n < 0)
  │ ---
  │ 22a:  lea    0x11(%rbx,%rbx,1),%r12   ; 2i + 17, i.e. tagged(i + 8)
  │ 22f:  cmp    %rdi,%r12                ; vs tagged n
  │ 232:  jg     280
  └────

  I really can't know for sure whether this is every instruction emitted
  by the expression since `i' originally was an unboxed integer, and
  Claude may be missing the context where `i' is being retagged/reboxed
  again just to make this comparison.

  The unboxed variant looks like the following:

  ┌────
  │ Int64_u.(compare (i + #32L) (of_int n) < 0)
  │ ---
  │ 101:  lea    0x20(%rbx),%r12      ; i + 32
  │ 109:  cmp    %rsi,%r12            ; vs n, pre-untagged at 0xd7
  │ 10c:  jg     224
  └────

  Taken at face value, both generate the same number of instructions and
  all but the parameters are identical, so if there's anything that's
  different, it has to be the hidden costs of the parameters being
  passed to these instructions. This bit matters, because it's in the
  hot loop execution path, and every instruction or nanosecond we save
  here can scale up to micro or even milliseconds saved.

  *Ergonomics*. This cuts both ways, I really like the localized imports
   that I showcased above with `Int64_u.(expression)' instead of tagging
   each function repeatedly, but doing it over and over again gets
   repetitive. I could indeed use a local import by doing `let open
   Int64_u in', however there are times where this doesn't work as
   expected, especially when I have to deal with boxed integers of
   varying sizes as well, like the aforementioned `int'. I don't think
   this is a problem that can be solved generally unless we solve the
   problem of polymorphic layouts, so I'd still list this as a pain
   point.


The ugly
╌╌╌╌╌╌╌╌

  *No continues/breaks/early returns*. This is starting to get really
   ugly – while I understand the argument from functional programmers
   that imperative code can usually be rewritten in a purer functional
   style without mutation, we're now in systems programming land, and
   every instruction emitted counts, and not being able to directly jump
   to where I want using continues, breaks or returns is a huge hole in
   my repertoire. Take for example, the code that I had to use to force
   an early exit in the loop:

  ┌────
  │  while Int64_u.(i + #8L <= n64) do
  │   let r = swar_raw (Bytes.unsafe_get_int64_ne_indexed_by_int64 s i) in
  │   if not Int64_u.(r land mask = #0L) then (
  │     hit <- i;
  │     i <- n64)
  │   else i <- Int64_u.(i + #8L)
  │ done
  └────

  See what I did here? I essentially have to assign `n64' to `i' so that
  the loop condition fails just to "break" from the loop. And we're not
  done here either, because `i' denotes the offset at which to start
  reading bytes, so a later loop needs it to be preserved:

  ┌────
  │ if Int64_u.(hit >= #0L) then i <- hit;
  └────

  I got lucky here because I am able to recover `i' quite easily as I've
  assigned it to `hit', but one can easily imagine that you can't be as
  lucky with other loops. You may have to keep spare variables around
  just to store the state of the loop when you break it, just to
  preserve it and use it on subsequent code paths. Granted, this may not
  be as much of a problem as I make it to be, since it's not on the hot
  execution path but rather done at most once every loop, but `continue'
  is certainly not the case. I guess in a proper TCO'd recursive
  function, calling the function again with new parameters would be
  equivalent to a continue, but I haven't tested it out enough yet to
  really conclude that TCO is as fast as an imperative loop.

  *Attributes can be trivially defeated*. Not an OxCaml problem per se,
   but I accidentally defeated the usage of `[@inline always]' in the
   idiomatic ML flavour of memchr because the function I'm annotating
   captures a variable from the environment:

  ┌────
  │ let[@inline always] swar_raw w =
  │   let w = Int64_u.(w lxor cs) in
  │   Int64_u.((w - ones) land lognot w)
  │ in
  └────

  Both `cs' and `ones' aren't passed in as parameters, so now `swar_raw'
  becomes a real function that gets allocated *on the stack*, which
  means both `[@@zero_alloc]' and the benchmark's `mWd/Run' didn't catch
  it, as they measure *heap allocations*. Unfortunately, even stack
  allocations still cost performance, because calling functions are not
  free and requires setting up the call frame, loading the environment
  variables from memory, saving the context in the callee, and cleaning
  up before returning to the callee, none of which are trivial costs
  that can easily be eliminated.

  Admittedly, this was my personal skill issue for not being well-versed
  enough in OCaml, I just have a feeling that the compiler should have
  at least warned me that it isn't inlining the function as I told it to
  due to captured variables. Fixing this bug immediately brought the ML
  functional style memchr implementation down to the same speed as the
  imperative ML style memchr, and maybe even 1-2% faster based on
  benchmarks.


Closing thoughts
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  Let's put into perspective about the numbers: OCaml's `Byte.index' is
  about 10x slower than the Rust/C equivalent, whereas OxCaml managed to
  get it down to about only 1.3x slower. This magnitude of difference is
  a huge win! With OxCaml as a language extension that may have its
  features upstreamed, OCaml can now have its system's slice of the cake
  and eat it too by being in the same order of magnitude as C/Rust. I'd
  say that OxCaml has completely justified its raison d'être, especially
  on the part where one can write idiomatic-ish OCaml syntax sprinkled
  with unboxed integers and still get performance close to bare metal.

  I think it's also good to address the friction points while developing
  in OxCaml – while writing this post, I've also tried to write a
  largely safe, idiomatic Rust version of memchr, and that alone is
  already about 10% faster than the OxCaml equivalent. What I wanted to
  bring up here isn't my varying skill levels in these two languages
  (although it may have indeed played a factor), but rather *how the
  programming language's philosophy guides the way you think*. If you've
  heard of linguistic relatively or the older Sapir-Whorf hypothesis in
  linguistics, this is exactly that, applied to programming languages –
  Rust is fundamentally about building safe, robust and efficient
  software, so the language features such as zero-cost abstractions,
  horrendously long compile times, bloated compiler error messages is
  designed exactly for you to write code that's going to be safe and
  fast by default.

  OCaml is not that, and it doesn't have to pretend to be something it
  isn't either, because it also has advantages over Rust that is hard to
  replicate there – fast compile times, layouts that are so uniform to
  the point where you really don't think about them, tail-call
  optimizations that brings loops/recursions close to bare-metal speed,
  and a richer type system that supports GADTs and monads, and let's not
  forget – without OCaml, there wouldn't be Rust. There's clearly still
  a lot that OCaml can offer to the world, and we (basically just me)
  still haven't seen all it has to offer yet.

  The pain points that I've listed are mostly because OxCaml is
  ostensibly written for systems programmers to write efficient code,
  and the syntax/tooling right now simply doesn't exactly support those
  goals just yet. Making it run faster is great; allowing anyone to
  easily write programs that are by default running efficiently is
  awesome.


What's next
╌╌╌╌╌╌╌╌╌╌╌

  OxCaml has SIMD support via `oxcaml_simd', so that's the natural next
  step to test and see how it fares when compared with the optimized C
  and Rust versions, the latter provided by BurntSushi's [`memchr'
  crate] (yes, it's his real username). After that, I'm looking to see
  if I can port some small and self-contained Rust crates over to OxCaml
  and continue experimenting on the performance characteristics. Bear in
  mind that `memchr' is a constrained example operating with only the
  input arguments; it'll be interesting to see how it works with systems
  that require storage and memory over time.


[`memchr' crate] <https://crates.io/crates/memchr>


OCaml Runtime Meeting: Mon, July 6 @ 10:00 UTC (10:00 London/Cambridge, 11:00 Paris, 7pm Sydney)
════════════════════════════════════════════════════════════════════════════════════════════════

  Archive:
  <https://discuss.ocaml.org/t/ocaml-runtime-meeting-mon-july-6-10-00-utc-10-00-london-cambridge-11-00-paris-7pm-sydney/18312/6>


Continuing this thread, Tim McGilchrist announced
─────────────────────────────────────────────────

  Thank you for the correct @kit-ty-kate I'll post the notice a bit
  earlier for next month. The notes are available on
  <https://hackmd.io/Cwj7lWjuRlKEr8H8F6wpRw?view#Agenda-Items-for-meeting-on-August-3rd-2026>

  The next edition will be Monday October 5th at the same time.


Old CWN
═══════

  If you happen to miss a CWN, you can [send me a message] and I'll mail
  it to you, or go take a look at [the archive] or the [RSS feed of the
  archives].

  If you also wish to receive it every week by mail, you may subscribe
  to the [caml-list].

  [Alan Schmitt]


[send me a message] <mailto:alan.schmitt@polytechnique.org>

[the archive] <https://alan.petitepomme.net/cwn/>

[RSS feed of the archives] <https://alan.petitepomme.net/cwn/cwn.rss>

[caml-list] <https://sympa.inria.fr/sympa/info/caml-list>

[Alan Schmitt] <https://alan.petitepomme.net/>


[-- Attachment #1.1.2: Type: text/html, Size: 49424 bytes --]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 568 bytes --]

             reply	other threads:[~2026-08-04  7:44 UTC|newest]

Thread overview: 304+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-04  7:44 Alan Schmitt [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-07-28 12:44 Alan Schmitt
2026-07-21 16:02 Alan Schmitt
2026-07-14  7:16 Alan Schmitt
2026-07-07 13:29 Alan Schmitt
2026-06-30 13:25 Alan Schmitt
2026-06-23 10:07 Alan Schmitt
2026-06-16 10:51 Alan Schmitt
2026-06-09  7:39 Alan Schmitt
2026-06-02  9:01 Alan Schmitt
2026-05-26  7:36 Alan Schmitt
2026-05-19  8:52 Alan Schmitt
2026-05-12  7:28 Alan Schmitt
2026-05-05  9:35 Alan Schmitt
2026-04-28  7:59 Alan Schmitt
2026-04-21  9:34 Alan Schmitt
2026-04-14  9:50 Alan Schmitt
2026-04-07  9:32 Alan Schmitt
2026-03-31  6:10 Alan Schmitt
2026-03-24  9:58 Alan Schmitt
2026-03-17 14:39 Alan Schmitt
2026-03-10 13:30 Alan Schmitt
2026-03-03 13:54 Alan Schmitt
2026-02-24 13:36 Alan Schmitt
2026-02-17 13:47 Alan Schmitt
2026-02-10 10:36 Alan Schmitt
2026-02-03 10:04 Alan Schmitt
2026-01-27 12:41 Alan Schmitt
2026-01-20  9:19 Alan Schmitt
2026-01-13  8:27 Alan Schmitt
2026-01-06 13:14 Alan Schmitt
2025-12-30  9:33 Alan Schmitt
2025-12-23 11:00 Alan Schmitt
2025-12-16 13:30 Alan Schmitt
2025-12-09 15:04 Alan Schmitt
2025-12-02 10:39 Alan Schmitt
2025-11-25 13:49 Alan Schmitt
2025-11-18 14:01 Alan Schmitt
2025-11-11  9:49 Alan Schmitt
2025-11-04 13:21 Alan Schmitt
2025-10-28 13:30 Alan Schmitt
2025-10-21  9:17 Alan Schmitt
2025-10-14  9:56 Alan Schmitt
2025-10-07 12:22 Alan Schmitt
2025-09-30 13:12 Alan Schmitt
2025-09-23 13:23 Alan Schmitt
2025-09-16 11:52 Alan Schmitt
2025-09-09 12:30 Alan Schmitt
2025-09-02 12:23 Alan Schmitt
2025-08-26 12:34 Alan Schmitt
2025-08-19 12:20 Alan Schmitt
2025-08-12 15:32 Alan Schmitt
2025-08-05  8:17 Alan Schmitt
2025-07-29  9:36 Alan Schmitt
2025-07-22 12:07 Alan Schmitt
2025-07-15 17:14 Alan Schmitt
2025-07-08 12:45 Alan Schmitt
2025-07-01 11:16 Alan Schmitt
2025-06-24 14:02 Alan Schmitt
2025-06-17  6:44 Alan Schmitt
2025-06-10 13:36 Alan Schmitt
2025-06-03  9:19 Alan Schmitt
2025-05-27  9:22 Alan Schmitt
2025-05-20 11:52 Alan Schmitt
2025-05-13  9:40 Alan Schmitt
2025-05-06  7:24 Alan Schmitt
2025-04-29  8:39 Alan Schmitt
2025-04-22 11:50 Alan Schmitt
2025-04-15  9:51 Alan Schmitt
2025-04-08 13:14 Alan Schmitt
2025-04-01  9:12 Alan Schmitt
2025-03-25  8:06 Alan Schmitt
2025-03-18 10:18 Alan Schmitt
2025-03-11 15:00 Alan Schmitt
2025-03-04 14:01 Alan Schmitt
2025-02-25 10:36 Alan Schmitt
2025-02-18 14:33 Alan Schmitt
2025-02-11  7:17 Alan Schmitt
2025-02-04 12:05 Alan Schmitt
2025-01-28 13:24 Alan Schmitt
2025-01-21 15:47 Alan Schmitt
2025-01-14  8:20 Alan Schmitt
2025-01-07 17:26 Alan Schmitt
2024-12-31  8:03 Alan Schmitt
2024-12-24  8:55 Alan Schmitt
2024-12-17 13:05 Alan Schmitt
2024-12-10 13:48 Alan Schmitt
2024-12-03 14:44 Alan Schmitt
2024-11-26  8:30 Alan Schmitt
2024-11-19  6:52 Alan Schmitt
2024-11-12 15:00 Alan Schmitt
2024-11-05 13:22 Alan Schmitt
2024-10-29 13:30 Alan Schmitt
2024-10-22 12:42 Alan Schmitt
2024-10-15 13:31 Alan Schmitt
2024-10-08 10:56 Alan Schmitt
2024-10-01 13:37 Alan Schmitt
2024-09-24 13:18 Alan Schmitt
2024-09-17 14:02 Alan Schmitt
2024-09-10 13:55 Alan Schmitt
2024-09-03  8:24 Alan Schmitt
2024-08-27  9:02 Alan Schmitt
2024-08-20  9:29 Alan Schmitt
2024-08-13 13:21 Alan Schmitt
2024-08-06  9:00 Alan Schmitt
2024-07-30 13:26 Alan Schmitt
2024-07-23 13:30 Alan Schmitt
2024-07-16  6:24 Alan Schmitt
2024-07-09  9:19 Alan Schmitt
2024-07-02  7:30 Alan Schmitt
2024-06-25 13:58 Alan Schmitt
2024-06-18 13:05 Alan Schmitt
2024-06-11 15:04 Alan Schmitt
2024-06-04 13:26 Alan Schmitt
2024-05-28  9:07 Alan Schmitt
2024-05-21 13:07 Alan Schmitt
2024-05-14 13:25 Alan Schmitt
2024-05-07  7:30 Alan Schmitt
2024-04-30  7:22 Alan Schmitt
2024-04-23 12:17 Alan Schmitt
2024-04-16 12:00 Alan Schmitt
2024-04-09  9:15 Alan Schmitt
2024-04-02 14:31 Alan Schmitt
2024-03-26  6:32 Alan Schmitt
2024-03-19 15:09 Alan Schmitt
2024-03-12 10:31 Alan Schmitt
2024-03-05 14:50 Alan Schmitt
2024-02-27 13:53 Alan Schmitt
2024-02-20  9:12 Alan Schmitt
2024-02-13  8:42 Alan Schmitt
2024-02-06 15:14 Alan Schmitt
2024-01-30 14:16 Alan Schmitt
2024-01-23  9:45 Alan Schmitt
2024-01-16 10:01 Alan Schmitt
2024-01-09 13:40 Alan Schmitt
2024-01-02  8:59 Alan Schmitt
2023-12-26 10:12 Alan Schmitt
2023-12-19 10:10 Alan Schmitt
2023-12-12 10:20 Alan Schmitt
2023-12-05 10:13 Alan Schmitt
2023-11-28  9:09 Alan Schmitt
2023-11-21  7:47 Alan Schmitt
2023-11-14 13:42 Alan Schmitt
2023-11-07 10:31 Alan Schmitt
2023-10-31 10:43 Alan Schmitt
2023-10-24  9:17 Alan Schmitt
2023-10-17  7:46 Alan Schmitt
2023-10-10  7:48 Alan Schmitt
2023-10-03 13:00 Alan Schmitt
2023-09-19  8:54 Alan Schmitt
2023-09-12 13:21 Alan Schmitt
2023-09-05  9:00 Alan Schmitt
2023-08-29 13:04 Alan Schmitt
2023-08-22  9:20 Alan Schmitt
2023-08-15 16:33 Alan Schmitt
2023-08-08  8:53 Alan Schmitt
2023-08-01  7:13 Alan Schmitt
2023-07-25  8:45 Alan Schmitt
2023-07-11  8:45 Alan Schmitt
2023-07-04  9:18 Alan Schmitt
2023-06-27  8:38 Alan Schmitt
2023-06-20  9:52 Alan Schmitt
2023-06-13  7:09 Alan Schmitt
2023-06-06 14:22 Alan Schmitt
2023-05-30 15:43 Alan Schmitt
2023-05-23  9:41 Alan Schmitt
2023-05-16 13:05 Alan Schmitt
2023-05-09 11:49 Alan Schmitt
2023-05-02  8:01 Alan Schmitt
2023-04-25  9:25 Alan Schmitt
2023-04-18  8:50 Alan Schmitt
2023-04-11 12:41 Alan Schmitt
2023-04-04  8:45 Alan Schmitt
2023-03-28  7:21 Alan Schmitt
2023-03-21 10:07 Alan Schmitt
2023-03-14  9:52 Alan Schmitt
2023-03-07  9:02 Alan Schmitt
2023-02-28 14:38 Alan Schmitt
2023-02-21 10:19 Alan Schmitt
2023-02-14  8:12 Alan Schmitt
2023-02-07  8:16 Alan Schmitt
2023-01-31  6:44 Alan Schmitt
2023-01-24  8:57 Alan Schmitt
2023-01-17  8:37 Alan Schmitt
2022-11-29 14:53 Alan Schmitt
2022-09-27  7:17 Alan Schmitt
2022-09-20 14:01 Alan Schmitt
2022-09-13  8:40 Alan Schmitt
2022-08-23  8:06 Alan Schmitt
2022-08-16  8:51 Alan Schmitt
2022-08-09  8:02 Alan Schmitt
2022-08-02  9:51 Alan Schmitt
2022-07-26 17:54 Alan Schmitt
2022-07-19  8:58 Alan Schmitt
2022-07-12  7:59 Alan Schmitt
2022-07-05  7:42 Alan Schmitt
2022-06-28  7:37 Alan Schmitt
2022-06-21  8:06 Alan Schmitt
2022-06-14  9:29 Alan Schmitt
2022-06-07 10:15 Alan Schmitt
2022-05-31 12:29 Alan Schmitt
2022-05-24  8:04 Alan Schmitt
2022-05-17  7:12 Alan Schmitt
2022-05-10 12:30 Alan Schmitt
2022-05-03  9:11 Alan Schmitt
2022-04-26  6:44 Alan Schmitt
2022-04-19  5:34 Alan Schmitt
2022-04-12  8:10 Alan Schmitt
2022-04-05 11:50 Alan Schmitt
2022-03-29  7:42 Alan Schmitt
2022-03-22 13:01 Alan Schmitt
2022-03-15  9:59 Alan Schmitt
2022-03-01 13:54 Alan Schmitt
2022-02-22 12:43 Alan Schmitt
2022-02-08 13:16 Alan Schmitt
2022-02-01 13:00 Alan Schmitt
2022-01-25 12:44 Alan Schmitt
2022-01-11  8:20 Alan Schmitt
2022-01-04  7:56 Alan Schmitt
2021-12-28  8:59 Alan Schmitt
2021-12-21  9:11 Alan Schmitt
2021-12-14 11:02 Alan Schmitt
2021-11-30 10:51 Alan Schmitt
2021-11-16  8:41 Alan Schmitt
2021-11-09 10:08 Alan Schmitt
2021-11-02  8:50 Alan Schmitt
2021-10-19  8:23 Alan Schmitt
2021-09-28  6:37 Alan Schmitt
2021-09-21  9:09 Alan Schmitt
2021-09-07 13:23 Alan Schmitt
2021-08-24 13:44 Alan Schmitt
2021-08-17  6:24 Alan Schmitt
2021-08-10 16:47 Alan Schmitt
2021-07-27  8:54 Alan Schmitt
2021-07-20 12:58 Alan Schmitt
2021-07-06 12:33 Alan Schmitt
2021-06-29 12:24 Alan Schmitt
2021-06-22  9:04 Alan Schmitt
2021-06-01  9:23 Alan Schmitt
2021-05-25  7:30 Alan Schmitt
2021-05-11 14:47 Alan Schmitt
2021-05-04  8:57 Alan Schmitt
2021-04-27 14:26 Alan Schmitt
2021-04-20  9:07 Alan Schmitt
2021-04-06  9:42 Alan Schmitt
2021-03-30 14:55 Alan Schmitt
2021-03-23  9:05 Alan Schmitt
2021-03-16 10:31 Alan Schmitt
2021-03-09 10:58 Alan Schmitt
2021-02-23  9:51 Alan Schmitt
2021-02-16 13:53 Alan Schmitt
2021-02-02 13:56 Alan Schmitt
2021-01-26 13:25 Alan Schmitt
2021-01-19 14:28 Alan Schmitt
2021-01-12  9:47 Alan Schmitt
2021-01-05 11:22 Alan Schmitt
2020-12-29  9:59 Alan Schmitt
2020-12-22  8:48 Alan Schmitt
2020-12-15  9:51 Alan Schmitt
2020-12-01  8:54 Alan Schmitt
2020-11-03 15:15 Alan Schmitt
2020-10-27  8:43 Alan Schmitt
2020-10-20  8:15 Alan Schmitt
2020-10-06  7:22 Alan Schmitt
2020-09-29  7:02 Alan Schmitt
2020-09-22  7:27 Alan Schmitt
2020-09-08 13:11 Alan Schmitt
2020-09-01  7:55 Alan Schmitt
2020-08-18  7:25 Alan Schmitt
2020-07-28 16:57 Alan Schmitt
2020-07-21 14:42 Alan Schmitt
2020-07-14  9:54 Alan Schmitt
2020-07-07 10:04 Alan Schmitt
2020-06-30  7:00 Alan Schmitt
2020-06-16  8:36 Alan Schmitt
2020-06-09  8:28 Alan Schmitt
2020-05-19  9:52 Alan Schmitt
2020-05-12  7:45 Alan Schmitt
2020-05-05  7:45 Alan Schmitt
2020-04-28 12:44 Alan Schmitt
2020-04-21  8:58 Alan Schmitt
2020-04-14  7:28 Alan Schmitt
2020-04-07  7:51 Alan Schmitt
2020-03-31  9:54 Alan Schmitt
2020-03-24  9:31 Alan Schmitt
2020-03-17 11:04 Alan Schmitt
2020-03-10 14:28 Alan Schmitt
2020-03-03  8:00 Alan Schmitt
2020-02-25  8:51 Alan Schmitt
2020-02-18  8:18 Alan Schmitt
2020-02-04  8:47 Alan Schmitt
2020-01-28 10:53 Alan Schmitt
2020-01-21 14:08 Alan Schmitt
2020-01-14 14:16 Alan Schmitt
2020-01-07 13:43 Alan Schmitt
2019-12-31  9:18 Alan Schmitt
2019-12-17  8:52 Alan Schmitt
2019-12-10  8:21 Alan Schmitt
2019-12-03 15:42 Alan Schmitt
2019-11-26  8:33 Alan Schmitt
2019-11-12 13:21 Alan Schmitt
2019-11-05  6:55 Alan Schmitt
2019-10-15  7:28 Alan Schmitt
2019-09-03  7:35 Alan Schmitt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2ldamnxd3.fsf@mac-03220211.irisa.fr \
    --to=alan.schmitt@polytechnique.org \
    --cc=caml-list@inria.fr \
    --cc=lwn@lwn.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox