Doing a cast like (int) $var
instead of the intval($var)
function is about 300% to 650% faster. I did some tests out of curiousity in #13317 and those are the results:
Running the Tests
Speed comparison (int)$val vs. intval($val) [System #1]
# INPUT (INT)$val INTVAL($val) RATIO ---------------------------------------------------------------------------- #0 42 : 0.068180 / 0.448819 658% #1 -42 : 0.067972 / 0.448907 660% #2 4.2 : 0.072348 / 0.450288 622% #3 '42' : 0.087305 / 0.469350 537% #4 '+42' : 0.087590 / 0.471153 537% #5 '-42' : 0.089154 / 0.469826 526% #6 34 : 0.068234 / 0.451035 661% #7 '042' : 0.089344 / 0.470391 526% #8 0x1A : 0.072989 / 0.451909 619% #9 '1e10' : 0.088196 / 0.469347 532% #10 26 : 0.068378 / 0.449884 657% #11 42000000 : 0.068770 / 0.449416 653% #12 2147483647 : 0.068927 / 0.448028 650% #13 2147483648 : 0.072599 / 0.450618 620% #14 4.2E+20 : 0.086305 / 0.467347 541% #15 '420000000000000000000' : 0.102120 / 0.484245 474% #16 array() : 0.092310 / 0.472185 511% #17 array('foo', 'bar') : 0.112644 / 0.494482 438%
Speed comparison (int)$val vs. intval($val) [System #2]
# INPUT (INT)$val INTVAL($val) RATIO ---------------------------------------------------------------------------- #0 42 : 0.045576 / 0.194759 427% #1 -42 : 0.042457 / 0.194273 457% #2 4.2 : 0.047853 / 0.196049 409% #3 '42' : 0.055792 / 0.209531 375% #4 '+42' : 0.055158 / 0.208236 377% #5 '-42' : 0.056604 / 0.209486 370% #6 34 : 0.042580 / 0.194606 457% #7 '042' : 0.056834 / 0.209276 368% #8 0x1A : 0.045320 / 0.196626 433% #9 '1e10' : 0.054923 / 0.209295 381% #10 26 : 0.042582 / 0.195295 458% #11 42000000 : 0.042673 / 0.194469 455% #12 2147483647 : 0.042560 / 0.194363 456% #13 2147483648 : 0.045553 / 0.197149 432% #14 4.2E+20 : 0.054069 / 0.206131 381% #15 '420000000000000000000' : 0.066170 / 0.218996 330% #16 array() : 0.057587 / 0.210010 364% #17 array('foo', 'bar') : 0.071908 / 0.224338 311%
This has been done with 100 000 iterations each. Both systems were running windows. The first one was with PHP 5.2.8 and weaker as the other with PHP 5.2.9 and more CPU, memory and hd-speed.
Comparison of results intval() and casting to integer
To proof that intval() and casting to integer reveal the exact same values, I did run another test as well:
# INPUT EXPECTED INTVAL() CAST RESULT ---------------------------------------------------------------------------- #0 42 : 42 / 42 / 42 pass. #1 -42 : -42 / -42 / -42 pass. #2 4.2 : 4 / 4 / 4 pass. #3 '42' : 42 / 42 / 42 pass. #4 '+42' : 42 / 42 / 42 pass. #5 '-42' : -42 / -42 / -42 pass. #6 34 : 34 / 34 / 34 pass. #7 '042' : 42 / 42 / 42 pass. #8 0x1A : 1410065408 / 1410065408 / 1410065408 pass. #9 '1e10' : 1 / 1 / 1 pass. #10 26 : 26 / 26 / 26 pass. #11 42000000 : 42000000 / 42000000 / 42000000 pass. #12 2147483647 : 2147483647 / 2147483647 / 2147483647 pass. #13 2147483648 : -2147483648 / -2147483648 / -2147483648 pass. #14 4.2E+20 : 0 / 0 / 0 pass. #15 '420000000000000000000' : 2147483647 / 2147483647 / 2147483647 pass. #16 array() : 0 / 0 / 0 pass. #17 array('foo', 'bar') : 1 / 1 / 1 pass.
Speed comparison settype() vs. intval() [System #1]
For comparison reasons I did run a test between settype() and intval() as well. The differences are not that big, but I’m not sure that the test actually is valid because it is not easy to test both functions directly against each other. Since I did run it I thought this is worth so share next to the data above:
# INPUT SETTYPE() INTVAL($val) RATIO ---------------------------------------------------------------------------- #0 42 : 0.533901 / 0.477519 89% #1 -42 : 0.533729 / 0.478345 89% #2 4.2 : 0.536932 / 0.480030 89% #3 '42' : 0.547209 / 0.503447 92% #4 '+42' : 0.553214 / 0.501764 90% #5 '-42' : 0.551974 / 0.503403 91% #6 34 : 0.532637 / 0.478039 89% #7 '042' : 0.552709 / 0.505796 91% #8 0x1A : 0.536864 / 0.481672 89% #9 '1e10' : 0.550352 / 0.506748 92% #10 26 : 0.537672 / 0.478947 89% #11 42000000 : 0.536360 / 0.478373 89% #12 2147483647 : 0.541348 / 0.490556 90% #13 2147483648 : 0.539018 / 0.486669 90% #14 4.2E+20 : 0.554357 / 0.499877 90% #15 '420000000000000000000' : 0.566189 / 0.522929 92% #16 array() : 0.549919 / 0.505488 91% #17 array('foo', 'bar') : 0.578893 / 0.527864 91%
Update:
I did run some tests for 0 + $var
as well because it’s some way to get a number as well. It’s not that type-safe but for comparison reasons I thought it’s worth to list as well while I’m at it:
Comparison of results intval() and 0 + $var
# INPUT EXPECTED INTVAL() 0+$VAR RESULT ---------------------------------------------------------------------------- #0 42 : 42 / 42 / 42 pass. #1 -42 : -42 / -42 / -42 pass. #2 4.2 : 4 / 4 / 4.2 different. #3 '42' : 42 / 42 / 42 pass. #4 '+42' : 42 / 42 / 42 pass. #5 '-42' : -42 / -42 / -42 pass. #6 042 : 34 / 34 / 34 pass. #7 '042' : 42 / 42 / 42 pass. #8 1e10 : 1410065408 / 1410065408 / 10000000000 different. #9 '1e10' : 1 / 1 / 10000000000 different. #10 0x1A : 26 / 26 / 26 pass. #11 42000000 : 42000000 / 42000000 / 42000000 pass. #12 2147483647 : 2147483647 / 2147483647 / 2147483647 pass. #13 2147483648 : -2147483648 / -2147483648 / 2147483648 different. #14 420000000000000000000 : 0 / 0 / 4.2E+20 different. #15 '420000000000000000000' : 2147483647 / 2147483647 / 4.2E+20 different. #16 array() : 0 / 0 / error. skipped. #17 array('foo', 'bar') : 1 / 1 / error. skipped.
Speed comparison (int)$val vs. 0 + $val [System #1]
And for the speed comparison. I only did run it on one test-system, I think it’s enough to show the picture:
# INPUT (INT)$val 0+$val RATIO ---------------------------------------------------------------------------- #0 42 : 0.068794 / 0.069249 100% #1 -42 : 0.074688 / 0.069155 92% #2 4.2 : 0.073207 / 0.069257 94% Note: different. #3 '42' : 0.086568 / 0.076261 88% #4 '+42' : 0.087230 / 0.080867 92% #5 '-42' : 0.090189 / 0.075923 84% #6 042 : 0.069072 / 0.069243 100% #7 '042' : 0.088535 / 0.082137 92% #8 1e10 : 0.072930 / 0.069512 95% Note: different. #9 '1e10' : 0.086942 / 0.082032 94% #10 0x1A : 0.068921 / 0.069365 100% #11 42000000 : 0.069203 / 0.069415 100% #12 2147483647 : 0.069109 / 0.069386 100% #13 2147483648 : 0.073053 / 0.069277 94% Note: different. #14 420000000000000000000 : 0.092318 / 0.069463 75% Note: different. #15 '420000000000000000000' : 0.105735 / 0.211617 200% Note: different. #16 array() : skipped. #17 array('foo', 'bar') : skipped.
Those one with the Note: different at the end are those where both functions do not return the same value (see previous test).
Conclusions
Cast. It’s handy and it’s not doing bad things. In fact it does exactly the same results as the intval() function while being faster. Both even do the same warning if I had seen that right.
Read On:
I’d expect intval() to be slower than a direct cast. A simple test script run through VLD shows one less operation. And the ops that are run are slightly different:
intval
———
0 ASSIGN
1 SEND_VAR
2 DO_FCALL
3 ASSIGN
4 RETURN
5* ZEND_HANDLE_EXCEPTION
cast
——-
0 ASSIGN
1 CAST
2 ASSIGN
3 RETURN
4* ZEND_HANDLE_EXCEPTION
I suspect that doing a single CAST is quite a bit faster than the combined SEND_VAR, DO_FCALL ops.
Nice listing. Can you try for
0 + $var
and maybe asettype()
call as well? I’ll update the article, because I did some measurements for0 + $var
. I got that one from the question / answer from stackoverflow.settype() increases the opcount to 7
0 ASSIGN
1 SEND_REF
2 SEND_VAL
3 DO_FCALL
4 ASSIGN
5 RETURN
6* ZEND_HANDLE_EXCEPTION
The 0 + $var is 5 ops
0 ASSIGN
1 ADD
2 ASSIGN
3 RETURN
4* ZEND_HANDLE_EXCEPTION
Great! I always had the feeling that cast is something nice to ensure a certain type and do things straight. Looks like it’s the same performance wise. So a nice win-win.
Pingback: 網站製作學習誌 » [Web] 連結分享
Pingback: PHP: Compare vs. Calculating | hakre on wordpress
Really really awesome post 🙂 I wonder where all of that speed is going with intval()… It must do something funky behind the scenes.
Any chance you could post up a link to the code you used to run these benchmarks?
Thanks!
Sam
Well, I do not know if this is really awesome but I had some fun doing so. Where the speed is going is pretty well shown in Jospeh Scott’s comment.
For the tests sourcecode, this is what I discovered on my harddisk:
Excellent benchmark! No doubt I’ll be using casting from now on.
The “0+” is lame. And not consistent. What if you need to cast string, you’d use a “”+”? And array? “$array+”??? Lol. And it’s still slower after all.
One thing to be careful about though is precision. Check this out:
<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>
Yes, that’s by nature of computers as machines are limited about numbers compared to what we as humans can imagine and calculate upon. From Warning: Floating point precision:
I would like to change string to number with decimal such as “0.001”. Which function I should use? (cannot use intval() because it returns “integer”, not “decimal”)
Casting to string can do the job for you:
See String conversion to numbers (PHP Manual) and Floating point numbers (PHP Manual). Further more: PHP String to Float (Stack Overflow).
Intval() probably is slower because it’s a function call, and we know that function calls cost time…
Pingback: Zajímavé články o WordPressu (v angličtině) « Fórum podpory WordPressu
Thanks for this. Exactly what i needed to prove a hunch. Complete and in depth. I really enjoyed knowing that after viewing this it was no longer a shot in the dark.
You’re welcome. Thanks for the feedback.
Pingback: PHP: Casten vs intval() | xi-intersection
Great. I got some brief one from http://www.techflirt.com/php/php-type-casting.html
Pingback: Кастинг типов в PHP – Php User Blog