运行 与 ReactPhp 并行的代码
Running code parallel with ReactPhp
问题:我需要 clone/download 几个 git 存储库,不幸的是按顺序执行它需要很长时间。我想到了使用 ReactPhp 事件循环并并行执行它。
尽管尝试了很多次,但我还是无法运行 并行获取它。也许我误解了这个概念,但我期望 ReactPhp 以某种方式分叉执行我的代码。
你能看看我的代码并分享一些如何让它工作的指南吗?
use Symfony\Component\Stopwatch\Stopwatch;
include 'vendor/autoload.php';
$toClone = [
['url' => 'http://github.com/symfony/symfony.git', 'dest' => 'C:\tmp\cloneR1'],
['url' => 'http://github.com/laravel/laravel.git', 'dest' => 'C:\tmp\cloneR2'],
['url' => 'http://github.com/rails/rails.git', 'dest' => 'C:\tmp\cloneR3'],
];
$end = count($toClone);
$i = 0;
$deferred = new React\Promise\Deferred();
$fClone = function (\React\EventLoop\Timer\Timer $timer) use (&$i, $deferred, &$toClone, $end) {
$project = array_pop($toClone);
$git = new \GitWrapper\GitWrapper();
$git->setTimeout(3600);
$git->cloneRepository($project['url'], $project['dest']);
$deferred->notify([$i++, $project['url']]);
if ($end <= $i) {
$timer->cancel();
$deferred->resolve();
}
};
$stopwatch = new Stopwatch();
$stopwatch->start('run');
$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(1, $fClone);
$deferred->promise()->then(function () use ($stopwatch) {
echo 'DONE' . PHP_EOL;
$event = $stopwatch->stop('run');
echo 'Run took ' . $event->getDuration() / 1000 . 'sec and ' . $event->getMemory() . ' bytes of memory';
}, null, function ($data) {
echo 'RUN ' . $data[0] . ' - ' . $data[1] . PHP_EOL;
});
$loop->run();
我的composer.json
{
"require": {
"react/promise": "2.2.0",
"react/event-loop": "0.4.1",
"cpliakas/git-wrapper": "1.4.1",
"symfony/stopwatch": "2.7.0"
}
}
OS: Windows7
PHP:5.4.8 和 5.5.20
none 这些扩展已安装
"suggest": {
"ext-libevent": ">=0.1.0",
"ext-event": "~1.0",
"ext-libev": "*"
},
所以使用了 StreamSelectLoop
您要处理的主要问题是 $git->cloneRepository()
呼叫阻塞; reactphp 只允许处理应用程序级循环。如果你不让你的代码成为非阻塞的,那么你的代码仍然会以线性方式运行。您必须弄清楚如何让克隆在后台发生;这可以通过分叉进程或在后台调用另一个 php 脚本到 运行 来完成。我不确定像这样运行的 git 包装器,但是如果你能找到一个以非阻塞方式执行 git 调用的库;那么您的问题将大部分得到解决。
ReactPHP 不会将 php 变成非阻塞的,它只是提供允许非阻塞技术的框架。如果你的代码块,反应循环将不会是 运行.
问题:我需要 clone/download 几个 git 存储库,不幸的是按顺序执行它需要很长时间。我想到了使用 ReactPhp 事件循环并并行执行它。
尽管尝试了很多次,但我还是无法运行 并行获取它。也许我误解了这个概念,但我期望 ReactPhp 以某种方式分叉执行我的代码。
你能看看我的代码并分享一些如何让它工作的指南吗?
use Symfony\Component\Stopwatch\Stopwatch;
include 'vendor/autoload.php';
$toClone = [
['url' => 'http://github.com/symfony/symfony.git', 'dest' => 'C:\tmp\cloneR1'],
['url' => 'http://github.com/laravel/laravel.git', 'dest' => 'C:\tmp\cloneR2'],
['url' => 'http://github.com/rails/rails.git', 'dest' => 'C:\tmp\cloneR3'],
];
$end = count($toClone);
$i = 0;
$deferred = new React\Promise\Deferred();
$fClone = function (\React\EventLoop\Timer\Timer $timer) use (&$i, $deferred, &$toClone, $end) {
$project = array_pop($toClone);
$git = new \GitWrapper\GitWrapper();
$git->setTimeout(3600);
$git->cloneRepository($project['url'], $project['dest']);
$deferred->notify([$i++, $project['url']]);
if ($end <= $i) {
$timer->cancel();
$deferred->resolve();
}
};
$stopwatch = new Stopwatch();
$stopwatch->start('run');
$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(1, $fClone);
$deferred->promise()->then(function () use ($stopwatch) {
echo 'DONE' . PHP_EOL;
$event = $stopwatch->stop('run');
echo 'Run took ' . $event->getDuration() / 1000 . 'sec and ' . $event->getMemory() . ' bytes of memory';
}, null, function ($data) {
echo 'RUN ' . $data[0] . ' - ' . $data[1] . PHP_EOL;
});
$loop->run();
我的composer.json
{
"require": {
"react/promise": "2.2.0",
"react/event-loop": "0.4.1",
"cpliakas/git-wrapper": "1.4.1",
"symfony/stopwatch": "2.7.0"
}
}
OS: Windows7
PHP:5.4.8 和 5.5.20
none 这些扩展已安装
"suggest": {
"ext-libevent": ">=0.1.0",
"ext-event": "~1.0",
"ext-libev": "*"
},
所以使用了 StreamSelectLoop
您要处理的主要问题是 $git->cloneRepository()
呼叫阻塞; reactphp 只允许处理应用程序级循环。如果你不让你的代码成为非阻塞的,那么你的代码仍然会以线性方式运行。您必须弄清楚如何让克隆在后台发生;这可以通过分叉进程或在后台调用另一个 php 脚本到 运行 来完成。我不确定像这样运行的 git 包装器,但是如果你能找到一个以非阻塞方式执行 git 调用的库;那么您的问题将大部分得到解决。
ReactPHP 不会将 php 变成非阻塞的,它只是提供允许非阻塞技术的框架。如果你的代码块,反应循环将不会是 运行.