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

2022-08-30 09:51:42

我遇到了这个代码...

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

编辑2:这就是为什么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/

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


答案 1

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

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

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

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

对于其余的,我没有看到isset()方法的任何缺点。我不知道还有其他方法可以获得字符串的长度,当不考虑故意复杂的字符串时,例如explode +count之类的东西。

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


答案 2

这方面的任何速度差异都是绝对没有后果的。它最多只有几毫秒。

使用任何对你和任何从事代码工作的人来说最容易阅读的样式 - 我个人会强烈投票支持第二个示例,因为与第一个示例不同,它使意图(检查字符串的长度)绝对清晰。


推荐