lig*_*ght 5 php performance types dynamic-typing
在动态类型的 PHP 中,我们可以创建可以接受多种数据类型作为参数的函数。然后我们可以根据变量的类型对数据进行操作。有两种方法可以做到这一点:
方法一:
function doSomething1($param) {
$type = gettype($param);
if ($type === 'string') {
// do something
}
else if ($type === 'integer') {
// do something
}
else if ($type === 'array') {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
方法二:
function doSomething2($param) {
if (is_string($param)) {
// do something
}
else if (is_int($param)) {
// do something
}
else if (is_array($param)) {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,从测试的角度来看,这两种方法在功能上是等效的,但是由于 PHP 有很多问题,我不得不问,如果我偏爱一种方法而不是另一种方法,我是否会错过什么?
从性能的角度来看,因为PHP 函数调用很昂贵,所以说一种方法比两种方法快是正确的吗?或者是gettype()比单个is_*()功能更昂贵的操作?
是否有任何关于此的编码习惯用法/风格指南?
更新
从我使用 PHP 7.0.4 的基准测试来看,一百万次迭代doSomething2()需要 159 毫秒,比doSomething1()315 毫秒的时间略少一半。这与传入的是字符串(第一次检查)还是数组(最后一次检查)无关。这似乎表明这gettype() 确实是一个昂贵的操作,并且比使用is_*().
任何对这可能发生的原因有更深入了解的人,都非常感谢您的帮助。
让我们比较一下 C 代码gettype和 的C 代码is_string函数的 C 代码。
gettype:
PHP_FUNCTION(gettype)\n{\n zval *arg;\n zend_string *type;\n\n ZEND_PARSE_PARAMETERS_START(1, 1)\n Z_PARAM_ZVAL(arg)\n ZEND_PARSE_PARAMETERS_END();\n\n type = zend_zval_get_type(arg);\n if (EXPECTED(type)) {\n RETURN_INTERNED_STR(type);\n } else {\n RETURN_STRING("unknown type");\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n因此,它创建字符串type并通过调用函数的结果填充它zend_zval_get_type,即:
ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */\n{\n switch (Z_TYPE_P(arg)) {\n case IS_NULL:\n return ZSTR_KNOWN(ZEND_STR_NULL);\n case IS_FALSE:\n case IS_TRUE:\n return ZSTR_KNOWN(ZEND_STR_BOOLEAN);\n case IS_LONG:\n return ZSTR_KNOWN(ZEND_STR_INTEGER);\n case IS_DOUBLE:\n return ZSTR_KNOWN(ZEND_STR_DOUBLE);\n case IS_STRING:\n return ZSTR_KNOWN(ZEND_STR_STRING);\n case IS_ARRAY:\n return ZSTR_KNOWN(ZEND_STR_ARRAY);\n case IS_OBJECT:\n return ZSTR_KNOWN(ZEND_STR_OBJECT);\n case IS_RESOURCE:\n if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {\n return ZSTR_KNOWN(ZEND_STR_RESOURCE);\n } else {\n return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);\n }\n default:\n return NULL;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我们来比较一下is_string,例如:
PHP_FUNCTION(is_string)\n{\n php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n去php_is_type:
static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)\n{\n zval *arg;\n\n ZEND_PARSE_PARAMETERS_START(1, 1)\n Z_PARAM_ZVAL(arg)\n ZEND_PARSE_PARAMETERS_END();\n\n if (Z_TYPE_P(arg) == type) {\n if (type == IS_RESOURCE) {\n const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));\n if (!type_name) {\n RETURN_FALSE;\n }\n }\n RETURN_TRUE;\n } else {\n RETURN_FALSE;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n所以,这些方法的核心逻辑与 PHP 使用的 \xe2\x80\x93 完全相同Z_TYPE_P所以,这些方法的核心逻辑与 PHP 用于检测变量类型的
但在这种情况下,gettype它还会为结果创建额外的字符串,并用常量字符串填充它,而不是在is_*函数的情况下仅返回布尔值 TRUE 或 FALSE。 \n所以,绝对is_*函数肯定更快:)
| 归档时间: |
|
| 查看次数: |
2029 次 |
| 最近记录: |