Hacker News new | ask | show | jobs
by shagie 1870 days ago
From the link about GraalVM:

> Something that Graal can do that C2 cannot, and a key advantage of GraalVM, is partial escape analysis. Instead of determining a binary value of whether an object escapes the compilation unit or not, this can determine on which branches an object escapes it, and move allocation of the object to only those branches where it escapes.

And from https://docs.oracle.com/en/java/javase/11/vm/java-hotspot-vi...

> The Java HotSpot Server Compiler implements the flow-insensitive escape analysis algorithm described in:

> ...

> After escape analysis, the server compiler eliminates the scalar replaceable object allocations and the associated locks from generated code. The server compiler also eliminates locks for objects that do not globally escape. It does not replace a heap allocation with a stack allocation for objects that do not globally escape.

----

So, some JVMs implement, others only do a limited subset of the optimizations available with escape analysis.

I would not say that the answer of "is it used in practice" is "no."

1 comments

GraalVM is excellent in performing escape analysis on objects on the call stack, but it does not prevent the pointer overhead that a JVM array-of-heap-object-references has vs an array-of-structs that e.g. .NET supports [2].

Theoretically it could do hat, but that's just the classic "sufficient smart compiler" strawman [1]

[1] https://wiki.c2.com/?SufficientlySmartCompiler

[2] https://stackoverflow.com/questions/29665748/memory-allocati...

My point wasn't so much "can GraalVM do {some optimization}" but rather that the Java Language Specification doesn't say anything about it and that different JVMs have a different set of optimizations.

So "does Java allocate a record in an array directly as some structure of values in the array or as a pointer to a record object?" isn't one that can be answered by looking at Java.

It is an interesting question, and I'd be curious to see someone do a deep dive into the internals of GraalVM to show what can be done.

The other part that trickled out in other comments from the person posing the question about the array of records:

> It's a global array of structs, let's say.

and

> No, because my competitors who are attempting to fill the same orders I am attempting to fill are not chasing pointers.

... which, I'd be curious to see how .NET supports an array of struts (that are presumably changing over the lifetime of the array) that is allocated as a global. That sort of use case and the specifics of how it is implemented could make escape analysis give up and you'll see an array on the heap with pointers to records on the heap as they're passed off to different threads (which each have their own stack).

The point is those optimizations are not here now, and haven't been there for the last 25 years. Hand-waving them away as theoretically possible is dishonest. We're 25 years into the most popular programming language's lifetime and the most advanced VM available only recently learned good escape analysis. It isn't easy.

> which, I'd be curious to see how .NET supports an array of struts (that are presumably changing over the lifetime of the array) that is allocated as a global.

Very easy. An array-of-structs (which can still be on the heap mind you) will just be a continuous block of memory. This is totally independent of any locking and synchronization.

For example in a class with 2 32-bit fields, and an array of objects a b object-ref array will look like: [p_ap_b], p being a pointer to [a_0a_1] or [b_0b_1]. A struct-array will look like [a_0a_1b_0b_1].