Live data from Hacker News

A deep dive into Multicore OCaml garbage collector

kcsrk.info

81–90 of 97 posts

Re: A deep dive into Multicore OCaml garbage collector

#81
post #47

Earlier quoted context omitted.

In OCaml there is Lwt. It provides very light-weight cooperative threads. The context switches are very fast and composing cooperative threads allows the writing of highly asynchronous applications. For instance, in the versions of Go prior to 1.5 goroutines used to run on a single core. And as of 1.5 the variable GOMAXPROCS can be set to the number of cores. EDIT:clarify the difference between concurrency and parall…

Lwt looks nice, but also seems a lot more intrusive to me than, say, Go. It's based on promises (so it's very explicit), and if I remember correctly, in order to do any I/O you have to use the Lwt mechanisms instead of the standard ones (which block). How does Lwt interact with third-party libs that aren't written to use Lwt? I know from Ruby that libevent-type stuff such as Eventmachine doesn't combine all that well…

Go story becomes rather bad the moment one wants to support IO cancellation without memory leaks in form of hanging forever go routines. As one cannot cancel them, a proper shutdown requires a lot of rather non-trivial code with thinks like sending channels over channels etc. Recently introduced Context was supposed to address it, but since one cannot use that to cancel a blocking system call, this is only helpful with high-level libraries that tries hard to work around that.

Lwt does have proper cancellation support. There are some pain points, but it is straightforward to work around them. The real problem with Ocaml is that there are 2 incompatible libraries for promise-based IO, Lwt and Async. That made it really hard for third-party libraries as now they need to support not one, but two frameworks...

Re: A deep dive into Multicore OCaml garbage collector

#82
post #57

Earlier quoted context omitted.

The short answer is: single-core cpu performance is not going up much in the recent years. The core count is still increasing every year. That is why graphics cards still see a strong rise in total performance, their usual work load is inherently parallel. For typical server tasks, like web serving, we can just run several processes. Unix is doing this for decades. But even web serving is often cpu bound, if your SQL…

> but the recent years brought quite some progress. Go makes it easy ... It actually feels like the recent years have been pretty disappointing. Go is one of the few places where the language developers are making a real effort around multicore. Erlang came with a bunch of opinions about how to do this in the 90s. But every other mainstream language is taking a head-in-the-sand attitude about this. Python squandered…

Given that Go is memory-unsafe on multicore, I do not think that language developers are made that strong efforts. The answer in Go is to use runtime checkers, but even those do not catch all memory safety issues.

Re: A deep dive into Multicore OCaml garbage collector

#83
post #34
post #15

Earlier quoted context omitted.

> you can cheat a little and write imperative code if you really need to I'm not sure if this is cheating. Yes, this can be misused to introduce side-effects where there should be none. However, the strict evaluation by default (and lazy evaluation only when explicitly marked) has a huge benefit that you can not only reason easily about correctness (as in Haskell), but also reason easily about performance. The latter…

Personally I think it is a mistake to use Rust instead of OCaml if the use case doesn't require the tight memory management that Rust supports. If the target domain can be done in a language with GC, enjoy productivity with sails taking full wind, instead of having to deal with lifetime annotations. Now if the GC induced delays are too much for the target domain, then for all means use Rust. After all, the tool for r…

In addition to the lack of GC Rust also requires type annotation for top-level functions. As types are often rather non-trivial due to borrowing etc, it really takes more efforts to write middle-level glue code in Rust.

Re: A deep dive into Multicore OCaml garbage collector

#84
post #18
post #15

Earlier quoted context omitted.

> you can cheat a little and write imperative code if you really need to I'm not sure if this is cheating. Yes, this can be misused to introduce side-effects where there should be none. However, the strict evaluation by default (and lazy evaluation only when explicitly marked) has a huge benefit that you can not only reason easily about correctness (as in Haskell), but also reason easily about performance. The latter…

You are offering a one-sided argument with regard to strict versus lazy! Lazy evaluation can make space usage difficult to reason about, but time complexity should be unchanged. Lazy evaluation, by default, is also a huge benefit to Haskell. Strict evaluation is often a huge impediment to function reuse.

Time _complexity_ is unchanged, but laziness makes it difficult to reason about when the time will be taken. This, more so than the space usage, is the reason laziness is avoided when run time is important.

> Strict evaluation is often a huge impediment to function reuse.

This reads like an argument for having laziness as a language construct, rather than for having it as a default.

Re: A deep dive into Multicore OCaml garbage collector

#85
post #46

Earlier quoted context omitted.

I don't know if you've worked with a production Haskell code base but it cannot be over stated what a poor decision operator overloading is. if they got rid of that it would immediately make Haskell an order of magnitude more practical

Haskell doesn't really have the problems that are commonly associated with operator overloading. Haskell does have type classes, which do allow overloading, even of operators, but the type class uniquely determines the type of the operator - and there can be only one definition of any operator in scope. Also, you can just define as many new operators as you like. For these reasons, you can't have the madness of opera…

>Also, you can just define as many new operators as you like.

this is exactly the problem

Re: A deep dive into Multicore OCaml garbage collector

#86

Earlier quoted context omitted.

Haskell doesn't really have the problems that are commonly associated with operator overloading. Haskell does have type classes, which do allow overloading, even of operators, but the type class uniquely determines the type of the operator - and there can be only one definition of any operator in scope. Also, you can just define as many new operators as you like. For these reasons, you can't have the madness of opera…

> Haskell doesn't really have the problems that are commonly associated with operator overloading. Nobody said it did. People said that it has its own brand of problems with operators looking something like >>+@* > peppering your code.

lol i wonder if you work on my team

Re: A deep dive into Multicore OCaml garbage collector

#87

Earlier quoted context omitted.

> Idiomatic rust avoids heap allocations, but it very much encourages immutable stack allocation...something that OCaml also tries to encourage. I'm not sure I'm following you here; one of the more common criticisms of OCaml is generally that it (unavoidably) puts too many values on the heap. I mean, even floats get boxed by default, unless the compiler can avoid that.

> even floats get boxed by default, unless the compiler can avoid that. Yikes, that seems like it would destroy performance.

It's one of OCaml's biggest weaknesses, but it's also not as bad as it sounds.

One, records and arrays of floats don't suffer an additional level of indirection.

Two, the compiler is actually pretty good at unboxing floats these days. Arguments of non-inlined functions are generally the major reason for boxing to happen (because of ABI requirements). Inner loops should generally be free of unnecessary boxing.

Three, even when boxing happens, keep in mind that OCaml uses a very fast bump allocator (which is also inlined). This means that heap allocation of short-lived values is more like alloca() than malloc().

OCaml is still not the language that you'd want to write performance-sensitive numeric code in, but it's generally fine when floating point math is only one aspect of your code or when you're using it as a way to interface with C/Fortran libraries (such as with Owl [1]), sort of like how Python uses NumPy.

[1] https://github.com/ryanrhymes/owl

Re: A deep dive into Multicore OCaml garbage collector

#88

Earlier quoted context omitted.

On the other hand, it may be possible to use F# on Linux with .NET Core now.

Tooling is definitely far from mature. It's treated as a second class language in .NET, and on top Linux is treated a second class OS. I just tried to start a project with F# and ended up abandoning, and am looking into Rust right now. I considered OCaml but its lack of multicore support and the ecosystem situation made me drop it.

You are kind of right.

My point was that even as second class citizen on .NET, F# has more tooling and available libraries than OCaml ever will on Windows.

For a long time OPAM did not support Windows, and right now cygwin or Linux subsystem still seem to be better ways than straight Win32 application support.

OCaml is quite nice on *NIX systems, on other kind of OSes not so much.

Re: A deep dive into Multicore OCaml garbage collector

#89
post #41

Earlier quoted context omitted.

From what I understand F# is a pretty close version of Ocaml, but has the benefit of all the libraries of the full .net ecosystem.

F# is basically an OCaml clone. I wonder why it isn't called NCaml or something like that. F# lacks some functional programming features the powerful macro system used for creating domain specific languages and extending the ocaml language.

It is related to previous OCaml.NET efforts.

F# computation expressions, coupled with .NET expression trees are quite useful though, even though they aren't macros as such.

Re: A deep dive into Multicore OCaml garbage collector

#90
post #19

I never managed to understand why so many people were apparently longering for multicore support. I just can't believe many are impatiently waiting for this feature to start using the ocaml language for some projects requiring multicore support, and I became impatient myself just to see what those projects are. In recent years where servers are to scale to many machines I found myself using less and less kennel threa…

The most common reasons for requiring shared memory concurrency (instead of message passing) are: 1. It's just plain easier to write a lot of stuff with a shared memory approach. 2. There are algorithms where you get the best speedup using shared memory. But yes, there are also downsides. 1. Shared memory concurrency can be a lot harder on the runtime. In particular, writing an efficient single-threaded GC is an orde…

Erlang essentially using that hybrid model. The runtime uses a shared heap for strings and some other immutable data that can be reference counted. On top of that each thread has own GC-heap and messages copies everything private heap.

I am puzzled why other languages do not even try to explore this. This will be a nice fit for Ocaml or nodejs. And even with Go I wish for be an option to run several Go processes with a shared heap with explicit API to write/read things there and channels working across processes.

Post reply on HN