ScopedValue performance declines as number of dynamic bindings increases
Johan Sjolen
johan.sjolen at oracle.com
Tue Jun 24 15:21:16 UTC 2025
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