-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Refactor BCMath 1 #14076
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
Refactor BCMath 1 #14076
Conversation
27c292e
to
e87f1f5
Compare
I plan to conduct a high-precision benchmark. |
89bcbbd
to
ff77807
Compare
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.
Commits 1 and 2 are good to land, got questions/remakrs about commit 3
ext/bcmath/libbcmath/src/str2num.c
Outdated
/* Skip Sign */ | ||
ptr++; | ||
} | ||
ptr += (*ptr == '-' || *ptr == '+'); |
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.
This is true, but adding a comment can't help (i.e. if we have a sign we need to increment the str pointer)
ext/bcmath/libbcmath/src/str2num.c
Outdated
char *ptr, *nptr; | ||
size_t trailing_zeros = 0; | ||
size_t str_scale = 0; | ||
char *ptr, *nptr, *integer_ptr, *integer_end, *fractional_ptr = NULL, *fractional_end = NULL, *decimal_point; |
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.
I usually prefer to have each declaration on its own line
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.
In release builds this had no effect so I reverted it
ext/bcmath/libbcmath/src/str2num.c
Outdated
@@ -38,9 +38,8 @@ | |||
bool bc_str2num(bc_num *num, char *str, size_t scale) |
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.
Does it make sense to pass the str_len here? As this should save the need to compute strlen()
of it in the function body (also you can easily determine if we have reached the end of the str or not.
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.
I've already tried that and it was slower. Since the length can be obtained from zend_string, there should be no computational cost, so it's strange that it's slower....
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.
I would also expect that ZSTR_LEN is faster. Are you using a release build without ASAN & UBSAN instrumentation?
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.
Ahhh, it was a debug build.... I'll try again
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.
This worked quite well for the release build, but I ended up not needing the length of str, so I'll leave it unchanged.
However, I would use ZSTR_LEN if future refactoring requires it.
ext/bcmath/libbcmath/src/str2num.c
Outdated
if (decimal_point) { | ||
/* search */ | ||
fractional_ptr = decimal_point + 1; | ||
fractional_end = fractional_ptr + strlen(fractional_ptr) - 1; |
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.
See remark at the start of the function declaration
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.
ditto
Cool work Saki! I like the performance gains. |
@nielsdos
BCMath is written in a "highly readable" manner, so I think there are quite a few places where your hack can be used. For example, in this PR change, I could use that hack for a loop that checks trailing zero while decrementing from fractional_end. result:
After your changes are committed, I'll try to commit them :) |
Since it became slow after making the release build, I will review the code again. |
c243421
to
cf252e7
Compare
cf252e7
to
4d6e4b1
Compare
There's no need to cram too many changes into this PR, so I'll leave it here for now and open another one 😄 |
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.
Overall looks good just needs some minor style adjustments / comment fixes
ext/bcmath/libbcmath/src/str2num.c
Outdated
@@ -57,77 +60,91 @@ bool bc_str2num(bc_num *num, char *str, size_t scale) | |||
while (*ptr == '0') { | |||
ptr++; | |||
} | |||
integer_ptr = ptr; |
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.
I'll only put this comment once as it applies to some other places too.
When refactoring code, you should merge the declaration and the assignment where possible.
I.e. make this char *integer_ptr = ptr;
. Or even const char *integer_ptr = ptr;
.
The reason to merge them is so it becomes clearer what the actual scope of the variable is, so it's not accidentally used when it should not be used (yet).
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.
Fixed 386cb7f
} | ||
fractional_ptr = decimal_point + 1; | ||
|
||
str_scale = fractional_end - fractional_ptr; |
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.
This may need a comment.
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.
Added 386cb7f
Co-authored-by: Niels Dossche <[email protected]>
I've added some comments in addition to the places mentioned. |
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.
Thx
I also have 2 patches for improving performance: the one I shared here already (that I might extend); and one that improves _bc_new_num_ex.
I'll open PRs after this is merged.
Just in case, I wait for CI to pass before merging. Thx :) |
Since freeing can deal with NULL, we can avoid calling bc_init_num and avoid resetting the number during parsing. Using benchmark from php#14076. Before: ``` 1.544440984726 2.0288550853729 2.092139005661 ``` After: ``` 1.5324399471283 1.9081380367279 2.065819978714 ```
Since freeing can deal with NULL, we can avoid calling bc_init_num and avoid resetting the number during parsing. Using benchmark from #14076. Before: ``` 1.544440984726 2.0288550853729 2.092139005661 ``` After: ``` 1.5324399471283 1.9081380367279 2.065819978714 ```
Using SIMD to accelerate the validation. Using the benchmark from php#14076. After: ``` 1.3504369258881 1.6206321716309 1.6845638751984 ``` Before: ``` 1.4750170707703 1.9039781093597 1.9632289409637 ```
Using SIMD to accelerate the validation. Using the benchmark from #14076. After: ``` 1.3504369258881 1.6206321716309 1.6845638751984 ``` Before: ``` 1.4750170707703 1.9039781093597 1.9632289409637 ```
bc_str2num
Very rough speed comparison
code (Increased loop count to 1 million):
Executed 3 times each
before:
after adjusting the order of structure members:
after refactor
bc_str2num
: