Custom scheduler: Using loom for deterministic simulation testing
Yannick Lecaillez
yannick.lecaillez at pingidentity.com
Tue Jul 8 14:22:17 UTC 2025
Hi,
We're also working a Deterministic Simulation Testing on top of loom for
some times now and though
you might be interested by this feedback:
One goal of our DST is to be able to run applications without having to
change application
code. To do so, we did a lot of trickery in JDK API using Agent (rewired
System.currentTimeMillis(),
System.nanoTime(), jdk.internal.misc.VMn ...). We're also doing call-site
instrumentation in application
code to replace every new Thread() by Thread.ofVirtual().start() (all
virtual threads are backed by a
single-platform thread, effectively a run loop). One limitation is that
this does not work for
`class Foo extends Thread'. Effectively application code must be changed to
replace 'extends Thread'
constructions by using composition. I don't think there is any solution to
this.
Another challenging aspect which might benefit from a JDK modification is
dealing with object monitor.
Since JDK 24, object monitor in virtual-threads don't pin the
carrier-thread anymore. The mechanism relies
on a queue which is polled by a thread-unblocker platform thread. To keep
determinism, we rewrote the
"unblockVirtualThreads()" loop (through Agent) and we select and push
unblocked pending virtual-thread
backed by the DST into another queue which is polled by the run-loop after
every iteration (while the
threads not backed by the DST are unblocked immediately). That appears to
work but is really inefficient
in addition to being complex: it requires checking for every virtual thread
backed by the DST whether
it is present in "onWaitingList". At that time, we made the choice to not
modify the JDK but that
maybe something we could revisit given the recent interest on this topic
appearing on this list.
ImmutableCollections (SALT32L and REVERSE) is another source of
non-determinism that we "fixed" with
our Agent. It would be helpful if the JDK provided a property to set the
seed (but I can see also how
doing so would kind of defeat the purpose of SALT32L).
ThreadLocalRandom.current() was also challenging as it is not possible to
provide a seed. We ended to
rewire #nextSeed() to the DST's Random#nextLong()
Regarding Object#hashCode()/System.identityHashCode() we don't have a
solution. So far we think they
could only impact iteration order of Hash(Map|Set) to which we're
evaluating replacing these by
LinkedHashMap/LinkedHashSet.
It feels like some localized modifications in the JDK would bring enough
flexibility to simplify our Agent
drastically. Otherwise, we'll probably have to adapt it for every JDK
version. I'll try to take the time to propose
a PR about these to make the discussion more concrete.
Best Regards,
Yannick.
--
_CONFIDENTIALITY NOTICE: This email may contain confidential and privileged
material for the sole use of the intended recipient(s). Any review, use,
distribution or disclosure by others is strictly prohibited. If you have
received this communication in error, please notify the sender immediately
by e-mail and delete the message and any file attachments from your
computer. Thank you._
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250708/4bb9d55a/attachment.htm>
More information about the loom-dev
mailing list