Hi,

> For the record, I was very excited to see your proposal and the work you've 
> done. 

Thanks! :)

> I'm not a PHP dev so I can't comment on the patch, maybe there might
> be a performance concern?

The new algorithm is slightly slower in most of the cases and quite a
bit slower if strings have to be used in order to ensure correctness.
The following table shows the performance comparison of the algorithm
when compiling 5.3 with gcc 4.1.2 on Gentoo Linux with and without
optimization activated:

+----+----+-----------------------+-----------------------+
|    |    | without patch         | with patch            |
| st | pr | -O0 -ggdb | -O2       | -O0 -ggdb | -O2       |
+----+----+-----------+-----------+-----------+-----------+
|  - |  X |  6.427930 |  3.151313 |  7.107897 |  3.581429 |
|  X |  X |  6.485305 |  3.197008 | 26.423409 | 15.571503 |
|  X |  - |  6.318853 |  3.124304 | 11.926427 |  6.910457 |
|  - |  - |  6.100793 |  2.850991 |  6.636300 |  2.926919 |
| precov. |  5.432411 |  2.382959 |  5.524717 |  2.382117 |
+----+----+-----------+-----------+-----------+-----------+

Times are in seconds, script was basically the following:

$start = microtime(true);
for ($i = 0; $i < 5000000; $i++) $ret = round (/*number*/, /*prec*/);
$end = microtime(true);
printf("%.6f\n", $end - $start);

Explanations for the left columns:

st: Uses to-string-and-back conversion to ensure correctness (the case
when |places| > 22)

pr: Uses prerounding to precision to ensure correctness (see RFC for
details)

precov: Precision overflow, i.e. rounding 12345.123456789012345 to more
than 10 places precision (which is the max. that doubles can represent)

The most commen case by far would be the first one (things such as
round(12.245, 2)), the cases where string-conversion is used are
probably extremely rare (remember, |second parameter of round| must be >
22).

I used the following numbers to test the combinations:

-st +pr: round (0.116, 2)
+st +pr: round (0.000000000000000000000000000000116, 32)
+st -pr: round (0.000000000000000000000000000000005, 30)
-st -pr: round (0.005, 0)
precov.: round (1, 30)

As you can see, the cases which don't to string-and-back conversion are
not problematic: There's basically no difference for the precision
overflow case, the case with prerounding is slightly slower and the case
without prerounding is actually slightly faster when compiler
optimizations are enabled (this is due to the fact that the 10^places
was optimized in my patch). So the most common cases basically don't
matter much at all.

The only potential problems are the cases where the second parameter of
the round() function is larger than 22 or smaller than -22. In that
case, the new algorithm is quite a bit slower than the old one (nearly
factor 5 for all numbers that won't become 0 after rounding). But these
are edge cases which won't happen that often and if people actually have
these numbers they are probably far more interested in correctness than
in performance [see for example var_dump(2e-23 - round(2e-23,23));].

---------------------------- snip ----------------------------------

@internals: Anyway, since nobody of the core devs seems to be interested
in this topic, is there any objection to me committing this patch to HEAD?

@Johannes, @Lukas: Should there be a decision for an alpha3 release of
PHP 5.3 due to the namespace discussion, is there any objection to me
committing this patch to PHP_5_3? Should there be directly a beta1
release, any objections against this patch in 5.3.1? Or, even though it
is a rewrite of the round() function, may this even qualify as a bugfix,
since the previous behaviour was erroneous (see for example
<http://bugs.php.net/bug.php?id=42294> and my RFC)?

Regards,
Christian

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to