Live data from Hacker News

We chose Java for our high-frequency trading application

medium.com

161–170 of 287 posts

Re: We chose Java for our high-frequency trading application

#161

I may be acting overly pessimistic, but given the arms race like nature of HFT this could be intentional disinformation.

There are a lot of companies that brag about their last victory, rather than their current one. It’s not so much disinformation as minimally actionable information.

Re: We chose Java for our high-frequency trading application

#162
post #145
post #133

I had to laugh at one line. PHP or Perl are called interpreted because the interpreter (installed on the destination machine) compiles each line of code as it goes. Yeah, that hasn't been true of most "interpreted languages" in decades. The most common interpreted languages that I can think of where you parse as you go are shells like bash. Languages like Perl and PHP are called interpreted because an interpreter run…

The difference is the “compiled representation” of Java is done ahead of time into the .class files while the other two are being done runtime.

> while the other two are being done runtime.

On a common PHP setup (with OpCache today, any predecessor in the past) this happens only once on startup, thus is neglectible. (Java's VM and JIT are faster, no doubt, but where the translation happens matters only a little ... especially since Java does optimisations and JITting on the VM at run time only as well)

Re: We chose Java for our high-frequency trading application

#163
post #143

Earlier quoted context omitted.

Jane Street famously uses OCaml for these types of guarantees, so I would think Rust would offer similar benefits.

Why would you think that? Rust's major selling point for safety guarantees is the borrow checker. It does not provide most of OCaml's type and functional semantics. That being said: Jane Street is pretty avant garde in this respect. I expect there already is, or soon will be, a successful trading firm which likewise builds its tech brand on Rust and alternatives to Rust standard library primitives. But overall adopti…

It has immutability, no null pointers, and error types. It has escape hatches available for everything, but unnecessary use of these should be caught in code review, so I don't think it's a big deal. Not sure what correctness features OCaml could add beyond those, but then again I've never programmed in OCaml, only Scala, so I might be wrong.

Re: We chose Java for our high-frequency trading application

#164

One bit of useful background knowledge: The technical demands for high frequency trading can vary wildly depending on both what kind of trading strategies you're using, and what market you're in. This translates into real-time needs that vary considerably, depending on context. At one firm I used to work at, the spread was several orders of magnitude. On one end, people were counting nanoseconds, and even C++ wasn't…

What language was the team counting in nanoseconds using?

Probably Verilog.

Re: We chose Java for our high-frequency trading application

#165
post #129

Earlier quoted context omitted.

Some people argue that HFT provides liquidity for retail investors, but it's debatable whether that liquidity is real or not since it'll be gone during black swan events. At the same time HFT profit from uninformed/retail flow. So it's debatable wether the actual activity provides values. I'd say probably not. But there can be indirect value in working in HFT, just like there is with other demanding jobs. There's int…

I'm not an economics or finance expert, so I may not have a very extensive view of this, but I think there is a meaning to the expression of providing value. If a product has more value to a person than the price of the product, assuming they have correct knowledge, that is the creation of value. In high frequency trading, or stock trading in general, people may be willing to pay more than the listed price, but I don…

HFT may not, but trading itself definitely provides positive value. People's utility function is not purely monetary over an infinite time horizon. Trading allows you to trade off price and risk over multiple time horizons.

For example, a trade where someone needs to convert his assets into cash due to a family emergency benefits both sides. The person with the emergency takes liquidity from the market and pays a premium because the trade is time-sensitive - he needs cash the next day. Other liquidity traders may profit from such "uninformed" flow in the long term, but both parties are happy because they got what they want.

Another example is trading off risk and hedging against certain changes in the world that would affect you.

Re: We chose Java for our high-frequency trading application

#166
post #48

The Azul JVM has been around for I'm guessing at least 10+ years? I think originally you had to buy it on their own custom hardware. No idea what it's like now, but an ex-sales guy told me then that it wasn't super reliable.

They had hardware in 2005, but started transitioning to JVM only in 2010.

They used some of the intel instructions meant for running VMs to get fast concurrent GC. It’s probably a lot easier to court customers with a software only solution than with custom hardware they can’t really repurpose...

Re: We chose Java for our high-frequency trading application

#167
post #109

Earlier quoted context omitted.

Even if you completely disable GC, Java is still allocating tons of ephemeral objects on the heap. Which in turn is leading to expensive and unpredictable page faults. In contrast, C++'s default is to allocate objects on the heap unless you knowingly call new/malloc. Of course, it's possible to write Java in such a way to minimize this type of heap-thrashing. But by that point, you're already doing the equivalent of…

That's covered in Java by escape analysis and allocation on the stack.

We have written a database in zero GC java and one thing I have not seen any evidence of "escape analysis".

   @State(Scope.Thread)
   @BenchmarkMode(Mode.AverageTime)
   @OutputTimeUnit(TimeUnit.NANOSECONDS)
   public class EscBenchmark {

       Rnd rnd = new Rnd();

       public static void main(String[] args) throws RunnerException {
           Options opt = new OptionsBuilder()
                   .include(EscBenchmark.class.getSimpleName())
                   .warmupIterations(5)
                   .measurementIterations(5)
                   .forks(1)
                   .addProfiler(GCProfiler.class)
                   .build();

           new Runner(opt).run();
       }

       @Benchmark
       public int testEscapeAnalysis() {
           int[] tuple = {0, 2}; // esc analysis? where are you?
           return tuple[rnd.nextPositiveInt() % 2];
       }
   }

And the output of GC profiler:

  Benchmark                                                     Mode  Cnt     Score     Error   Units
  EscBenchmark.testEscapeAnalysis                               avgt    5     8.234 ±   0.029   ns/op
  EscBenchmark.testEscapeAnalysis:·gc.alloc.rate                avgt    5  2647.216 ±   9.275  MB/sec
  EscBenchmark.testEscapeAnalysis:·gc.alloc.rate.norm           avgt    5    24.000 ±   0.001    B/op
  EscBenchmark.testEscapeAnalysis:·gc.churn.G1_Eden_Space       avgt    5  2643.140 ± 177.137  MB/sec
  EscBenchmark.testEscapeAnalysis:·gc.churn.G1_Eden_Space.norm  avgt    5    23.963 ±   1.613    B/op
  EscBenchmark.testEscapeAnalysis:·gc.count                     avgt    5   157.000            counts
  EscBenchmark.testEscapeAnalysis:·gc.time                      avgt    5   103.000                ms

Re: We chose Java for our high-frequency trading application

#168
If you are publishing a JVM GC benchmark, you should really include the parameters you used for the program as well as what steps you took to find those particular parameters. While I think it has gotten better in recent years, there are still many knobs for most JVMs which can make a big difference in performance.

Ideally, you would want to have the benchmark developers cooperate with the team creating the JVM you are evaluating in order to be as far as possible with the benchmark sort of like how the TPC benchmarks are done.

Re: We chose Java for our high-frequency trading application

#169
post #133

I had to laugh at one line. PHP or Perl are called interpreted because the interpreter (installed on the destination machine) compiles each line of code as it goes. Yeah, that hasn't been true of most "interpreted languages" in decades. The most common interpreted languages that I can think of where you parse as you go are shells like bash. Languages like Perl and PHP are called interpreted because an interpreter run…

The PHP Wikipedia page seems to argue that the most popular implementation, Zend, is an interpreter.

https://en.wikipedia.org/wiki/PHP#Implementations

Re: We chose Java for our high-frequency trading application

#170
post #112

Several commenters have brought up garbage collection. I'm curious. How much heap memory do HFT applications typically allocate in a day? I'd expect them to be doing most of the work, or at least most of what actually needs low latency, in locally allocated primitives which would be on the stack. If that's the case, you might be able to turn off garbage collection and just stick enough RAM in your computer that it ta…

> Once a day, reboot.

Alternatively, you could have a pool of Java servers and coordinate GC with your load balancer.

That is, some system would:

(1) coordinate with the load balancer (or directory service of endpoints) to ensure that a Java node is completely out of the pool

(2) coordinate with the Java node to ensure all its in-progress requests have completed

(3) run a full GC on that node

(4) return it to the pool

(5) move on to the next node, cycling through them.

You probably wouldn't need to increase the number of Java nodes very much, either. If a GC is required every 10 minutes and it only takes 30 seconds to do this, then you only need 5% more Java nodes.

Post reply on HN