php - isset() vs strlen() - 快速/清晰的字符串长度计算

标签 php coding-style

我遇到了这段代码...

if(isset($string[255])) {
    // too long
}

isset() 比

快 6 到 40 倍
if(strlen($string) > 255) {
    // too long
}

isset() 的唯一缺点是代码不清楚 - 我们无法立即知道正在做什么(请参阅 pekka 的回答)。我们可以将 isset() 包装在一个函数中,即 strlt($string,255),但这样我们就失去了 isset() 的速度优势。

如何在保持代码可读性的同时使用更快的 isset() 函数?

编辑:测试显示速度http://codepad.org/ztYF0bE3

strlen() over 1000000 iterations 7.5193998813629
isset() over 1000000 iterations 0.29940009117126

EDIT2:这就是 isset() 更快的原因

$string = 'abcdefg';
var_dump($string[2]);
Output: string(1) “c”

$string = 'abcdefg';
if (isset($string[7])){
     echo $string[7].' found!';
  }else{
     echo 'No character found at position 7!';
}

这比使用 strlen() 更快,因为“……调用函数比使用语言结构更昂贵。” http://www.phpreferencebook.com/tips/use-isset-instead-of-strlen/

EDIT3:我总是被教导要对微优化感兴趣。可能是因为我是在计算机资源很少的时候受教的。我对它可能并不重要的想法持开放态度,答案中有一些很好的论据反对它。 我已经开始了一个新问题来探索这个... https://stackoverflow.com/questions/6983208/is-micro-optimisation-important-when-coding

最佳答案

好的,所以我运行了测试,因为我几乎不相信 isset() 方法更快,但是是的,而且相当快。 isset() 方法始终快 6 倍左右。

我尝试过使用不同大小的字符串并运行不同数量的迭代;比率保持不变,顺便说一下总运行长度(对于不同大小的字符串),因为 isset() 和 strlen() 都是 O(1) (这是有道理的 - isset 只需要在一个 C 数组,而 strlen() 只返回为字符串保留的大小计数)。

我在php源码中查了一下,我想我大概明白为什么了。 isset(),因为它不是函数而是语言结构,所以在 Zend VM 中有自己的操作码。因此,它不需要在函数表中查找,它可以做更专业的参数解析。代码在 zend_builtin_functions.c 中用于 strlen() 和 zend_compile.c 用于 isset(),供感兴趣的人引用。

为了将其与原始问题联系起来,从技术角度来看,我认为 isset() 方法没有任何问题;但是对于不习惯该成语的人来说,imo很难阅读。此外,isset() 方法将在时间上保持不变,而 strlen() 方法将在改变 PHP 中内置的函数数量时为 O(n)。这意味着,如果您构建 PHP 并在许多函数中静态编译,所有函数调用(包括 strlen())都会变慢;但 isset() 将是恒定的。然而,这种差异实际上可以忽略不计;我也不知道维护了多少个函数指针表,所以如果用户定义的函数也有影响。我似乎记得它们在不同的表中,因此与本案无关,但距离我上次真正处理这个已经有一段时间了。

对于其余部分,我认为 isset() 方法没有任何缺点。当不考虑像explode+count之类的故意复杂的方法时,我不知道获取字符串长度的其他方法。

最后,我还测试了您上面将 isset() 包装到函数中的建议。这甚至比 strlen() 方法慢,因为您需要另一个函数调用,因此需要另一个哈希表查找。额外参数的开销(用于检查的大小)可以忽略不计;就像不通过引用传递时字符串的复制一样。

关于php - isset() vs strlen() - 快速/清晰的字符串长度计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6955913/

相关文章:

php - TinyMCE 值在第一次提交时返回 NULL/无值

typescript - 干净的方式来尊重 DRY 的条件

PHP PDO 更新查询未在选择查询中更新

php - 涂鸦对 API 调用中的 "message"有何期待?

rest - 如何在现实世界的 Go 项目中分离路由、处理程序、第 3 方接口(interface)和业务逻辑

javascript选择样式标签?

python - Django 编码风格 : Should I be using class decorators here?

Java 注释 - 对象数组或 toString 值

php - 选择具有特定 where 过滤器 MYSQL 的最小值

Php Mysql - 获取之前的值自动增量并将其插入到另一列