Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 16 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
ParallelExecutor | |
0.00% |
0 / 16 |
|
0.00% |
0 / 2 |
42 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
runInParallel | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
30 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\Utilities; |
5 | |
6 | use MediaWiki\MediaWikiServices; |
7 | |
8 | /** |
9 | * Helper class for maintenance scripts to run things in parallel. |
10 | * |
11 | * See also ForkContoller and https://phabricator.wikimedia.org/T201970. |
12 | * |
13 | * @since 2020.11 |
14 | * @license GPL-2.0-or-later |
15 | * @author Niklas Laxström |
16 | */ |
17 | class ParallelExecutor { |
18 | /** @var true[] */ |
19 | private $pids = []; |
20 | /** @var int */ |
21 | private $threads; |
22 | |
23 | public function __construct( int $threads = 1 ) { |
24 | $this->threads = $threads; |
25 | } |
26 | |
27 | public function runInParallel( callable $mainThread, callable $forkThread ): void { |
28 | // Fork to increase speed with parallelism. Also helps with memory usage if there are leaks. |
29 | $pid = -1; |
30 | if ( function_exists( 'pcntl_fork' ) ) { |
31 | $pid = pcntl_fork(); |
32 | } |
33 | |
34 | if ( $pid === 0 ) { |
35 | MediaWikiServices::resetChildProcessServices(); |
36 | $forkThread(); |
37 | exit(); |
38 | } elseif ( $pid === -1 ) { |
39 | // Fork failed do it serialized |
40 | $forkThread(); |
41 | } else { |
42 | // Main thread |
43 | $mainThread( $pid ); |
44 | $this->pids[$pid] = true; |
45 | |
46 | // If we hit the thread limit, wait for any child to finish. |
47 | if ( count( $this->pids ) >= $this->threads ) { |
48 | $status = 0; |
49 | $pid = pcntl_wait( $status ); |
50 | unset( $this->pids[$pid] ); |
51 | } |
52 | } |
53 | } |
54 | } |