Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upbpo-38858: Small integer per interpreter #17315
Conversation
This comment has been minimized.
This comment has been minimized.
Example:
The subinterpreter and the main interpreter don't have the same small integer singletons for numbers 1 and 2. |
This comment has been minimized.
This comment has been minimized.
That's a temporary solution which I consider as an acceptable compromise. Small integer singletons are not really part of the Python semantics. It's more the opposite, we advice to not use "is" operator to compare numbers. That's why Python starts to emit such SyntaxWarning:
|
This comment has been minimized.
This comment has been minimized.
I rebased my PR to fix a confict. |
This comment has been minimized.
This comment has been minimized.
Should I run a benchmark? If yes, which kind of benchmark? |
mostly LGTM Also, would it make sense to add any tests for this? I'm not sure it would add much. |
#ifndef NSMALLNEGINTS | ||
#define NSMALLNEGINTS 5 | ||
#endif | ||
#define NSMALLPOSINTS _PY_NSMALLPOSINTS |
This comment has been minimized.
This comment has been minimized.
ericsnowcurrently
Nov 22, 2019
Member
This is effectively a backward-incompatible change (though it only affects folks building their own python binary). So there should be a note in the whatsnew doc (porting section) indicating what folks must do if they want the previous behavior.
This comment has been minimized.
This comment has been minimized.
vstinner
Dec 17, 2019
Author
Member
Do you really expect that anyone would recompile their Python with different NSMALLPOSINTS and NSMALLNEGINTS constants? Disabling these singletons is likely to make Python faster. I'm not sure about increasing the number of singletons. I don't expect any significant performance difference.
This comment has been minimized.
This comment has been minimized.
vstinner
Dec 17, 2019
Author
Member
I completed the NEWS entry. I prefer to not document it in the What's New in Python 3.9 document. IMHO it's too low-level and obscure.
@@ -53,7 +43,8 @@ static PyObject * | |||
get_small_int(sdigit ival) | |||
{ | |||
assert(IS_SMALL_INT(ival)); | |||
PyObject *v = (PyObject*)small_ints[ival + NSMALLNEGINTS]; | |||
PyThreadState *tstate = _PyThreadState_GET(); |
This comment has been minimized.
This comment has been minimized.
ericsnowcurrently
Nov 22, 2019
Member
I'm guessing this was simpler than adding a tstate arg to get_small_int()
...
This comment has been minimized.
This comment has been minimized.
vstinner
Dec 17, 2019
Author
Member
I began by passing tstate to get_small_int() but I don't see any benefit, since no caller requires tstate, or already have tstate, currently. For now, it seems simpler to only get tstate inside get_small_int(). I don't expect any performance issue for now.
@@ -53,7 +43,8 @@ static PyObject * | |||
get_small_int(sdigit ival) | |||
{ | |||
assert(IS_SMALL_INT(ival)); | |||
PyObject *v = (PyObject*)small_ints[ival + NSMALLNEGINTS]; | |||
PyThreadState *tstate = _PyThreadState_GET(); | |||
PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS]; |
This comment has been minimized.
This comment has been minimized.
ericsnowcurrently
Nov 22, 2019
Member
This isn't a static value any more, so is it possible to run into problems during interpreter/runtime finalization?
This comment has been minimized.
This comment has been minimized.
vstinner
Dec 16, 2019
Author
Member
I'm not sure of what you mean. A subinterpreter is supposed to not leak any object to other interpreters, right? If an subinterpreter object survives after the subinterpreter is destroyed, it's a bug, no?
if (_PyLong_One == NULL) { | ||
return 0; | ||
} | ||
if (_Py_IsMainInterpreter(tstate)) { |
This comment has been minimized.
This comment has been minimized.
ericsnowcurrently
Nov 22, 2019
Member
Yuck!
It would be great to have a comment here about how we would like to get rid of this special case. Bonus points if you open an issue for that and link to it in the comment. :)
This comment has been minimized.
This comment has been minimized.
vstinner
Dec 17, 2019
Author
Member
I have no plan to remove _PyLong_One and _PyLong_Zero yet. It seems like there are too many things to do for subinterpreters, I am not excited by long TODO lists. They depress me, as if I will never be able to go to the end. I like to make tiny incremental changes :-)
In general, searching for "_Py_IsMainInterpreter" became a nice hint for "subinterpreters TODO".
This comment has been minimized.
This comment has been minimized.
bedevere-bot
commented
Nov 22, 2019
When you're done making the requested changes, leave the comment: |
This comment has been minimized.
This comment has been minimized.
benchmark? Certainly the normal suite. On top of that, it might be nice to see a "worst-case" benchmark: code that heavily exercises the code paths that have calls to |
This comment has been minimized.
This comment has been minimized.
Here you have. In short, I see no performance regression (maybe speedups, but I'm not sure about these ones :-p). pyperformance benchmark results, ignoring differences smaller than 1%:
pyperformance benchmark results, ignoring differences smaller than 1%:
|
Each Python subinterpreter now has its own "small integer singletons": numbers in [-5; 257] range. It is no longer possible to change the number of small integers at build time by overriding NSMALLNEGINTS and NSMALLPOSINTS macros: macros should now be modified manually in pycore_pystate.h header file. For now, continue to share _PyLong_Zero and _PyLong_One singletons between all subinterpreters.
This comment has been minimized.
This comment has been minimized.
I would prefer until we get ride of _PyLong_Zero and _PyLong_One before going up to unit tests. Right now, you may get the subinterpreter singletons, or the main interpreter singletons depending on which function is called... This PR is a small step towards more isolated subinterpreters. It doesn't solve all issues at once ;-) |
630c8df
into
python:master
This comment has been minimized.
This comment has been minimized.
As I wrote, I know that this change is not complete nor perfect. It's a small step towards better isolated subinterpreters. I chose to not document the backward incompatible change in What's New in Python 3.9, but only in the Changelog. IMHO it's enough, since it's really an obscure low-level feature (number of small integer singletons). |
This comment has been minimized.
This comment has been minimized.
Thanks for the review @ericsnowcurrently. I hope that I addressed most of your remarks ;-) |
bpo-38858: Small integer per interpreter (pythonGH-17315)
vstinner commentedNov 21, 2019
•
edited by bedevere-bot
Each Python subinterpreter now has its own "small integer
singletons": numbers in [-5; 257] range.
For now, continue to share _PyLong_Zero and _PyLong_One singletons
between all subinterpreters.
It is no longer possible to change the number of small integers at
build time by overriden macros: pycore_pystate.h macros should now be
modified manually.
https://bugs.python.org/issue38858