-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
py/objint_*: Convert back to small int after binary op. #9531
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
Conversation
77e1ada
to
06c09d3
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #9531 +/- ##
=======================================
Coverage 98.42% 98.42%
=======================================
Files 161 161
Lines 21249 21251 +2
=======================================
+ Hits 20915 20917 +2
Misses 334 334 ☔ View full report in Codecov by Sentry. |
The coverage results are pretty much as expected:
I guess this can all be addressed through |
Well... maybe we can delete all that code that's no longer "reachable"...? If we can't write tests for it in Python, it's not strictly needed. |
Also would be worth running the performance benchmarks, to see if they change. |
You make a very good point. I'm not sure if I'm brave enough to remove them though and it is a very small number of lines. I realised that pow3 can be used to make "small big ints" still, but we should probably also add the same logic there too. |
@@ -308,6 +308,13 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i | |||
} | |||
} | |||
|
|||
mp_int_t res_small; | |||
if (mpz_as_int_checked(&res->mpz, &res_small)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main concern with this PR is that this may impact performance, because now all operations try to convert to a small int.
We should run the benchmark suite to check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance testing has been done, see below.
I ran benchmark tests on this PR, on PYBV10:
The main test is |
06c09d3
to
4e995ee
Compare
Code size report:
|
4e995ee
to
6c0d72c
Compare
Visiting this PR 20 months later, there's a lot less uncovered code now. There are only two small blocks that are now uncovered due to this PR: in |
Before this change, long/mpz ints propagated into all future calculations, even if their value could fit in a small-int object. With this change, the result of a big-int binary op will now be converted to a small-int object if the value fits in a small-int. For example, a relatively common operation like `x = a * b // c` where a,b,c all small ints would always result in a long/mpz int, even if it didn't need to, and then this would impact all future calculations with x. This adds +24 bytes on PYBV11 but avoids heap allocations and potential surprises (e.g. `big-big` is now a small `0`, and can safely be accessed with MP_OBJ_SMALL_INT_VALUE). Performance tests are unchanged on PYBV10, except for `bm_pidigits.py` which makes heavy use of big-ints and gains about 8% in speed. Unix coverage tests have been updated to cover mpz code that is now unreachable by normal Python code (removing the unreachable code would lead to some surprising gaps in the internal C functions and the functionality may be needed in the future, so it is kept because it has minimal overhead). This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <[email protected]>
6c0d72c
to
557d31e
Compare
Add four Pimoroni RP2350 boards
Inspired by #9516 (comment) -- this behaviour was a surprise to me.
Before this change, long/mpz ints propagated into all future calculations.
For example, a relatively common operation like
x = a * b // c
where a,b,c all small ints would always result in a long/mpz int, even if it didn't need to, and then this would impact all future calculations with x.This adds +24 bytes on PYBV11 but avoids heap allocations and potential surprises (e.g.
big-big
is now a small0
, and can safely be accessed with MP_OBJ_SMALL_INT_VALUE).There are several places in the
int_big*
tests that result in small integers (especially zero). I don't think this change makes those tests less valid -- it still correctly checks that they evaluate to the right thing. What we're missing is a way to check that you can print a small-valued mpz (as all these tests will now be going via small int printing).The longlong implementation doesn't have tests, but I adapted the new int_big_to_small.py to run on a 32-bit Linux build.
This work was funded through GitHub Sponsors.