Recently I finally got myself to try writing some OCaml. Of course, I never make it easy for myself, so I tried out js_of_ocaml at the same time.

I wanted to improve my password generation tool to generate passwords on the client side, as server-side password generation with security improvement pretense is just clown-worthy.

TL;DR

It all worked out – js_of_ocaml is pretty cool, but I wouldn’t say I’d rush to use it in a production system right away. Of course I have little to no OCaml and js_of_ocaml experience, so perhaps with some more time invested it gets a lot better.

The end result can be seen here: password generation app (CLICK). The source code is on GitHub.

OCaml, js_of_ocaml

OCaml is a general purpose programming language with strong bias towards statically-typed functional programming. It descends from the ML family of languages and has been around for a rather long time now. Some of the cool features of this language are:

  • first-class parametrizable modules, which are often compared to Haskell’s typeclasses, but are in fact more powerful in a way that they can be parametrized not only by type, but by value. (see OCaml Functors)
  • sophisticated object system with support for structural typing
  • powerful type system with support for GADTs and dependent types to some extent.

js_of_ocaml is an OCaml bytecode compiler that outputs JavaScript. It’s been developed since at least 2010 and the project seems to be getting a fair amount of activity.

Since js_of_ocaml compiles OCaml bytecode, it therefore does not limit the language to some subset – it is a full-on OCaml compiler to JavaScript.

Performance

It’s hard to assess performance in my use case since I don’t do any heavy computation and don’t rely on low latency, but let’s look at Chrome dev tools profiler’s data.

Disclaimer: I’m not trying to pretend this is a legit analysis of JavaScript code generated by js_of_ocaml. I’m pretty sure it is the way it is only because I made it so.

The program itself is rather simple. The password generation is done in a series of steps:

  • parse the password template, creating a password template definition structure
  • for each item in the passowrd template, run a corresponding random token generation function
  • concatenate the results into a single string

Memory

According to memory profiler, each password generation run allocates about 20Mb of heap memory. From the chart it looks like most of the allocated objects, by volume, are strings. This looks like a pretty bad result.

Memory allocation chart for a single password generation run.

My guess about this is the inefficient string manipulation code:

let rec explode : string -> char list = function
  | "" -> []
  | s ->
    (String.get s 0) ::
    explode (String.sub s 1 ((String.length s) - 1))

let rec implode : char list -> string = function
  | [] -> ""
  | x :: xs -> (Char.escaped x) ^ (implode xs)

let filter p s =
  (* ugh *)
  explode s |> List.filter p |> implode

OCaml’s standard library doesn’t really have a lot of string processing functions. In fact, the string processing support in standard OCaml is rather lacking, if not abysmal, considering it’s 2015 and there’s no Unicode support.

I just went the simplest route and think that efficiency of this implementation is horrible. I even used that filter function in one place.

CPU

Each generation takes about 50-100ms to complete, including ~1-3 garbage collections, on a 2.3GHz i7. Honestly, this is a pretty bad result as well. I would blame it all on the inefficient string processing again.

Flame graph of a single password generation run.

It doesn’t seem to help that almost half of the time is spent doing garbage collection.

Generated code size

In my case, js_of_ocaml produced around 60kb of minified JavaScript, which I’d say is not bad at all, especially compared to other compilers that have a JavaScript backend. They will often drag the whole runtime into the output, compiling a helloworld-like program to over 1Mb of JavaScript code (looking at you, GHCJS).

Ergonomics

At this minimal level of sophistication my experience with OCaml + js_of_ocaml has been good enough – it works.

There are some pain points though.

Standard OCaml library

String processing support is modest: not a lot of string utility functions, no support for Unicode in the standard library. There also doesn’t seem to be a lot of math functions in the standard library. I suppose there’s everything you need is in the popular libraries like Batteries.

JavaScript interop

Interoperation with JavaScript could be more intuitive/documented. I think it also could be made somewhat easier to do.

Calling OCaml functions from JavaScript:

var generate = function (dict, tpl) {
  // call into js_of_ocaml code
  return window.pwdGen.generate(tpl)(dict);
}

Exposing OCaml code to JavaScript:

let m = Js.Unsafe.obj [| |] in
Js.Unsafe.global##pwdGen <- m;

let js_generate tpl_string dict =
(* ... *)
in

m##generate <- Js.wrap_callback js_generate;

Returning JavaScript objects from OCaml:

(* ... *)
| Error e ->
  let r = Js.Unsafe.obj [| |] in
  r##error <- Js.string ("Could not parse template: " ^ e);
  r
(* ... *)

Opam

Often, the language’s build system or the package manager can give a lot of grief to beginners. I liked my first opam experience though. I found the compiler switching feature very cool, although I only had to use it once so I could get js_of_ocaml to work.

comments powered by Disqus