php - 在 PHP 中进行类型检查的更快方法是什么? gettype() 或多个 is_*()

标签 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
    }
}

方法二 :
function doSomething2($param) {
    if (is_string($param)) {
        // do something
    }
    else if (is_int($param)) {
        // do something
    }
    else if (is_array($param)) {
        // do something
    }
}
  • 据我所知,从测试的角度来看,这两种方法在功能上是等效的,但是由于 PHP 有很多问题,我不得不问,如果我偏爱一种方法而不是另一种方法,我是否会错过什么?
  • 从性能的角度来看,因为 PHP function calls are expensive 说方法一比二快是正确的吗? ?或者是 gettype()比个人更昂贵的操作is_*()职能?
  • 是否有任何关于此的编码习惯用法/风格指南?

  • 更新
    从我使用 PHP 7.0.4 的基准测试来看,一百万次迭代 doSomething2()耗时 159 毫秒,略少于 doSomething1() 的一半时间在 315 毫秒。这与传入的是字符串(第一次检查)还是数组(最后一次检查)无关。这似乎表明 gettype()确实是一个昂贵的操作,比使用 is_*() 的多个函数调用更昂贵.

    任何对这可能发生的原因有更深入了解的人,都非常感谢您的帮助。

    最佳答案

    让我们比较 gettype 的 C 代码和 is_string职能。
    gettype :

    PHP_FUNCTION(gettype)
    {
        zval *arg;
        zend_string *type;
    
        ZEND_PARSE_PARAMETERS_START(1, 1)
            Z_PARAM_ZVAL(arg)
        ZEND_PARSE_PARAMETERS_END();
    
        type = zend_zval_get_type(arg);
        if (EXPECTED(type)) {
            RETURN_INTERNED_STR(type);
        } else {
            RETURN_STRING("unknown type");
        }
    }
    

    因此,它创建字符串 type并通过调用函数 zend_zval_get_type 的结果填充它,即:
    ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
    {
        switch (Z_TYPE_P(arg)) {
            case IS_NULL:
                return ZSTR_KNOWN(ZEND_STR_NULL);
            case IS_FALSE:
            case IS_TRUE:
                return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
            case IS_LONG:
                return ZSTR_KNOWN(ZEND_STR_INTEGER);
            case IS_DOUBLE:
                return ZSTR_KNOWN(ZEND_STR_DOUBLE);
            case IS_STRING:
                return ZSTR_KNOWN(ZEND_STR_STRING);
            case IS_ARRAY:
                return ZSTR_KNOWN(ZEND_STR_ARRAY);
            case IS_OBJECT:
                return ZSTR_KNOWN(ZEND_STR_OBJECT);
            case IS_RESOURCE:
                if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
                    return ZSTR_KNOWN(ZEND_STR_RESOURCE);
                } else {
                    return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
                }
            default:
                return NULL;
        }
    }
    

    我们比较一下is_string , 例如:
    PHP_FUNCTION(is_string)
    {
        php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);
    }
    

    转至 php_is_type :
    static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
    {
        zval *arg;
    
        ZEND_PARSE_PARAMETERS_START(1, 1)
            Z_PARAM_ZVAL(arg)
        ZEND_PARSE_PARAMETERS_END();
    
        if (Z_TYPE_P(arg) == type) {
            if (type == IS_RESOURCE) {
                const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
                if (!type_name) {
                    RETURN_FALSE;
                }
            }
            RETURN_TRUE;
        } else {
            RETURN_FALSE;
        }
    }
    

    所以,这些方法的核心逻辑是完全一样的——PHP使用Z_TYPE_P检测变量的类型。

    但在 gettype 的情况下它还为结果创建额外的字符串并用常量字符串填充它,而不是在 is_* 的情况下只返回 bool 值 TRUE 或 FALSE|职能。
    所以,绝对是is_*功能更快:)

    关于php - 在 PHP 中进行类型检查的更快方法是什么? gettype() 或多个 is_*(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36494054/

    相关文章:

    PHP:正则表达式从字符串中替换除字母数字字符之外的所有内容

    performance - R中更快的比例表

    multithreading - Doxygen 很慢

    .net - 为什么 DateTime.Now.Year 是 int 而不是 ushort

    php - php 中的 Linux uptime 命令不显示任何内容

    php - 在 Laravel 7 Scheduler 上执行服务器命令

    jquery - 使用媒体查询或创建 JQuery 函数来添加少量 CSS 会更好吗?

    python - 序列化 `numpy.dtype` 对象 : human readable

    types - ReasonML签名不匹配

    php - 如何在 Laravel 5 中的类之间共享作用域