kmuenkel / parallel-collection
AmpPHP的Laravel包装器,提供执行并行处理的集合宏
v1.0.11
0202-03-07 15:00 UTC
Requires
- php: >=7.4
- amphp/parallel-functions: ^1.1
- laravel/framework: >=8.0
- opis/closure: ^3.6
Requires (Dev)
- ext-json: *
- barryvdh/laravel-ide-helper: ^2.10
- fzaninotto/faker: ^1.9.1
- mockery/mockery: ^1.4.4
- orchestra/testbench: ^6.20
- phpunit/phpunit: ^9.5.8
README
AmpPHP的Laravel包装器,提供执行并行处理的集合宏。
有一个类似的包叫做spatie/laravel-collection-macros,也尝试这样做,但当并行闭包试图利用Laravel抽象或模型实例时,就不够好了。问题是,类似于隔离的PhpUnit测试,当闭包被初始化以执行时,App需要重新初始化。此外,序列化和反序列化模型类并不是一个简单的过程,因为需要重新建立数据库连接。然而,Laravel已经解决了这个问题,即在序列化闭包用于队列作业的上下文中。所以这两个问题都可以使用框架中现有的特性来解决。
请注意,虽然AmPhp提供真正的并行处理,但父线程仍然需要在所有子线程解决之前等待,以便关闭。类似于分叉,这似乎是PHP本身的限制,如果子任务被允许在父任务关闭之后解决,那么父任务可能会尝试提前终止子任务,或者子线程在执行完成后不会被指令释放其资源,从而导致僵尸进程。如果目的是触发一个稍后解决的进程,而不会使父任务等待,你仍然需要使用类似队列作业的东西。然而,队列和此并行处理器的组合可以兼得两者之优,并且性能极好。
用法
并行闭包
如果并行处理的项本身是闭包,不需要特殊处理。
$process1 = function () { sleep(5); //Simulate taking a long time to handle the item return 'perform some long process'; }; $process2 = function () { sleep(5); //Simulate taking a long time to handle the item return 'perform another long process'; }; $items = compact('process1', 'process1'); $before = now(); $results = collect($items)->mapToParallel()->toArray(); $after = now(); $elapsedTime = $after->diffInSeconds($before); print_r(compact('results', 'elapsedTime')); /** * Array: * ( * "results" => Array * ( * ["process1"] => 'perform some long process' * ["process2"] => 'perform another long process' * ) * "elapsedTime" => 5 * ) */
带有处理器的并行项
如果你的项不是闭包,而是需要处理,示例将如下所示
$items = ['Hello', 'World']; $handler = function (string $item) { sleep(5); //Simulate taking a long time to handle the item return $item; }; $before = now(); $results = collect($items)->mapToParallel($handler)->toArray(); $after = now(); $elapsedTime = $after->diffInSeconds($before); print_r(compact('results', 'elapsedTime')); /** * Array: * ( * "results" => Array * ( * [0] => 'Hello' * [1] => 'World' * ) * "elapsedTime" => 5 * ) */