Reputation: 155
Running
type expression =
| Num of int
| Var of string
| Let of string * expression * expression
| Binop of string * expression * expression;;
in one utop session takes approximately 8 seconds.
Now, if we hop over to a separate utop session and run
type expression =
| Num of int
| Var of string
| Let of string * expression * expression * expression * expression
| Binop of string * expression * expression;;
This takes around 13 seconds.
Finally, let's do both in the same session
type expression =
| Num of int
| Var of string
| Let of string * expression * expression
| Binop of string * expression * expression;;
type expression_1 =
| Num of int
| Var of string
| Let of string * expression_1 * expression_1 * expression_1 * expression_1
| Binop of string * expression_1 * expression_1;;
The first type takes 8 seconds as in the separate session, but the former 13 second operation is now 3 seconds! What's going on here?
I know very little about all of the work OCaml does under the hood with types; perhaps it's able to construct the 4-expression tree from the 2-expression tree via some smart caching?
Or is it something more elaborate?
For example, since my custom type has recursive components in both cases, is it checking whether or not expression_1
and expression
have some kind of "structural" similarity? As the compiler goes along annotating and unifying types in the program it might have a couple options (no pun intended) when it encounters a new type: does it use explicitly pre-defined types that are annotated as clues to infer the type at hand, or does it go through the types it knows about and then the custom types that I defined?
Is the compiler initially evaluating some type and then coming up with a representation to check whether it's a certain type? In this example, is it constructing the recursive structure of all the expression * expression
... into a tree?
I really don't know, but I want to find out!
Upvotes: 0
Views: 162
Reputation: 35210
In your experiment you're not measuring OCaml, but utop, an interactive interpreter of OCaml. While the numbers that you are showing are indeed outrageous and unusual, they have nothing to do with OCaml performance. They indicate that something is terribly wrong with your system.
Speaking of OCaml, it features an extremely performant compiler which is capable of typing thousands of expressions per millisecond, so you would hardly be able to notice it. In fact, OCaml is often used as a target language for various higher-level languages and theorem provers, like Coq, Ott, and F*, so it is used to compile a machine generated code, which usually comes in plenty.
Back to your example, I would suspect that you're either running utop in a folder with lots of files, or your .ocamlinit file is running some slow computation, or you're not describing us your experiment in full. Or you hit some bug in utop.
I can also suggest playing with down
a new top-level library for OCaml. E.g., (the first symbol is a prompt)
$ ocaml
# #use "topfind";;
# #require "down";;
Or just run ocaml
using rlwrap
, e.g.,
$ rlwrap ocaml
Or, even, try OCaml in your browser1.
Besides, as you want to learn what OCaml is doing with your type definitions — nothing sophisticated just parses it and performs some sanity checks. Nothing that could take more than a fraction of a second, even 30 years ago.
1))In this case, the OCaml compiler itself is compiled to Javascript and is run by your browser, and it still will accept your definitions in a matter of milliseconds.
Upvotes: 3