Skip to content

Fast paths for small arities in caml_js_fun_call (and others) #275

@alainfrisch

Description

@alainfrisch

In the same way as caml_js_new, one could add fast paths in caml_js_fun_call and other similar functions to avoid copying the array of arguments:

function caml_js_fun_call(f, args) {
  switch (args.length) {
  case 1: return f.call(null);
  case 2: return f.call(null, args[1]);
  case 3: return f.call(null, args[1], args[2]);
  case 4: return f.call(null, args[1], args[2], args[3]);
  // ad libitum
  }
  return f.apply(null, caml_js_from_array(args));
}

The compiler could also detect cases where caml_js_fun_call is called on an array of known size to inline the corresponding branch directly. Or, alternatively, one could expose specialized primitives caml_js_fun_call1, caml_js_fun_call2.

The micro-benchmark below runs about 15x faster with the version of caml_js_fun_call above.

let () =
  let r = ref [| Js.Unsafe.inject 1 |] in
  for i = 1 to 10000000 do
    if i < 1 then r := [| Js.Unsafe.inject 0 |]; (* prevent wrong optim *)
   Js.Unsafe.fun_call (Js.Unsafe.variable "add") !r;
  done
    <script type="text/javascript">
      var accu = 0;
      function add(x) {  accu += x; }
      var t0 = new Date().getTime();
    </script>
    <script type="text/javascript" src="bench_js.js">
    </script>
    <script type="text/javascript">
      var t1 = new Date().getTime();
      alert("Sum = " + accu + "\nTime : " + (t1 - t0));
    </script>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions