Uh oh!
There was an error while loading. Please reload this page.
gh-103092: Add a mutex to make the random state of rotatingtree concurrent-safe - #115301
Conversation
Codesimportsysimportthreadingimport_xxsubinterpretersimportcProfilecode="""def f(): import re import json import pickle d = {str(x): {x: x} for x in range(1000)} for _ in range(100): re.compile("foo|bar") json.loads(json.dumps(d)) pickle.loads(pickle.dumps(d))"""defrun_single():
ctx= {}
exec(code, ctx)
cProfile.runctx("f()", ctx, {})
defrun_multi():
ts= []
interps= []
for_inrange(4):
interp=_xxsubinterpreters.create(isolated=1)
interps.append(interp)
c=code+"import cProfile; cProfile.run('f()')"t=threading.Thread(target=_xxsubinterpreters.run_string, args=[int(interp), c])
t.start()
ts.append(t)
fortints:
t.join()
forinterpininterps:
_xxsubinterpreters.destroy(int(interp))
iflen(sys.argv) >1andsys.argv[1] =='multi':
run_multi()
else:
run_single()Single interpreter:base (b104360):current:Multiple interpreters:I'm using a 4 physical core Intel MacBook. As the code above shows, 4 isolated interpreters are used for this benchmark. base (b104360):With Lines 1008 to 1009 in b104360 PER_INTERPRETER_GIL_SUPPORTED.Although this is not safe, I think it doesn't matter for this microbenchmark. All 4 interpreter finished in the same seconds (+-0.x seconds). current:SummaryOn my machine, the execution time of the code before and after the modification varies, sometimes better and sometimes worse. I believe that the introduced performance difference falls within the observable error range. |
erlend-aasland
left a comment
There was a problem hiding this comment.
AFAICS, it should be ok to share the pseudo-random generator between interpreters. @ericsnowcurrently, thouhts?
erlend-aasland
commented
Feb 12, 2024
(Needs a NEWS entry, though.) |
erlend-aasland
commented
Feb 27, 2024
I'll land this sometime next week, to give @ericsnowcurrently a chance to chime in. |
ericsnowcurrently
commented
Feb 27, 2024
I'll take a look in the next couple days. Thanks for the heads-up! |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
erlend-aasland
commented
Feb 29, 2024
Thanks for the PR, @aisk, and thanks for the review, @ericsnowcurrently 🎉 |
The only two static variables,
random_valueandrandom_stream, inrotatingtree.c(which is only used by_lsprofmodule) are just the state of a pseudo-random generator. They can be shared between interpreters if we add a mutex to make them concurrent-safe. And this work can be done easily, and make the_lsprofilemodule isolated.Another way to isolate
_lsprofis to store the two variables in module state. This will involve more work and review of modifications to existing functions to pass the module state. See #115130.Adding the mutex does not introduce a noticeable performance decrease. See the comment below for a micro benchmark.
@erlend-aasland