RFR: JDK-8286666: JEP 429: Implementation of Scoped Values (Incubator) [v25]
Andrew Haley
aph at openjdk.org
Thu Nov 24 09:09:27 UTC 2022
On Wed, 23 Nov 2022 19:16:23 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:
> Looks good (just some last minor comments). I did not focus on the tests, nor too closely at all of the HotSpot changes.
>
> Something for future investigation perhaps (if not already thought about): consider using a persistent map, a Hash Array Mapped Trie (HAMT), for storing scoped keys and values, which could potentially remove the need for the cache of replace the cache when many values are in scope. The HAMT's structural sharing properties, wide-branching factor, and `Integer.bitCount` being intrinsic all make for an efficient implementation.
I've certainly considered a HAMT. (I've considered everything! It's been a long journey.) The trouble is that using one penalizes binding operations because a persistent HAMT requires path copying for insertions. This won't matter if your bind operation is rare, such as at the start of a large block of code. However, it might not be. Consider a common case such as a parallel stream using fork/join.
void parallelRunWithCredentials(List<?> aList, Runnable aRunnable) {
var permissions = ScopedValue.where(PERMISSION, getCredentials());
aList.parallelStream().forEach(() -> permissions.run(aRunnable));
}
Because the binding operation `permissions.run()` is invoked for every element on the list, we must make the binding operation as fast as it can possibly be.
In addition, the cache is _extremely_ fast. Typically it's four instructions, and C2 almost always hoists values, once looked up in cache, into registers. A HAMT lookup, while fast and (mostly) O(1), is more complex.
-------------
PR: https://git.openjdk.org/jdk/pull/10952
More information about the core-libs-dev
mailing list