Why is it five times slower to use mutable fields in records?

Made a small benchmark to compare performance of record updates, with with vs mutable fields. For some reason, the loop with mutable fields run 5x slower. Is Ocaml optimizing something I missed?

type query = {
    select: string;
    from: string;
    where: string;
}

type query_mut = {
    mutable select: string;
    mutable from: string;
    mutable where: string;
}

let _ =
    for i = 0 to 1000000 do
        let q : query = {select = ""; from = ""; where = ""} in
        let q1 = {q with select = "1"} in
        let q2 = {q1 with from = "table"} in
        let q3 = {q2 with where = "a = b"} in
        ()
    done;
    (*
    for i = 0 to 1000000 do
        let q : query_mut = {select = ""; from = ""; where = ""} in
        q.select <- "1";
        q.from <- "table";
        q.where <- "a = b";
        ()
    done
    *)

Compile with ocamlopt -O3 (or not, doesn’t affect run time).

1 Like

Debugging with -dcmm, it looks like the content of the loop is removed. Can I tell OCaml to not optimize it?

2 Likes

Compiling with ocamlc (to produce bytecode) the imperative version is a bit faster (6.2sec vs 4.95sec for 100000000 iterations).

1 Like

Thanks! Didn’t realize ocamlc behaved differently in this regard. :slight_smile:

The nice people on IRC also mentioned Sys.opaque_identity.