New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[4.x] Atomic reference types should use new Java features, if possible #1560
Comments
🙋♂️ I don't have much experience with Monix, but I saw this on Twitter. One option might be multi-release JARs where different code would be run by different JDK's. It's sort of meant for this kind of issue. I think sbt-missinglink has support for it in sbt, but I've never used it myself. |
@hugo-vrijswijk 👋 I already mentioned the multi-release JARs:
I once saw a plugin for it, but it's not maintained, and it isn't clear to me what it could handle: sbt-multi-release-jar. If multi-release JARs is desirable, the code could be extracted into a pure Java/Maven project, then Monix could depend on it. Another use-case for multi-release JARs is in supporting newer APIs, such as Java 9's The easier option, however, and the de facto standard, is to use Java's runtime reflection mechanisms. We already do that, since once upon a time we supported Scala 2.11 with Java 6 (AFAIR), and so we are querying In addition to Monix's code that I already highlighted in the description (in particular Reflection may not solve the So there are definitely 2 ways to go forward, but that need research and PoC:
Given |
If I understand everything correctly - currently monix use longs for padding. Also, Contended annotation can't be used because it isn't publicly accessible. |
Yikes. This is a very good observation. Memory layout for that padding should be checked, and possibly corrected, for the latest LTS. |
Monix exposes Atomic references, as an alternative to using
java.util.concurrent.atomic
directly. There are several advantages for doing this, such as … reliable cross-platform compilation, a more idiomatic Scala API, and support for all primitive types.The implementation is primarily based on unsage of
sun.misc.Unsafe
. Usage ofsun.misc.Unsafe
is deprecated in newer Java versions and it might go away soon. Monix relies on atomic references for its concurrency (that, plus the queues implemented in JCTools), so ifUnsafe
goes away, we might be in trouble. Also, Monix goes out of its way to make it easier to avoid the problem of false sharing, which is why we have a PaddingStrategy when initializing atomic references.There are 2 new additions to the standard library that need to be investigated, and possibly used by default in the future:
sun.misc.Unsafe
orAtomicReferenceFieldUpdater
(Since Java 9) ;jdk.internal.vm.annotation.Contended
annotation, see paper (Since Java 8, but we might need Java 9 or later, due to JEP 261);Prior art in Monix
The low-level JVM-specific code that Monix uses is in monix-execution/atomic/jvm/src/main/java/. This directory/package has a lot of code repetition b/c these internal classes are specified per Java version and
PaddingStrategy
.For example:
getAndSet
platform intrinsics, but is based onsun.misc.Unsafe
. It also adds 64 bytes of padding to the right of the volatile variable;sun.misc.Unsafe
AND usesgetAndSet
platform intrinsics, available since Java 8;AtomicLongFieldUpdater
(nosun.misc.Unsafe
), which makes it compatible with older Android versions or future Java versions that disallow access tosun.misc.Unsafe
;NOTE — knowing what to build happens in the Factory, which makes use of runtime reflection in UnsafeAccess to evaluate if
sun.misc.Unsafe
or itsgetAndSet
platform intrinsic are available.Making use of reflection is a standard practice for supporting multiple standard libraries from multiple JVM versions. The alternative would be JEP 238: Multi-release JARs, but this never took off (yet).
TODO
PaddingStrategy.Auto
that chooses the best padding strategy, depending on the capabilities of the underlying platform;VarHandle
if possible and where applicable;@Contended
if possible and where applicable;plugins.sbt
) — it would be interesting to see if the new implementations are slower than thesun.misc.Unsafe
ones, and if we don't have a performance hit, maybe they should be preferred by default; note however that benchmarking is tricky, but it would be a fun exercise regardless;NOTE — the difficulty of this issue is that
VarHandle
is available since Java 9. But Monix needs compatibility to start with Java 8.So the question is — in our CI workflows, how do we compile AND test for Java 8, but also have the ability to access a Java 9's standard library when possible, preferably with tests in CI too?
The text was updated successfully, but these errors were encountered: