为啥 PHP 不对字符串使用内部智能字符串?

Posted

技术标签:

【中文标题】为啥 PHP 不对字符串使用内部智能字符串?【英文标题】:Why doesn't PHP use internal smart string for strings?为什么 PHP 不对字符串使用内部智能字符串? 【发布时间】:2015-12-14 21:26:53 【问题描述】:

php 有一个称为智能字符串 (smart_str?) 的内部数据结构,它们在其中存储长度和缓冲区大小。也就是说,分配比字符串长度更多的内存来提高连接性能。为什么这个数据结构不用于实际的 PHP 字符串?这不会导致更少的内存分配和更好的性能吗?

【问题讨论】:

我们说的是多少字节?大声笑 @AdamBuchananSmith 什么字节? 在 PHP 7 中,所有字符串都是zend_string 类型,分配和释放由zend_string_* 函数处理。因此,使所有字符串“智能”是微不足道的。我想这是一个深思熟虑的决定,那就是不“聪明”。 【参考方案1】:

普通的 PHP 字符串(自 PHP 7 起)由 zend_string 类型表示,它包括字符串的长度及其字符数据数组。 zend_strings 通常被分配以精确匹配字符数据(尽管对齐):它们不会留下位置来附加额外的字符。

smart_str 结构包括一个指向zend_string 的指针和一个分配大小。这一次,zend_string不会被精确分配。相反,分配将变得太大,因此可以附加额外的字符而无需进行昂贵的重新分配。

smart_str 的重新分配策略如下:首先,将分配总大小为 256 字节(减去 zend_string 标头,减去分配器开销)。如果超过这个大小,它将被重新分配到 4096 字节(减去开销)。之后,大小将以 4096 字节为增量增加。

现在,假设我们用smart_strings 替换所有字符串。这意味着即使是单个字符串也将具有 256 字节的最小分配大小。鉴于使用的大多数字符串都很小,这是不可接受的开销。

所以本质上,这是一个经典的性能/内存权衡。我们默认使用内存紧凑的表示,并在从中受益最多的情况下切换到更快但内存效率较低的表示,即大字符串由小部分构成的情况。

【讨论】:

当然可以,但是您仍然可以调整smart_str 以更好地满足普通 PHP 字符串处理的需要,对吧?从小尺寸开始,然后在每次连接发生时加倍。特别是因为字符串缓冲区不可能在 PHP 中实现(!)。尤其是因为内存比 CPU 周期更丰富。 @OlleHärstedt 是的,一旦开始存储容量,就有可能找到一些合理的分配策略。我在这里专门回答了 smart_str 。一种相对安全的做法是与分配器集成,并且(对于小型分配器)选择无论如何都会使用的下一个最大存储桶大小。通过一些技巧,甚至可以不引入额外的内存开销来存储容量(使用伪浮点编码)。这就是 HHVM 所做的 ;) 嗯,你有解释这个诡计的链接吗?听起来很有趣。 @OlleHärstedt 当然,这里是 cap 代码实现:lxr.php.net/xref/OTHER_IMPLEMENT/hiphop-vm/hphp/runtime/base/… PHP 没有额外内存开销的原因是我们可以安全地将哈希缓存缩小到 32 位,留下 32 位用于编码容量值。这是用于选择字符串容量的 HHVM 实现:lxr.php.net/xref/OTHER_IMPLEMENT/hiphop-vm/hphp/runtime/base/…

以上是关于为啥 PHP 不对字符串使用内部智能字符串?的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 解码内部的多个 xml 标签

javascript,innerHTML或者innerText获取的内容是否字符串?为啥和另外一个字符串相比结果不对

为啥PHP传递参数值为0时,empty判断参数为真

PHP将字符串编译为字节码而不对其进行评估

为啥在CMD中输入JAVA显示不是内部或外部命令,求大神指教

为啥我使用 PHP 的 $_SERVER 变量得到一个随机字符串作为 IP 地址?