Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

OCaml Module 13

Runtime, performance and interoperability interview questions

Interview questions on runtime, performance and interoperability: warm-ups, then what each harder question tests and how a good answer starts.

14 questions: 3 warm-ups and 11 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher to mid

    Which OCaml values cost no allocation, and which live in a block?

    Answered in the lesson Memory representation and the garbage collector

  2. Fresher to mid

    What does dune's (modes byte exe js wasm) stanza do, and when would you shorten it?

    Answered in the lesson OCaml in the browser: js_of_ocaml and Wasm

  3. Fresher to mid

    What does #trace print, and when is it the quickest way to find a bug?

    Answered in the lesson Debugging, profiling and benchmarking

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Mid to staff

    A booking service on OCaml 5.5 builds a response tree of about 16,000 words for each request and drops it after the reply. With one request in flight the collector is quiet; with 32 in flight the major heap grows fivefold and the slowest responses stall. Explain what the collector is doing, and what you would change.

    What it tests
    Knowing that a minor collection copies whatever is still reachable, seeing that requests in flight keep young data alive, and choosing between a larger minor heap and less allocation, with numbers.
    First step
    Measure promoted words per request at both loads, with Gc.quick_stat read before and after a fixed number of requests. If they jump from a small share of the tree to almost all of it, the trees are still in flight when the minor heap fills, so each one is copied into the major heap and has to be collected there later.
    Follow-ups

    From the lesson Memory representation and the garbage collector

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes
  2. Mid to senior

    A pricing service keeps 2 million quotes in a Hashtbl keyed by 11-character SKU strings, with type quote = { price : float; qty : int; updated : float }. The team budgeted 64 bytes an entry, and the process holds far more. Work out the words one entry really takes, and cut them without changing any lookup.

    What it tests
    Counting words from the representation of strings, records that mix floats and ints, boxed floats and hash table buckets, then choosing a layout that removes the boxes.
    First step
    Count one entry on paper, then check the count with Obj.reachable_words over the whole table divided by its length. The 11-byte key is a 3-word string, and the record mixes floats with an int, so it is a 4-word block whose two floats sit in boxes of their own; the table adds a bucket cell for every binding.
    Follow-ups

    From the lesson Memory representation and the garbage collector

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  3. Mid to senior

    A hand-written C stub returns a record built with caml_alloc. Under load it sometimes returns garbage or crashes, but never in small tests. What rule is most likely broken, and how would you find and fix it?

    What it tests
    Knowing that an allocation can move young values, that every value held across one must be a registered root, and that the bug surfaces only when a collection falls between two allocations.
    First step
    Reproduce it on purpose: call the stub in a tight loop that allocates hard between calls so a minor collection lands inside the stub. Then read the stub for any OCaml value kept across an allocation without CAMLparam or CAMLlocal.
    Follow-ups

    From the lesson Interfacing with C

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  4. Mid to senior

    A colleague marks a numeric stub [@@noalloc] to speed it up, but the stub calls caml_copy_double to return a float. The program passes every test, then crashes in production. Explain the connection.

    What it tests
    Seeing that [@@noalloc] is a promise the compiler optimises on, that caml_copy_double allocates, and that the broken promise lets a collection run without the bookkeeping the compiler skipped.
    First step
    State what [@@noalloc] means: the C function does not allocate, raise or release the domain lock, so the native compiler skips the bookkeeping it puts around a C call. Then note that caml_copy_double allocates, so a collection can run mid-call without that bookkeeping.
    Follow-ups

    From the lesson Interfacing with C

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Mid to staff

    Your team must bind a C library of about forty functions, mostly taking ints, doubles and pointers, to OCaml. Would you write hand stubs or use ctypes, and what decides it?

    What it tests
    Weighing per-function C effort against a dependency on ctypes and libffi, the kinds of values crossing the boundary, and call overhead, rather than a blanket preference for either.
    First step
    List what crosses the boundary: for ints, doubles and pointers ctypes removes forty stubs and is a natural fit; for OCaml strings, arrays or records a hand stub and the CAML macros are safer. Then check whether the build may depend on ctypes and libffi.
    Follow-ups

    From the lesson Interfacing with C

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  6. Mid to senior

    A browser project binds eight DOM APIs through Js.Unsafe.get and Js.Unsafe.meth_call. Three of the eight are already in Dom_html with the correct type. A teammate says: rewrite all eight to use Js.Unsafe for consistency. What is the better rule, and why?

    What it tests
    Knowing the two layers of js_of_ocaml bindings and choosing them per API, keeping the type checker useful where it already covers an API, and knowing when the ppx is needed and when it is not.
    First step
    Rewrite only the five APIs that Dom_html does not cover to use Js.Unsafe. Keep Dom_html.createButton, Dom_html.window and the typed functions as they are, so the compiler keeps checking method names, argument types and return types for them. Add a comment next to each Js.Unsafe call that names the browser API it reaches, so the next reader knows why it is at the lower layer.
    Follow-ups

    From the lesson OCaml in the browser: js_of_ocaml and Wasm

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  7. Mid to senior

    A team pushes a 2.2 MB JavaScript bundle to a user-facing site because that is what dune build emits. The lead says: "the gzipped size is 500 KB, so a browser only downloads 500 KB." Explain what is wrong with that reasoning, and give the one-line fix.

    What it tests
    Knowing the dev-release gap, how dune profiles work, and why raw and parsed bytes also matter to a browser, not only the number on the wire.
    First step
    Rebuild with dune build --profile release (dune build -p PACKAGE for opam). The same source compiles to 72,471 bytes raw and 22,065 gzipped: thirty times smaller than the dev build the team shipped. Even compressed, the dev file is about 23 times larger (503,257 bytes). Parsing time scales with the raw size, not the gzip size, so the browser also uses less CPU after download.
    Follow-ups

    From the lesson OCaml in the browser: js_of_ocaml and Wasm

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  8. Mid to senior

    A single-file dom_counter.ml holds every piece of a running browser program: the counter state, the arithmetic, the formatting and every DOM call. Six months later a native CLI is wanted that reports the same counter from a saved file. How do you refactor without breaking the browser version, and what do you test first?

    What it tests
    Splitting pure logic from the browser front end, naming the library and executable layout dune supports, writing native tests that cover the library, and leaving a thin front end for browser-only concerns.
    First step
    Move the arithmetic and formatting into a counter.ml library with no js_of_ocaml dependency. The browser program becomes main_browser.ml with (modes js) and (libraries counter js_of_ocaml), and the new CLI becomes main_cli.ml with (libraries counter). Write Alcotest cases against Counter.increment and Counter.format in a test/ folder first; both executables then share the same tested bytes.
    Follow-ups

    From the lesson OCaml in the browser: js_of_ocaml and Wasm

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 5 minutes
  9. Mid to senior

    A nightly OCaml job that summarises 2 million log lines took 4 minutes last month and takes 40 minutes since a refactor, with the same output. Nobody knows which function got slower. How do you find it, and how do you show that your fix worked?

    What it tests
    Treating a correct but slow program as a profiling question, choosing between exact counts and samples, and proving the fix with a fair comparison rather than one timing.
    First step
    Reproduce the slowdown on an input small enough to run in seconds, then profile the old and the new build in the same way, with exact call counts or a sampling profiler, and compare which function's share grew before changing any code.
    Follow-ups

    From the lesson Debugging, profiling and benchmarking

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  10. Mid to staff

    After a parser rewrite, a service's minor collections rise from 50 to 400 a second at the same traffic, and its p99 latency doubles. How do you find which code allocates the extra words, without guessing?

    What it tests
    Measuring allocation per request before attributing it, using an allocation profiler to name the call sites, and cutting the allocation where it is made.
    First step
    Count the minor words per request in both versions with Gc.minor_words around a fixed batch of requests, so the size of the change is a number. Then sample the new version's allocations with Gc.Memprof and add the samples up by call site.
    Follow-ups

    From the lesson Debugging, profiling and benchmarking

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Mid to senior

    A teammate's change claims to make the price formatter 15% faster, from one run of each version timed with Unix.gettimeofday on a laptop. What do you ask for before you accept the claim?

    What it tests
    Knowing what makes a timing comparison fair, and which measurements stay the same from one run to the next.
    First step
    Ask how the two numbers were produced: the machine, the compiler and its flags, the input, and how many runs of each version stand behind each number.
    Follow-ups

    From the lesson Debugging, profiling and benchmarking

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All OCaml interview questions · The OCaml track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.