当它不是内存,CPU或IO时,瓶颈是什么?

时间:2011-11-09 01:21:07

标签: php profiling

我有一个PHP类,它从MySQL数据库中选择有关文件的数据,在PHP中处理该数据,然后将最终数据输出到命令行。然后它移动到foreach循环中的下一个文件。 (后来我将这些数据插入到另一个表中......但现在这并不重要了)

我想尽快处理。

当我运行脚本并使用top或iostat监控我的系统时:

  • 我的cpus永远不会低于65%空闲(4核心EC2实例)
    • PHP脚本大约占45%
    • mysqld约占8%
  • 我的内存使用率从未超过~1.5GB(总共8GB的内存)
  • 磁盘IO很少

还有哪些瓶颈会阻止此进程更快地运行并使用可用的CPU和内存?

编辑1:

这不需要是一个程序过程,我设计它可以在必要时并行化处理。如果我可以加速一些,那么将它作为程序处理更简单。

我使用iostat -x 1监控磁盘I / O并且几乎没有。

我需要加快速度,因为它最终将用于处理数亿个文件,我希望它尽可能快,因为它是更大处理步骤的一部分。

6 个答案:

答案 0 :(得分:4)

嗯,可能因为一个PHP进程一次只能在一个核心上运行而你没有将系统加载到连续运行四个并发作业的程度

示例:如果PHP是唯一在该框上运行的东西,它本身就与每个“作业”的单个核心绑定,并且一次只有一个请求,我完全可以预期CPU负载大约为25尽管事实上它已经尽可能快地发展了。

当然,一旦该系统开始逐渐升级到连续运行四个PHP脚本的程度,您可能会发现CPU利用率更高。

在我的意见中,如果是实际的问题(例如无法跟上传入请求),您应该只担心性能问题。仅仅因为你希望它使用更多的CPU和/或内存资源而进行优化似乎是错误地看待它。我会让它尽可能快地运行,而不用担心实际使用的资源。


如果您希望尽可能快地处理数亿个文件(根据您的更新)并且PHP受核心约束,那么您应该考虑水平扩展。

换句话说,如果单个文件的处理是独立的,您可以简单地启动两个或三个PHP进程并让它们分别处理一个文件。这将更有可能让他们在不同的核心上运行。

如果需要,您甚至可以跨物理机进行扩展,但这可能会在数据库访问中引入网络延迟(除非DB也在所有计算机上复制)。

如果没有更多细节,我可以提供的选项大多是通用选项。

答案 1 :(得分:1)

你需要解决的第一个问题是“瓶颈”这个词,因为它意味着一切都没有。 它结合了这种形象,在机器似乎做的任何事情的流动中都有某种收缩,它必须像水一样穿过管道。

计算不是那样的。 我发现看一个非常简单,缓慢的计算机是如何工作的,这有助于Harry Porter's Relay Computer。 您可以以非常慢的时钟速率观察它,执行每条指令中的每一个小步骤,并在它开始下一步之前完成它们。 (现在,显然,现在的机器是多核,流水线,多级缓存,等等等等。这一切都很好,但这让你觉得计算就像流水,这会阻止你理解软件性能。)

将任何计算机和软件视为中继机器,除非是纳秒级,而不是秒级。 当计算机在程序中计算时,它正在一个接一个地执行指令。称之为“X”。 当程序想要向外部硬件读取或写入一些位时,它必须请求启动硬件,然后必须找到一种方法来消耗时间直到结果准备好。 称之为“y”。 它可能是一个空闲循环,或让另一个“线程”运行等等。

所以程序的执行看起来像是 XXXXXyyyyyyyXXXXXXXXyyyyyyy
如果那里的“y”比“X”更多,我们倾向于称它为“I / O界限”。 如果没有,我们可以称之为“计算限制”。 无论哪种方式,这只是花费的时间比例。

如果你说它是“内存限制”,那就像I / O一样,除了它可能是不同的外部硬件。 它仍然占整个连续时间线的一小部分。

现在,对于任何给定的任务,可以编写无限多的程序来执行此操作。其中一些将以比其他所有步骤更少的步骤完成。 当您想要表现时,您希望尽可能接近编写其中一个程序。 一种方法是找到你可以摆脱的“X”和“y”s ,并尽可能多地摆脱它。

现在,在一个线程中,如果你随机选择一个“X”或“y”,你怎么知道你是否可以摆脱它? 找出它的目的是什么! “X”或“y”表示程序执行顺序中的一个时刻,如果你查看当时程序的状态,并查看源代码,你就能弄清楚为什么那个时刻正在度过。 这样做几次。 一旦你看到两个时刻具有类似的绝对必要目的, 可能还有很多像他们一样,你找到了一些你可以摆脱的东西。 如果你这样做,程序将不再花时间。

这是性能调优this method背后的基本思想。 Here's an example where在多次迭代中使用了该方法来删除程序中花费的97%以上的时间。 并非所有程序都远离最佳。 (有些更远。) 许多程序只需要做一定数量的“X”或“y”,并且没有办法绕过它。 然而,通常非常令人惊讶的是,在其他完美的代码中你可以找到多少加速空间 - 提供 - 你忘记了“瓶颈”并寻找它正在做的步骤,随着时间的推移,可以删除或做得更好。

这很容易。

答案 2 :(得分:0)

我怀疑你花了大部分时间与MySQL沟通并阅读文件。你如何确定IO很少?与MySQL通信将通过网络进行,与直接内存访问相比,这是非常缓慢的。与阅读文件相同。

答案 3 :(得分:0)

看起来CPU是你的瓶颈。或者更确切地说,单个核心就是你的瓶颈。

如果其他三个内核空闲,单个内核的100%利用率将导致“25%的CPU利用率”。

您的数字与在单核上以100%运行的php脚本一致,其他三个核上的利用率为5%到10%。

答案 4 :(得分:0)

很抱歉复活旧帖子,但认为这可能有助于某人。

我遇到了类似的问题,它与命令行脚本有关,该脚本抛出了许多“通知”警告。这不知怎么导致它表现缓慢并且使用不到10%的cpu。此行为仅出现在从MacOS X迁移到Ubuntu,因为OSX中的默认设置似乎是为了抑制这些问题。一旦我修复了有问题的代码,它就会表现得更好,因为进程一直使用大约100%的cpu。

答案 5 :(得分:0)

正如另一个人所说的那样,很抱歉复活旧线程,但这可能对某人有所帮助。

我遇到了同样的问题:并行运行一堆进程,都使用MySQL。机器很慢,没有可识别的瓶颈:cpu,内存和磁盘。

事实证明,我的问题最可能的原因是MySQL内部线程大部分时间都挂在同一个信号量上。从vanilla MySQL 5.5切换到MariaDB 10.0解决了这个问题。

另外,为了确保我的机器始终以满负荷运行而不被淹没,我创建了一个Perl script raspawn.pl(在GitHub上)。

你可以阅读完整的悲伤故事here