最近,我的 php 应用程序尝试使用一万多行 CSV 数据执行一些操作,但遇到了一些严重的性能问题。 基本上我有大约十个函数,由不同的 preg_match/preg_replace 操作组成,这些操作处理解析的 csv 数据的每一行的一列(NLP DateParser、各种字符串修改内容、来自 html 源的图像识别等)。
因为我正在达到脚本处理速度非常慢(50 到 120 秒之间)以及内存问题(过于复杂的对象)的范围,现在是时候进行一些性能改进了;)
所以我想到了 pthreads,它允许在 php 脚本中使用多线程。但我不太确定这是否对我的情况有帮助,或者只是产生比它解决的更多的性能问题(通过线程处理的开销):
我的想法是循环遍历所有一万行,并为每个列处理步骤启动一个线程(10k 行 + 10 列 = 10k * 10 = 100.000 个线程)。您认为这会带来性能提升吗? 或者我应该将 csv 数据分割成 block (假设 200 行),这些 block 将在单独的线程中处理(10k 行/200 block = 50 个线程)?
我会附上一张由我分析的 php 脚本组成的图像,您可以在其中看到哪些函数消耗了很多时间,但遗憾的是我没有足够的声誉点:/
并行处理有潜力吗?我可以直接从不同的线程向同一个对象添加属性,还是必须先同步(因此等待线程完成)?是否可以在多个线程中读取同一文件(第一百行线程 1,第二百行在线程 2 等),并在所有处理步骤结束时构建一个包含所有行的大对象?
我希望我糟糕的英语不会妨碍你理解我的想法和问题......
感谢您的建议!
mfuesslin
编辑:我不确定瓶颈:猜测最大的瓶颈是处理所有 csv 数据产生的大对象...Profiler 引起了我对一些冗余 foreach 循环的注意我可以忽略这一点。 但主要问题是我必须处理的数据量。所有处理函数都不需要那么多时间(但是如果你连续处理 10k...)。
使用内存数据库而不是 csv 进行操作的想法很好 - 将尝试一下。
preg_* 函数不能用 str_* 函数替换,因为我需要模式识别。
我还将尝试 Gearman 并尝试将每个数据处理步骤分离到各个作业中。
PHP 版本为 5.6.10,启用了 opcache。
最佳答案
听起来你想拿出一把非常大的枪。我不确定 pthreads 是否能解决所有问题。我不会详细介绍如何应用pthreads,因为这里发生了很多事情,而且似乎现有的解决方案还有一些改进的空间。
- 瓶颈到底在哪里?您是否分析了代码并解决了瓶颈?
- CSV
- 也许您可以删除它并将 CSV 数据导入到数据库中?
- 例如,使用 SQLite 内存数据库进行处理怎么样
- 您是否通过使用分块解析来降低 CSV 解析器的内存占用?
- 您正在使用
preg_*()
函数:尝试将其替换为字符串函数 - 将数据处理职能拆分为明确定义的单独工作
- 使用作业/队列系统进行处理,例如
- 吉尔曼 ( examples )
- RabbitMQ (worker queue)
- 你的 PHP 怎么样?升级到5.6? opcache 启用了吗?
关于PHP + pthreads : Build one big object - parallel-processing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30954216/