Original Post: PHP: Casting vs. intval()
By Hakre, hakre.wordpress.com, May 13th, 2010
Translated by Crisp
在 PHP 中,使用 (int)$var
方式进行类型转换比使用 intval($var)
函数方式快 400% 到 650%。
# | 输入 | (INT)$val | INTVAL($val) | 比率 |
---|---|---|---|---|
#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% |
# | 输入 | (INT)$val | INTVAL($val) | 比率 |
---|---|---|---|---|
#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% |
这组测试每个项目进行了 100000 次循环。两个测试都在 Windows 上运行。系统 #1 使用的是 PHP 5.2.8,而系统 #2 使用 PHP 5.2.9 并且有更高的 CPU、内存和硬盘速度。
为了证明 intval()
和 int
得到同样的值,我进行了另一个测试:
# | 输入 | 期待结果 | INTVAL($val) | (INT)$val | 结果 |
---|---|---|---|---|---|
#0 | 42 | : 42 | / 42 | / 42 | 通过 |
#1 | -42 | : -42 | / -42 | / -42 | 通过 |
#2 | 4.2 | : 4 | / 4 | / 4 | 通过 |
#3 | ‘42’ | : 42 | / 42 | / 42 | 通过 |
#4 | ‘+42’ | : 42 | / 42 | / 42 | 通过 |
#5 | ‘-42’ | : -42 | / -42 | / -42 | 通过 |
#6 | 34 | : 34 | / 34 | / 34 | 通过 |
#7 | ‘042’ | : 42 | / 42 | / 42 | 通过 |
#8 | 0x1A | : 1410065408 | / 1410065408 | / 1410065408 | 通过 |
#9 | ‘1e10’ | : 1 | / 1 | / 1 | 通过 |
#10 | 26 | : 26 | / 26 | / 26 | 通过 |
#11 | 42000000 | : 42000000 | / 42000000 | / 42000000 | 通过 |
#12 | 2147483647 | : 2147483647 | / 2147483647 | / 2147483647 | 通过 |
#13 | 2147483648 | : -2147483648 | / -2147483648 | / -2147483648 | 通过 |
#14 | 4.2E+20 | : 0 | / 0 | / 0 | 通过 |
#15 | ‘420000000000000000000’ | : 2147483647 | / 2147483647 | / 2147483647 | 通过 |
#16 | array() | : 0 | / 0 | / 0 | 通过 |
#17 | array(‘foo’, ‘bar’) | : 1 | / 1 | / 1 | 通过 |
用于对比,我还进行了 settype()
和 intval()
速度测试。
两者的差别并不大,但我不确定这个测试是否合理,因为并不容易直接对这个函数进行测试。既然已经跑了这个测试,我认为值得把结果同前面的数据一起分享出来。
# | 输入 | SETTYPE($val) | INTVAL($val) | 比率 |
---|---|---|---|---|
#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% |
更新:
我进行了一些关于 0 + $var
的测试,因为这也是一种获得数字的方式。
这种方法没那么”类型安全”,不过作为对比,我认为有必要一起列出来:
# | 输入 | 期待结果 | INTVAL($val) | 0+$VAR | 结果 |
---|---|---|---|---|---|
#0 | 42 | : 42 | / 42 | / 42 | 通过 |
#1 | -42 | : -42 | / -42 | / -42 | 通过 |
#2 | 4.2 | : 4 | / 4 | / 4.2 | 不通过 |
#3 | ‘42’ | : 42 | / 42 | / 42 | 通过 |
#4 | ‘+42’ | : 42 | / 42 | / 42 | 通过 |
#5 | ‘-42’ | : -42 | / -42 | / -42 | 通过 |
#6 | 042 | : 34 | / 34 | / 34 | 通过 |
#7 | ‘042’ | : 42 | / 42 | / 42 | 通过 |
#8 | 1e10 | : 1410065408 | / 1410065408 | / 10000000000 | 不通过 |
#9 | ‘1e10’ | : 1 | / 1 | / 10000000000 | 不通过 |
#10 | 0x1A | : 26 | / 26 | / 26 | 通过 |
#11 | 42000000 | : 42000000 | / 42000000 | / 42000000 | 通过 |
#12 | 2147483647 | : 2147483647 | / 2147483647 | / 2147483647 | 通过 |
#13 | 2147483648 | : -2147483648 | / -2147483648 | / 2147483648 | 不通过 |
#14 | 420000000000000000000 | : 0 | / 0 | / 4.2E+20 | 不通过 |
#15 | ‘420000000000000000000’ | : 2147483647 | / 2147483647 | / 4.2E+20 | 不通过 |
#16 | array() | : 0 | / 0 | / 报错 | 跳过 |
#17 | array(‘foo’, ‘bar’) | : 1 | / 1 | / 报错 | 跳过 |
# | 输入 | (INT)$val | 0+$val | 比率 |
---|---|---|---|---|
#0 | 42 | : 0.068794 | / 0.069249 | 100% |
#1 | -42 | : 0.074688 | / 0.069155 | 92% |
#2 | 4.2 | : 0.073207 | / 0.069257 | 94%* |
#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%* |
#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%* |
#14 | 420000000000000000000 | : 0.092318 | / 0.069463 | 75%* |
#15 | ‘420000000000000000000’ | : 0.105735 | / 0.211617 | 200%* |
#16 | array() | : 跳过 | ||
#17 | array(‘foo’, ‘bar’) | : 跳过 |
*: 在上一个测试中,结果未通过
使用 (int) 类型转换,便捷而且没有负面效果。 事实上,它在速度快的同时,还和 intval() 函数有完全一样的结果。 两者甚至还会有同样的 warning 信息。
对于作者的结论,网友 Joseph Scott 对 OPCODE 进行了分析,解释了其深层原因。
0 ASSIGN
1 SEND_VAR
2 DO_FCALL
3 ASSIGN
4 RETURN
5* ZEND_HANDLE_EXCEPTION
0 ASSIGN
1 CAST
2 ASSIGN
3 RETURN
4* ZEND_HANDLE_EXCEPTION
int
比 intval()
快3-6倍。SEND_VAR
和 DO_FCALL
操作,是导致 int
比 intval()
快很多的原因。