bcmath-extended
bcmath-extended copied to clipboard
Performance
Please provide the following details.
- Operating System: Linux
- PHP Version: 8.1.14
Performance implications
I am using BC::roundDown() on my responses to always round down specific fields to a specific decimal place. Now let's say we have in a for me realistic scenario of 16000 BC::roundDown() operations on my response. It's fine if they are all raw and not already rounded. But what if they are already? In my case the values coming cache and other sources are already rounded to 2 decimals. So why should I run BC::roundDown() again, but at the same time I can not be sure that the source always gives me formatted values?
I did 3 different solutions with 10 million values to be round:
- Explode a string and check if number of chars after the dot is <= required decimals
- Use
preg_match - Just run
BC::roundDownas we currently do:
Simple validation with explode takes 2.6 seconds to run. Using preg_match takes 0.8 seconds to run Just do what we do now and just run BC::roundDown takes 76 seconds to run
So projected on my current project, I can drop another 10 ms at least from the response generation. And in total reduce CPU time if we can add this simple validation to the library where it makes sense.
Code used for the test
$case = 2;
$testString = '1234.123';
$start = microtime(true);
for ($i = 0; $i < 16000; ++$i) {
switch ($case) {
case 0:
$elements = explode('.', $testString);
$elementsCount = count($elements);
if ($elementsCount === 1) {
continue 2;
}
if (strlen(end($elements)) <= 2) {
// Match
}
break;
case 1:
if (preg_match("/\d+(\.\d{1,2})?$/", $testString)) {
// Match
}
break;
case 2:
BC::roundDown($testString, 2);
break;
}
}
dump(microtime(true) - $start);
Besides that further optimizations are:
Do a simple string cutoff if you roundDown a positive number or roundUp a negative number.
Indeed this are cool optimization, I need to test it
The above comment is phishing and it should be removed.
@TheLevti, after looking at the BC::roundDown method, its approach is more complicated than other cases you mention.
The approach are about the BC::roundDown method is as follows:
- Calling the static::convertScientificNotationToString method.
- Calling the static::parseNumber method.
After checking above of these methods, the static::parseNumber takes about 0.27 seconds.
The case 0 takes about 0.00523084 seconds. and the case 1 takes about 0.002723818 seconds.
@TheLevti, after looking at the BC::roundDown method, its approach is more complicated than other cases you mention.
The approach are about the
BC::roundDownmethod is as follows:
- Calling the static::convertScientificNotationToString method.
- Calling the static::parseNumber method.
After checking above of these methods, the
static::parseNumbertakes about0.27seconds. The case 0 takes about0.00523084seconds. and the case 1 takes about0.002723818seconds.
I don't suggest to completely replace it, just for specific cases we should take shortcuts.
I am not quite sure what you conclude in the last comment :)
When you do several thousand BC operations per second, it is heavily noticeable how much CPU is required. Little optimizations showed huge differences.
Unfortunately I did not have time to properly contribute to this issue code wise. But if you agree, for sure I can find some time to contribute.
@TheLevti, thanks for your reply. I concluded that we might use other approaches to refactor the BC::roundDown method and let rounding number efficiency and optimization.