Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The Janet Street folks, who created this, also did an interesting episode[0] of their podcast where they discuss performance considerations when working with OCaml. What I was curious about was applying a GC language to a use case that must have extremely low latency. It seems like an important consideration, as a GC pause in the middle of high-frequency trading could be problematic.

[0] https://signalsandthreads.com/performance-engineering-on-har...




I actually asked Ron Minsky about exactly this question on Twitter[0]:

    Me: [W]hy not just use Rust for latency sensitive apps/where it may make sense?  Is JS using any Rust?

    Minsky: Rust is great, but we get a lot of value out of having the bulk of our code in a single language. We can share types, tools, libraries, idioms, and it makes it easier for folk to move from project to project.

    And we're well on our way to getting the most important advantages that Rust brings to the table in OCaml in a cleanly integrated, pay as you go way, which seems to us like a better outcome.

    There are also some things that we specifically don't love about Rust: the compile times are long, folk who know more about it than I do are pretty sad about how async/await works, the type discipline is quite complicated, etc.

    But mostly, it's about wanting to have one wider-spectrum language at our disposal.
[0]: https://x.com/arr_ohh_bee/status/1672224986638032897


Well on their way.. by having to write a ton of C for the interpreter. I think it’s really imprudent for them not to be using Rust yet for critical sections.


The problem is not a GC language per se, people keep putting all GC languages in the same basket.

The real issue is being a GC language, without support for explicit manipulation of stack and value types.

Want a GC language, with productivity of GC languages, with the knobs to do low level systems coding?

Cedar, Oberon language family, Modula-3, D, Nim, Eiffel, C#, F#, Swift, Go.


Does Go have much in the way of GC knobs? It didn't some years ago, but I haven't kept up on latest developments


The knobs aren't on the GC necessarily, rather language features.

With a Go compiler toolchain you have stack and global memory static allocation, use of compiler flags to track down when references escape, manually allocate via OS bindings, there is the unsafe package, and use slices with it, an assembler is part of the toolchain learn to use it, and regardless of CGO is not Go memes, it is another tool to reach for if Assembly isn't your thing.


Ohh right yes, now I get what you mean. My brain just immediately went for "GC knobs" when you mentioned "knobs", but in my defense I'm running a 40°C fever so I should probably not be commenting at all


All the best and get well.


.NET AOT compiles comically slowly. It makes C++ look like Ocaml. I have no idea how anyone uses it for anything serious.


GC compactions were indeed a problem for a number of systems. The trading systems in general had a policy of not allocating after startup. JS has a library, called "Zero" that provides a host of non-allocating ways of doing things.


Couldn’t find this after 6 seconds of googling, link?


The linked podcast episode mentions it.


There's no mention of a library called zero, or even JavaScript.


Im assuming the JS refers to Janes street


That makes sense, I guess I've got web tunnel vision.


I was bit by the same spider that gave you web tunnel vision. In any case, I find OCaml too esoteric for my taste. F# is softer and feels more..modern perhaps? But I don’t think GC can be avoided in dotnet.


You can avoid GC in hot loops in F# with value-types, explicit inlining, and mutability.

Mutability may not result in very idiomatic code however, although it can often be wrapped with a functional API (e.g. parser combinators).


> This is what I like to call a dialect of OCaml. We speak in sometimes and sometimes we gently say it’s zero alloc OCaml. And the most notable thing about it, it tries to avoid touching the garbage collector ...


> What I was curious about was applying a GC language to a use case that must have extremely low latency. It seems like an important consideration, as a GC pause in the middle of high-frequency trading could be problematic.

Regarding a run-time environment using garbage collection in general, not OCaml specifically, GC pauses can be minimized with parallel collection algorithms such as found in the JVM[0]. They do not provide hard guarantees however, so over-provisioning system RAM may also be needed in order to achieve required system performance.

Another more complex approach is to over-provision the servers such that each can drop out of the available pool for a short time, thus allowing "offline GC." This involves collaboration between request routers and other servers, so may not be worth the effort if a deployment can financially support over-provisioning servers such that there is always an idle CPU available for parallel GC on each.

0 - https://docs.oracle.com/en/java/javase/17/gctuning/parallel-...


Java is like C and C++, there isn't the one implementation.

So if you want hard guarantees, you reach out to real time JVM implementations like the commercial ones from PTC and Aicas.


You just let the garbage accumulate and collect it whenever markets are closed. In most cases, whenever you need ultra low latency in trading, you usually have very well defined time constraints (market open/close).

Maybe it's different for markets that are always open (crypto?) but most HFT happens during regular market hours.


Is that really a viable solution for a timeframe of 6+ hours?


Sure, if you know how much you allocate per minute (and don’t exceed your budget) you just buy enough RAM and it’s fine.


This will decrease performance because of reduced locality. Maybe increased jitter because of TLB misses.


Compared to what, running a garbage collector?


No, compared to not doing so many allocations that freeing them is time consuming or expensive. Having allocations slow a program down means that there are way too many, probably due to being too granular and being in a hot loop. On top of that it means everything is a pointer and that lack of locality will slow things down even further. The difference between allocating many millions of objects and chasing their pointers and doing a single allocation of a vector and running through that can easily be 100x faster.


Probably? Locality becomes fairly important at scale. That’s why there’s a strong preference for array-based data structures in high-performance code.

If I was them I’d be using OCaml to build up functional “kernels” which could be run in a way that requires zero allocation. Then you dispatch requests to these kernels and let the fast modern generational GC clean up the minor cost of dispatching: most of the work happens in the zero-allocation kernels.


(this comment was off topic, sorry)


Is this relevant to OCaml?


ha ha oops I got confused


I think it is, but to be clear I think (from my very limited experience, just a couple of years before leaving finance, and the people with more experience that I've talked with) that c++ is still a lot more common than any GC language (typically java, since OCaml is even rarer). So it is possible, and some firms seem to take that approach, but I'm not sure exactly how besides turning off GC or very specific GC tuning.

Here is a JVM project I saw a few years back, I'm not sure how successful the creators are but they seem to use it in actual production. It's super rare to get even a glimpse at HFT infra from the outside so it's still useful.

https://github.com/OpenHFT


Yes. It is a very common design pattern within banks for systems that only need to run during market hours.


I talk about doing this in an audio context and get met with raised eyebrows, I'd love some references on others doing it, if anyone can share!


You can just add more RAM until it is viable.


Are you aware of how many allocations the average program executes in the span of a couple of minutes? Where do you propose all of that memory lives in a way that doesn’t prevent the application from running?


Haven't looked at the link, but I think for a scenario like trading where there are market open and close times, you can just disable the GC, and restart the program after market close.


It is a common strategy.


*Jane Street


It's a great name for a competitor :)




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: