ScopedValue performance declines as number of dynamic bindings increases

Robert Engels robaho at me.com
Tue Jun 24 15:29:28 UTC 2025


You can’t test Java applications that way. I’m sorry but you need to look into using something like JMH. 

Most low level Java designs for infrastructure code like this rely on the JVM being able to optimize away a lot of layers. Your tests don’t allow that to happen. 

> On Jun 24, 2025, at 10:22 AM, Johan Sjolen <johan.sjolen at oracle.com> wrote:
> 
> 
> Hi Robert,
> 
> Right, I skipped some explanation for brevity. I just ran `time java ScopedTest.java > /dev/null` and `time java ScopedTest2.java > /dev/null` and checked the time difference. That is of course not very granular, but the difference was from 0.6 seconds to 3 seconds, so the noise from VM startup etc doesn't seem very relevant.
> 
> ________________________________________
> From: Robert Engels <robaho at me.com>
> Sent: Tuesday, June 24, 2025 17:16
> To: Johan Sjolen
> Cc: loom-dev at openjdk.org
> Subject: Re: ScopedValue performance declines as number of dynamic bindings increases
> 
> The Java code has no valid benchmarking that i can see ???
> 
>> On Jun 24, 2025, at 10:12 AM, Johan Sjolen <johan.sjolen at oracle.com> wrote:
>> 
>> Hi,
>> 
>> I've been working on implementing a feature and the ScopedValue preview feature was an excellent fit to a particular design problem I faced.
>> Reading the source code, I noticed that it seems as though the linked list of value bindings are shared across all ScopedValue instances. This was a bit surprising to me, as this means that the performance of accessing
>> a ScopedValue binding declines linearly with the number of bindings before it on the stack.
>> 
>> The ScopedValue feature has a long heritage, with historical roots in Lisp and Scheme. The most similar implementation that I know of is that found in Racket, where they are called Parameters[0]. Parameters are also inherited by child threads, and are accessed per thread. Guile, a different Scheme, calls ScopedValue thread-local fluids[1].
>> 
>> Okay, so multiple languages have these things, do they have the same performance implications? The answer seems to be no.
>> I wrote a number of benchmarks, for Java, Racket and Guile. The Racket benchmark shows no discernible difference in performance, and neither does Guile Scheme, however the Java benchmarks show a very large difference in runtime. It makes sense that the Scheme languages optimize for this case, as they use parameters a lot. For example, with-output-to-file rebinds the current-output-port in order redirect the output to a file. If accessing this variable required traversing a linked list each time, then the performance of the system as a whole would suffer. These languages show how ScopedValues have come to be used by languages which have had these features for a long time. Namely, they provide a reasonable default (current-output-port pointing to stdout), whilst allowing the user to manipulate the parameters in order to change behavior when needed.
>> 
>> I'm wondering about the reasoning and trade-offs here, what do we get with our implementation that the Schemers do not? Maybe we should consider changing our implementation?
>> 
>> Cheers,
>> Johan
>> 
>> ScopedTest.java:
>> https://urldefense.com/v3/__https://gist.github.com/jdksjolen/19133aa25f1008eee34bab07d4c94eab__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA4pIREFTw$
>> ScopedTest2.java:
>> https://urldefense.com/v3/__https://gist.github.com/jdksjolen/2b689d91873b411bdcbfc790a7238f5a__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA5Q8tVycg$
>> 
>> Racket benchmark code:
>> https://urldefense.com/v3/__https://gist.github.com/jdksjolen/9598ec7a8c4a925b2913a9062d4d9917__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA6hiiCnwg$
>> Guile benchmark code:
>> https://urldefense.com/v3/__https://gist.github.com/jdksjolen/cfbf22976f17bec2d9b08b1e6f976bad__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA4emOCpVw$
>> 
>> [0] https://urldefense.com/v3/__https://docs.racket-lang.org/reference/parameters.html__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA57vjxI8A$
>> [1] https://urldefense.com/v3/__https://www.gnu.org/software/guile/manual/html_node/Thread-Local-Variables.html__;!!ACWV5N9M2RV99hQ!Oe9RX8Xi3F6apgsiVGb05gq34JZYOqCoUiUR06JoHb65pv6yIfXDeePbuK2yuSrsQpdgLA6LMDlC8g$


More information about the loom-dev mailing list