在一个PHP流程中,实现某些PHP流程的执行和结果的收集存在哪种设计模式?
背景
我在PHP中有很多大树(> 10000条)并且必须对它进行递归检查。我想减少执行时间。
答案 0 :(得分:11)
从您的php脚本中,您可以启动另一个脚本(使用exec
)来进行处理。将状态更新保存在文本文件中,然后由父线程定期读取。
注意:为避免php等待exec
'脚本完成,请将输出传递给文件:
exec('/path/to/file.php | output.log');
或者,您可以使用PCNTL函数分叉脚本。这使用一个php脚本,在分叉时可以检测它是父节点还是子节点并相应地操作。有一些函数可以发送/接收信号,以便在父/子之间进行通信,或者让子日志记录到文件中,父文件从该文件中读取。
从pcntl_fork手册页:
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
// we are the parent
pcntl_wait($status); //Protect against Zombie children
} else {
// we are the child
}
答案 1 :(得分:9)
如果您的目标是最短的时间 - 解决方案很容易描述,但实现起来并不那么简单。
您需要找到一种模式来划分工作(在这方面,您不会在问题中提供太多信息)。
然后使用一个forks个孩子完成工作的主过程。通常,您使用的流程总数应在n
和2n
之间,其中n
是计算机拥有的核心数。
假设此数据将存储在文件中,您可以考虑使用非阻塞IO来最大化吞吐量。不这样做会使您的大部分进程花费时间等待磁盘。 PHP有stream_select()
可能对您有所帮助。请注意,使用它并非易事。
如果您决定不使用select
- 增加进程数可能会有所帮助。
关于pcntl
函数:我和他们一起写了一个deamon(一个正确的,有分叉,更改会话ID,正在运行的用户等等),它是最可靠的一个我写过的软件。因为它为每个任务生成工作者,即使其中一个任务中存在错误,也不会影响其他任务。
答案 2 :(得分:4)
这可能是考虑使用message queue的好时机,即使您在一台计算机上运行它也是如此。
答案 3 :(得分:3)
您可以使用更高效的数据结构,例如btree。我在Java中使用过一次但在PHP中没有使用过。您可以尝试以下脚本:http://www.phpclasses.org/browse/file/708.html,它是btree的实现。
如果还不够,你可以使用Hadoop来实现Map / Reduce模式,正如Michael所说。我不会分叉PHP进程,它似乎对性能没有帮助。
就个人而言,我会将PHP用作客户端并将所有内容放在Hadoop中。本教程可能有所帮助:http://www.lunchpauze.com/2007/10/writing-hadoop-mapreduce-program-in-php.html。
另一个解决方案是使用Btree的Java实现:http://jdbm.sourceforge.net/。 JDBM是使用Btree +数据结构的对象数据库。然后,您可以通过使用Web服务公开数据或使用Quercus直接访问数据来使用PHP进行搜索
答案 4 :(得分:2)
使用网络还是CLI?
如果您使用网络,则可以在Quercus中集成该部分。然后您可以使用JAVA多线程的优势。
我实际上并不知道Quercus有多可靠。我还建议使用一种消息队列并重构代码,因此它不需要范围。
也许您可以将代码重建为Map / Reduce模式。然后,您可以在Hadoop中运行PHP代码然后,您可以通过几台计算机对处理进行集群。
我不知道它是否有用,但我遇到了另一个名为Gearman的项目。它还用于集群PHP进程。如果Hadoop不是您想要的方式,我想你可以将它与reduce脚本结合起来。
答案 5 :(得分:2)
这个问题似乎有点困惑。
我想减少绝对执行时间。
你的意思是经过的时间?当然使用正确的数据结构会提高吞吐量,但对于给定的数据结构,算法的最小阶数是绝对的,与实现算法的方式无关。
实现哪种设计模式......?
设计模式是代码 的东西,不是编写程序的模板,也是课程设计的有用工具。要从模式开始并使代码适合,它本身就是一种反模式。
没有人能够更好地了解您的数据及其结构如何解决这个问题,但效率的关键驱动因素将是您用于实现树的数据结构。如果经过的时间很重要,那么肯定要看并行执行,但是也可能值得考虑在不同的工具中执行操作 - 数据库是高度优化的,用于处理大型数据集,但请注意,描述树中的明显方法在隔离子树和走树时,关系数据库的效率非常低。
回应亚当提出的要求你的回答:
我“听说”pcntl不是一个好的解决方案。任何经历?
你在哪里听到的?当然从CGI或mod_php调用脚本分叉是一个坏主意,但从命令行执行它没有任何问题。有一个谷歌长期运行PHP进程(被警告有很多不良信息)。您编写的代码将根据底层操作系统而有所不同 - 您没有说明。
我怀疑您可以通过确定需要检查树的哪些部分来解决大部分性能问题,并且只检查这些部分并在树更新时触发检查,或者至少将节点标记为'脏”。
您可能会发现这些有用:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ http://en.wikipedia.org/wiki/Threaded_binary_tree
下进行。
答案 6 :(得分:0)
有一个相当新的(自2012年以来)PHP扩展可用:pthreads。它可以通过PECL安装。
PHP代码中的简单实现:从.smtbBtn img { height: 14px; border: 1px solid transparent; }
.ie6img {
border-color: pink; filter: chroma(color=pink);
}
类扩展。添加Thread
方法并执行run()
方法。
start()
输出
<?php
// Example from http://www.phpgangsta.de/richtige-threads-in-php-einfach-erstellen-mit-pthreads
class AsyncOperation extends Thread
{
public function __construct($threadId)
{
$this->threadId = $threadId;
}
public function run()
{
printf("T %s: Sleeping 3sec\n", $this->threadId);
sleep(3);
printf("T %s: Hello World\n", $this->threadId);
}
}
$start = microtime(true);
for ($i = 1; $i <= 5; $i++) {
$t[$i] = new AsyncOperation($i);
$t[$i]->start();
}
echo microtime(true) - $start . "\n";
echo "end\n";