New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Small ints aren't always cached properly #90519
Comments
To my surprise, it seems that it's possible to create "small" integers that should live in _PyLong_SMALL_INTS, but don't. Here are two examples I've found: >>> import decimal
>>> i = int(decimal.Decimal(42)) # Modules/_decimal/_decimal.c:dec_as_long
>>> i
42
>>> i is 42
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False
>>> i = int.from_bytes(bytes([42])) # Objects/longobject.c:_PyLong_FromByteArray
>>> i
42
>>> i is 42
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False I'm not entirely sure if this is "allowed" or not, but in any case it seems beneficial to reach into the small ints here (provided it doesn't hurt performance, of course). I'm testing out simple fixes for both of these now. |
I don't *think* we currently rely on small integers being cached anywhere in the implementation (and neither do we guarantee anywhere in the docs that small integers will be cached), so as far as I can tell these omissions shouldn't lead to user-visible bugs. I agree that these cases should be fixed, though. |
Hmm. This sort of thing is a little dodgy, though (despite the comment that it's "okay"): Line 939 in 1de6015
PyObject *zero = _PyLong_GetZero(); // borrowed ref
for (i = 1; i < nargs; i++) {
/* --- 8< --- snipped code */
if (res == zero) {
/* Fast path: just check arguments.
It is okay to use identity comparison here. */
Py_DECREF(x);
continue;
}
/* --- 8< --- snipped code*/
} |
And there are some similar things going on in rangeobject.c. Line 598 in 1de6015
if (r->step == _PyLong_GetOne()) {
return idx;
} Again, technically "okay", since it's only a fast path and the slow path that follows will still do the right thing with a 1 that's not "the" 1, but it feels fragile. |
The attached PR doesn't seem to have any impact on Decimal performance (non-optimized, non-debug build on a fairly quiet laptop): main: Convert 262,000 Decimals to "small" ints: 31.7 ms +- 5.3 ms patched: Convert 262,000 Decimals to "small" ints: 30.9 ms +- 4.0 ms |
int
caching #30583Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: