Release fence pollution in constructors and builders

175 views
Skip to first unread message

Andriy Plokhotnyuk

unread,
Jul 17, 2019, 3:06:22 AM7/17/19
to mechanical-sympathy
Hi All,

Latest versions of some JVMs and libraries started to use release fences in constructors or builders of data structures which are not concurrent by definition.

Below are a couple of examples:

1) Using of release (and sometime store-store) fences in all constructors in GraalVM:

2) Using of release fences in constructors or builders of immutable collections in Scala 2.13:

The question is: Why all these fences cannot be moved to places which work with concurrency immediately: GCs, static field initializers, concurrent data structures and APIs like futures, actors, etc.?

Aleksey Shipilev

unread,
Jul 17, 2019, 4:12:36 AM7/17/19
to mechanica...@googlegroups.com, Andriy Plokhotnyuk
On 7/17/19 9:06 AM, Andriy Plokhotnyuk wrote:
> 1) Using of release (and sometime store-store) fences in all constructors in GraalVM:
> https://github.com/oracle/graal/blob/e9dbc9d6d3080daf22dec38ce8c234417e1a8e3c/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java#L925

I don't follow. It puts LoadStore for all constructors that store final fields (as expected), and
StoreStore for everything else (as expected). StoreStore is needed to protect the recently allocated
object metadata from the races. Note that you can see the "default" values of Java fields because
publishing the reference to the object may appear "before" constructor stores are observed. But the
same thing would be catastrophic for "metadata" stores like initial mark and klass words: in the
_best_ case scenario, JVM would just crash.

Graal is not alone in this, see e.g. https://bugs.openjdk.java.net/browse/JDK-8032481

> 2) Using of release fences in constructors or builders of immutable collections in Scala 2.13:
> https://github.com/scala/scala/search?q=releaseFence%28%29&type=Code

I vaguely remember this being discussed, but cannot remember the conclusion. It tries to emulate
final fields without declaring them final? It does not work completely without LoadLoad on the
reader side (https://shipilev.net/blog/2014/all-fields-are-final/#_implementation_support), but it
is safer than not doing the release stores at all.

> The question is: Why all these fences cannot be moved to places which work with concurrency
> immediately: GCs, static field initializers, concurrent data structures and APIs like futures,
> actors, etc.?

I don't follow this suggestion. These fences are about surviving races (this is what finals are
for), and thus every follow-up access to the object is exposed on every path, including those that
do not deal with concurrency "immediately".

-Aleksey

signature.asc

Andriy Plokhotnyuk

unread,
Jul 17, 2019, 6:41:47 AM7/17/19
to mechanical-sympathy
Hi Aleksey,

Thanks for your fast response! Now I see that all these usages of fences are for better, but on another side when combined they lead to the slowdown of the throughput for single-thread code greatly...

And I feel a little panic when seeing ~1.5x times drop of performance for Scala 2.13.0 collections with JDK and ~7x times with GraalVM.

Here is a PR with benchmarks and their results for the linked list building in Java and Scala: https://github.com/plokhotnyuk/jsoniter-scala/pull/341

I'm not going to suggest something and just wondering if there is some clear approach to minimize the usage of fences, but still stay on the safe ground when working with data structures in JVMs.
Reply all
Reply to author
Forward
0 new messages