Hacker News new | ask | show | jobs
by z92 2028 days ago
When you write Java in a C like syntax : "Chronicle's system is built in what Lawrey describes as "C-like Java" and it's this that he encourages people to code low latency systems in."

I guess very limited number of constructors, and most of all the methods are static.

And they still struggle to find programmers that can code that way.

6 comments

Avoiding allocations is the key part: "...we avoid all the garbage". I found the same is true when trying to write high performance Java UI code for Android. If you have to do something complex each frame, make sure to pre allocate or pool your objects. If the hot parts of the code are written in a C-like style, then the JIT and other optimizations can give you C-like performance. You'll still need to write C code if you want vector operations or other processor-specific functionality, but writing in C-like Java can give you C performance while still letting you interact with Java libraries & APIs.
I've found that coding in a "C-like style" offers great performance too. Are there any languages that target the JVM and are designed for higher speed? If it enforced the "C-like style" at the language level, perhaps it would be easier to follow?

Of course at this point the usual answer is just use Rust, but is there a language that meets in the middle? Sometimes I just want the GC to do the work and I'm okay with that.

I find Java itself works quite well for this. Especially newer Java versions with functional interfaces. You keep your data in data centric classes (e.g. something akin to struct-of-arrays in C) and have some functional interfaces to access this data, the only place where you loop over it, maybe in batches if it's really large (test it though, up to 10s or 100s of millions of elements is still fast to loop through in memory). Then you got some algorithm centric classes that you can plug into these interfaces. And finally, after reducing the data you may have some classic objects, e.g. to represent results.

edit, to give you an example. Let's say you have double precision X/Y coordinates. Put that into a class with two double arrays for X and Y. In order to e.g. run an Euclidean distance computation against it, provide a (double, double) -> double interface against it. Then you have either an Euclidean distance class providing that function or just an inline lambda that you can plug into that interface, giving you a distance array. Let's now say you just want to have a list of 10 closes points - instead of sorting you're fastest to brute force it. Only after you reduced it down to the 10 points, you put them into Point objects because there's probably a consumer expecting it that way.

> Are there any languages that target the JVM and are designed for higher speed?

Yes: Java

Performant Java looks mostly like C, just with no manual malloc() calls.

Sure you could write Java in a J2EE way but.. that not a good choice.

In Java, every object stored on heap (and they can't be stored on stack) has a JVM-induced space overhead. Also, the allocator is free to spread the objects across the heap in a chaotic manner, which will make for less than optimal utilization of cache lines.
That's... not how JVMs work.

All modern VMs (not just limited to Java here!) apply two key optimizations. The first is escape analysis, which checks if references to objects will escape the current function boundary. If not, the objects will be stored on the stack instead of the heap. The second is generational GC, where memory allocation looks like this:

   void *new_ptr = heap_mem;
   heap_mem += alloc_size;
   if (heap_mem >= max_size)
     outlined_function_to_get_larger_blocks_of_memory();
It's actually likely to be a tighter allocator than C/C++'s malloc, since there's no mucking about with freelists.
>"but writing in C-like Java can give you C performance while still letting you interact with Java libraries & APIs."

Assuming those libraries do not do allocations of their own negating all the efforts.

That's right. Java libraries even within JDK are notorious for unnecessary allocations and locks (which also do allocations for queues) putting GC pressure. C-like java means the need to roll out your own or using libraries like Chronicle.
I imagine that the other libraries would be used only on the non-critical parts of the application.
This is Go and sync.Pool, essentially. He may have better luck finding good Gophers.
> "but writing in C-like Java can give you C performance while still letting you interact with Java libraries & APIs."

It really can't. Quite the opposite. Writing C-like Java is already doomed from the start. Java is faster than C when it comes to OOP. Unless you product is a highly complex OOP nightmare, C will always beat Java to the curb.

GC is not free. The problem with GC is that you pay asynchronously, while allocations are essentially free. But this asynchronous cost is very very hard to measure and to control. Java does not offer the mechanism C/C++ offer for native resource management. It also doesn't do complex optimizations, most notably vectorization. Number crunching performance will always suck in Java. Even if they add all the optimizations in the world, the simple fact remains: Java as a language simply does not allow you to express code in a performant way. That leave the compiler at a double disadvantage. It needs to essentially "convert Java to C++ and guess the most performant interpretation" (we are decades away from this), and it needs to do that within milliseconds (because its a JIT).

It just makes no sense to talk about this. Use Java for the 99% of your product that is not a hotpath, use C for the remaining 1% where you need pure performance. Simple as that.

Use the stack and not the heap.

Pre-allocate arrays, avoid collections.

Use LUTs.

Avoid string processing, operate on bits and bytes as much as possible.

Same applies to telecoms-development that has to be fast and predictable.

>Same applies to telecoms-development that has to be fast and predictable.

Funny enough, I've always thought of it more of writing Java like Erlang than C.

What is LUT?
> When you write Java in a C like syntax

And C is faster still when you write it with Fortran like (column order, and "restrict" mostly) semantics.

An old mentor said to me 30 years ago that "A good programmer writes FORTRAN no matter what language they are using" (he was referring to speed of execution in the context of "good"). It seemed super funny at the time, but there's a lot of truth in that.

Why does column order matter? If you translate to the equivalent C/C++ row-major order, it should be laid out in memory the same way.
What do you mean by "if you translate to C/C++ row major order?"

What I meant was: In FORTRAN, you idiomatically do Struct-Of-Array=Column-Major order by default, In C/C++ you do Array-of-Struct or Array-of-Pointer-to-Struct (both of which are Row-Major) by default. The former tends to be much more efficient than the latter in computational code.

It turns out that, often and especially in computationally intensive code, only a small number of fields of an object/record are used in every part of the computation pipelines, but almost all records are.

As a result, if you do your data in column major order, then the cache usage patterns reflect that - whereas if you are in row major order, a lot more field get loaded into cache when they are not needed (thus, much lower cache utilization and lower performance).

FORTRAN did not have structures until quite late (FORTRAN-95 has them for sure, but IIRC FORTRAN-77 and earlier didn't). Thus, the idiomatic way to do stuff is have an SoA=Coiumn-Major implementation, rather than the C/C++ AoS=Row-Major order.

Furthermore, FORTRAN didn't have any pointers. As a result, most code was written with very little pointer chasing / foreign key reference chasing -- which also contributes to efficient use of cache and memory bandwidth.

Are you using meme language? If yes, be aware it makes your point harder to understand. I'm wondering if you've made a grammatical error, are not good at English, or something else.
Imagine comment on hacker news ngl
Sometimes I feel this approach is simpler than making everything into an Object. It usually results in less files to deal with.
This is also allegedly the programming style of C# used by StackOverflow to squizz performances.