Actually, we've funded lots of things that we don't directly use. For example, we funded the development of OPAM, which we don't use internally at all. Moreover, the funding of OCaml Labs was aimed broadly at improving the OCaml ecosystem, rather than just addressing our narrow internal needs. Our work and funding on compiler improvements like Flambda is aimed at things we want, but they're also of broad utility to the users of the language. Merlin is another example of something we've supported that is useful to us internally, but also useful more broadly.
This is of course self serving in the sense that we think the OCaml ecosystem is important to our future, and so we want to help it flourish. But it's a relatively enlightened form of self interest...
That's fair, I wasn't aware that OPAM was funded by JS. It is definitely one of the better package managers that I've worked with too.
I'd like to ask you a question, as it isn't every day that yminsky responds to me. If you knew from the beginning that you would end up creating an entire ecosystem (including libraries, package managers, etc) mostly from scratch, would you have chosen SML instead? I know when you joined JS that OCaml was probably the pragmatic choice. But so many ML enthusiasts (myself included) prefer the syntax and semantics of SML and end up using OCaml/F#/Scala because the SML ecosystem is so non-existent.
I've heard similar things from folks at Twitter, IIRC. But I do find the whole thing kind of mysterious, I have to admit. I'd love to learn that I was wrong.
I don't think that person knows what he is talking about. Either you pick high-throughput or low-latency. You don't get both. They got the young generation collection pause down to 60 ms which is completely crap. :) The gc for Factor which I've been hacking on has a young generation pause of 2-3 ms (depending on object topology, generation sizes and so on). But the young generation is only 2mb so the number of gc pauses is significantly higher.
Although it's probably not at all what that author meant, there is a way in which throughput and latency have a kind of fractally-layered relationship. For example, if you have a distributed computation that requires all parts to be finished before any result is returned, your throughput is dependent on the average latency for each part being consistently low. If one of them gets stuck it becomes a huge bottleneck, and speeding up the rest won't matter. And at the lowest levels of optimization a similar concern arises when CPU throughput is ultimately concerned with avoiding unnecessary latency such as cache misses.
For modern systems, latency seems to be increasingly important, as the fast paths have all grown various asynchronous aspects. For some systems 60ms pause might be fine, for others 2ms might be way too much. It's definitely a "what scale are you thinking about" kind of thing.
What the author (and I) meant by "low-latency" is a gc were the work is very fairly distributed among the mutators allocation requests. The gc with highest throughput just allocates memory and never frees it. But then you sacrifice other properties such as extremely high memory usage..
I think what he meant is an application that is serving a lot of requests at low latency which would be the ideal scenario for a api/cache server so not much of crap. And I'm not sure why you are comparing a 6G new gen to a 2MB new gen. Do you mean to say that a 70ms GC for a 6G heap is too low? It is fairly possible to hit those or even lower range for a heap of that size depending on the data. I have even heard of people hitting even lower GC pause though I myself haven't been able to do that personally.
In fact low latency and high-throughput are usually best friends. You cannot maintain high throughput if your operations are taking longer. Also have a look to this picture. Using G1, doing few hundred MB/s.
Throughput is generally measured in the fraction of CPU cycles spent on GCing. The Parallel Old Gen collector is more efficient in that regard (i.e. provides more compute-throughput) than CMS, Zing or G1, but it is not concurrent and thus you have longer STW pauses compare to the latter collectors.
The concurrent collectors trade some throughput for latency by occupying additional threads for concurrent work. Due to the additional synchronization actions (more atomic instructions, read/write barriers, additional cleanups during shorter STW pauses) they are less efficient in overall CPU cycles spent.
So it certainly is a tradeoff.
Of course a collector that can burn more memory bandwidth and CPU cycles will generally lead to lower pause times, so in that sense increasing throughput of the collector is good for latency. But increasing the collector's throughput leaves less resources for your actual application, decreasing effective throughput.
I don't think that you are wrong, most of the JVM users are not forced to look into how GC works unless they are exposed to extreme high scale and load like LinkedIN, Twitter, etc. It is not uncommon to roll with 6GB+ heap. GC gets in your way if this high scale meets with low latency requirements for p99 (and above) latency, again which these guys care about a lot.
I think the best approach to GC based memory management is what Erlang does, extremely limited scope, no global locking and tiny GC time. I am not entirely familiar how the OCaml VM works, just started to play with the environment. Also, my understanding is that OCaml is not for highly concurrent systems. Anyways it is kind of offtopic here.
The summarize:
- JVM GC details are extremely important for high throughput low latency systems at scale, as far as I know the G1 GC is used for predictable low latency compactions, and I can verify that with my experiments, having 10ms GC pauses
- I think the Erlang approach is superior to garbage collected systems, but it requires no shared memory across your threads (or in the Erlang case processes), so the GC scope is tiny (and few other niceties in BEAM)
Unix support is definitely better than Windows. That said, the core language and base libraries are pretty portable. Here's one nice retrospective on a move from Python to OCaml for a program that needed portability to Windows as a fundamental concern.
> Probably the biggest problem on Windows is that OPAM, the package manager, doesn't work there. That will come eventually, though
Wodi [1] is a reasonable choice until OPAM starts supporting Windows. It includes many of the interesting/useful libraries (including, importantly, batteries [2] and core [3])
My experience has been building parallel and distributed programs using multiple runtime instances that communicate via message passing. There are libraries that help automate this, link our own Async_parallel (https://blogs.janestreet.com/async-parallel/). One advantage of this approach is that it scales beyond a single box.
There is work going on at OCaml Labs on a parallel runtime. I suspect it will be useful, but in the end, message passing is I think a better idiom than shared memory threads for parallel programming. When the true parallel runtime lands, I'm not sure that we'll actually use it much for running truly parallel threads.
> I suspect it will be useful, but in the end, message passing is I think a better idiom than shared memory threads for parallel programming.
It really depends on the problem you are working with. You wouldn't want to make a high-performance HTTP server this way. Especially if you get to copy 2MB of POST data every time.
For an HTTP server you should use Async or LWT, which are lightweight concurrency libraries. You can handle quite high levels of concurrency with either one. My impression is that people building highly parallel HTTP servers do quite well with collections of processes with a load-balancer in front, but it's not my area of expertise.
Async and LWT give you lightweight concurrency mechanisms. Libraries like Async.RPC give you lightweight remote invocation, and Async_parallel gives you simple mechanisms for spinning up multiple physical processes and communicating between them.
Don't get me wrong: OTP by all accounts has richer support for this kind of stuff. I think OCaml is a better language for many purposes, but OTP is a great runtime and set of libraries whose equal is not yet found in any other language as far as I can tell.
The biggest change is OPAM, http://opam.ocaml.org/, a top-notch package management system that makes installing OCaml packages much easier.
Shameless plug: there's also a newish O'Reilly book, Real World OCaml http://realworldocaml.org, which I think is a big help in learning the language.
Oh, and there's OCaml Labs, a new lab at Cambridge University that's dedicated to improving the language.
And of course the compiler is constantly making progress. The upcoming 4.02 release is a pretty fun one, which I documented here: https://blogs.janestreet.com/ocaml-4-02-everything-else/ And before that, changes like GADTs and first-class modules landed, which have been quite useful extensions.
Really, it's a very active and fun community these days. The language is getting better quite quickly, but mostly in conservative and tasteful ways. The people in charge of the core language have been doing a great job, and the community infrastructure (things like OPAM) have been making big strides as well.
It looks like the ecosystem is fairly small. Another thing that is off-putting (unless I'm missing something) is that OPAM packages have no online docs per default, something that is standard with Haskell packages, for instance, and is definitely a big help.
The stdlib that ships with the compiler is indeed minimal, though it is used for things other than the compiler. It can be used for other projects, but you probably want something more full-featured. Core, and the more minimal and portable Core_kernel (https://github.com/janestreet/core_kernel) is a full-featured alternative that is growing in popularity, and is what the book I worked on (Real World OCaml, http://realworldocaml.org) is based on.
OCaml (and most of both the stdlib and Core) default to immutable data structures, but OCaml has good support for programming imperatively, to its credit, in my view.
FWIW: Core doesn't work with Windows (the Real World OCaml book does state this upfront) so you need either an OSX or Linux machine to work with Core, and so you can't work through the book with a Windows machine. Something to be aware of.
For what it's worth, the world has changed since then: Core_kernel (which is the highly portable bits of Core, which is most of it) works on Windows just fine. Indeed, WODI, which is the best windows package manager for OCaml right now, ships with it.
Hi, Yaron! I was recently looking into using Core for one of my projects, but have so far failed to find any good, clear, complete documentation or how-to guide. Is there anything like that available online? I guess I could read the Real World OCaml book to learn parts of it, but I already know OCaml...
I've heard that Jane Street uses their own extensions to the language. Also, how does one deal with the development of OCaml being largely done in French?
Jane Street makes use of OCaml's built-in metaprogramming facility, camlp4. While these are in some sense "our own extensions", they're wholly shareable without using a hacked version of the compiler, and just because we build our code using these syntax extensions, doesn't mean that users of our libraries need to do the same. You can use Core_kernel, for example, without using our syntax extensions.
The French thing is a non-issue. The compiler is written and documented in English, and all the main contributors are fluent English speakers, and the mailing lists are almost entirely in English.
> Also, how does one deal with the development of OCaml being largely done in French?
OCaml is developed by french people, I've never heard of it being done in french (aside from interpersonal banter I guess). The french version of the official site doesn't even work correctly (when you click on the "manual" link you get the english manual)
ML (OCaml and SML) seems to get short shrift in your analysis. CS51 at Harvard is in OCaml. Brown's cs017 is OCaml, Scheme, Scala and Java. Penn's CS120 is OCaml (I think. It definitely used to be, but I can't find the course online anymore. You can reach out to Benjamin Pierce to ask, though.) And CMU has an SML-based FP course as part of their intro sequence
None of this is to deny the fact that Python is highly popular as an intro language.
Thanks, will look into those and update accordingly. However, Harvard CS51 doesn't count as CS1 since CS50 is already its CS1 course. (But please correct me if I'm wrong.)
(arg can't reply to your reply) this is actually quite important ... let me keep looking into this. sorry there's a giant backlog of (often angry!) emails in my inbox right now ... might not be able to sort thru them all :)
i wish the blogging platform supported some version-control friendly format.
[Edit: I made a typo about Penn CS120 ... I mistakenly found another course named CS120 that wasn't at Penn. Also, Harvard CS51 calls itself "Computer Science II" [1], implying that it's a CS2 course. It probably has CS50 as a prereq, tho I haven't double-checked yet.]
It depends on what CS1 really means. I do think cs51 is comparable to CIS120 at Penn, and I think the later is pretty clearly CS1. That said, I find it hard to really figure out what the precise criteria are. It's pretty clear that Harvard encourages concentrators to take cs50, but I think the same course at other institutions would often be skipped by concentrators.
@yminsky -- yep, taxonomies r hard :) but i'm trying to go as much as possible by what each department proclaims for itself rather than trying to calibrate across departments. If Harvard calls a class "Computer Science II", I'm going to consider it as CS2. (fwiw I consider Harvard CS50 a hybrid of CS0 and CS1 since students voluntarily split themselves into two tracks called "less comfortable" and "more comfortable", respectively.)
I would have thought cs50 is a cs0 course, and cs51 is the cs1. cs50 is the concentrators-and-non-concentrators course that's all flash and fun. What do you think is the cs0 at Harvard?
As for your point about Penn's CS120, I guess I don't fully understand the criterion. From the way you described it, CS120 seems like a CS1 course: not for someone who has had zero programming, but the very first course taken by most CS concentrators.
FWIW, I spoke to Benjamin Pierce about the structure of the course, and he said he didn't want to use "Real World OCaml" because it's too early of a course: he has students who he thinks don't yet understand things like what a scope is. From the sense I got from him, it's quite early in the curriculum.
That said, this is mostly minor quibbling. I think there's little doubt that "very early" courses, for some reasonable definition of "very early", lean towards Python. And reasonably so.
I'm not sure how you define CS0, but my understanding is that there are now three introductory CS courses at Harvard: CS1, CS50, and CS51. Note that I graduated in 2007, so my understanding may be dated.
CS1 is intended for non-concentrators or people with very little prior CS experience.
CS50 is the standard intro course that most CS concentrators (or people considering CS as a concentration) take. Although it's taken by non-concentrators, most of the non-concentrators taking the course do so because they're in some field that has a lot of exposure to programming (e.g. Applied Math).
CS51 is the "advanced" intro course and is usually not the first CS course a CS concentrator takes, if for no other reason that it's not offered until the spring semester.
I went to Penn and TAed for some lower level CS courses (but not 120).
CIS120 is the course for students who have some programming experience, and probably falls under CS1. I had taken AP Java AB before and was overprepared for the old (Java) version of the course. The current course teaches basic data structures and uses Ocaml.
Penn's CIS120 is half OCaml and half a continuation of Java from 110 (the first course). Python is not found in the intro courses at Penn. Just Java and OCaml.
I think we're pretty clearly the most intense user (most code, most developers using it), but not technically the biggest company using it. Bloomberg and Facebook are examples of bigger companies using it in serious ways.
I don't think this is correct. All pure data structures are threadsafe. It's true that mutable datastructures like the built-in hashtable are not threadsafe. But isn't that the standard tradeoff with threads? Most things aren't threadsafe, but with mutexes and condition variables and the like, you can make them so. Surely one doesn't want to make the performance destroying mistake of making _everything_ threadsafe.
To be clear, it is true that the runtime has a single lock for the GC, so for now, it's not possible to gain physical parallelism from multiple threads. That's being worked on, but I have to say that I rather prefer message passing and I don't know that how we build programs will change much when shared memory threads are available.
http://opam.ocaml.org
I've found it to be surprisingly reliable and easy to use.