【问题标题】:PHP does modifying strings copy of update itPHP确实修改了更新它的字符串副本
【发布时间】:2014-06-09 09:57:38
【问题描述】:

我正在研究一个脚本,尽可能多地进行优化,甚至是微优化,但幸运的是这个问题并没有围绕这些方法的必要性,更多的是对 PHP 正在做什么的理解。

$sql = rtrim($sql, ',');

运行此行时,我想知道在内部返回的值是新字符串(即修改后的副本)还是内存中的相同值,但已更新。

如果这条线看起来像这样:

$sql2 = rtrim($sql1, ',');

那我就不会问了,但是因为它是对同一个变量的修改,我想知道 PHP 是用修改后的副本覆盖它,还是更新内存中的相同值。

出于性能原因,我需要在尽可能短的时间内将相同的操作运行数百万次,这就是为什么我非常着迷于每一个微小的细节。

这个问题不只是针对上面的示例,而是针对一般的字符串操作。

【问题讨论】:

  • 一个函数有一个不是引用的返回值,所以它几乎肯定是一个新变量。但真正的问题是你为什么要编写 sql 字符串? =)。从上面暗示你的 sql 很可能是不安全/可利用的。或者:为什么重要?无论答案如何,它都不会改变您的代码或性能。如果您真的对代码性能分析感兴趣,不要浪费时间优化需要 0.001% 执行时间的东西。如果代码已经被分析并且你正在寻找最后几个 m% - 表明情况就是这样。
  • 正在创建的 sql 稍后会在准备好的语句中使用。它是动态的原因是因为列是动态的。 0.001% 也很重要,因为它和脚本中的所有其他内容都将被循环。另外 1 mill 操作是小规模的,源是一个 200MB 的文件,所以大约 1 mill(行),但文件可以是几个 GB。
  • 你意识到帮助你优化你正在做的整个操作会更容易,而不是告诉你如何改进每件事的 0.0001%?根据我所读到的内容,我可以肯定地声称您很可能做错了很多事情,并且在优化您所要求的内容方面所获得的收益与努力是微不足道的。
  • PHP 在内部创建一个包含函数调用结果的新内存位置,然后将其分配给变量 $sql,释放旧值使用的内存;但这不是你应该尝试优化的东西......如果你真的需要知道它在做什么,请使用 VLD
  • 为什么很难解释优化内存中的字符串副本并不重要,你的算法才是。您正在努力优化性能,但您忽略了这样一个事实,即您优化的是最便宜的操作之一 - 从一个内存位置复制到另一个内存位置 - 它非常快。即使有数百万次迭代,它也不会累加。这无关紧要,您的时间将被浪费。你应该关注的是优化你的整个算法和文件,而不是字符串复制。

标签: php string performance pointers


【解决方案1】:

回答您的具体问题:字符串存储在称为 ZVAL 的内部结构中,并且 ZVAL 执行惰性复制,即执行复制引用相同的 ZVAL 并增加其引用计数。更新字符串会减少 ZVAL 上的引用计数(当计数为零时,垃圾会收集字符串)。更新时,会创建一个指向新值的新 ZVAL。

现在讨论支持这个问题的普遍误解:

出于性能原因,我需要在尽可能短的时间内运行相同的操作数百万次,这就是为什么我非常关注每一个微小的细节。

bubble sort 是 O(N²)。一个聪明的冒泡排序仍然是 O(N²)。对算法的简单更改可以让您降低到 O(N logN)。道德:算法优化带来巨大收益;微优化很少这样做,并且通常会适得其反,因为它们会创建无法维护的代码。

在 SQL 优化的情况下,用正确索引(连接和)单个语句替换语句循环可以在运行时节省一个数量级。

用数组函数调用替换 PHP for 循环也可以这样做。

【讨论】:

  • 这很好地解释了它。关于您提到的 SQL 优化,这些过程是插入。从文件中读取(做一些处理)然后插入解释的行。 5000 行 = 1 个查询,包含 5000 个插入。我现在的代码非常优化。现在唯一的问题是 mysql 服务器的性能和 php 在 165k 插入时内存不足,但我可以通过某种分布式工作负载来解决这个问题。谢谢你的解释。
  • 插入有每个 stmt 和每行的开销,因此将它们批处理是有意义的,但是随着批量大小的增加,回报会迅速减少。如果您以 10K 的速度进行批处理,那么只要您在每个批处理之后对变量进行解析(例如 undef 或重用),就不会耗尽内存。优化散装装载本身就是一个主题。例如。禁用插入周围的索引,因为索引更新在批处理中更有效。假脱机到 tmp 文件并执行 LOAD DATA 可能会更好。
猜你喜欢
  • 1970-01-01
  • 2016-07-07
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多