Script to replicate:
<?php
use parallel\{Runtime, Future};
$closure = function($n)
{
$x = 0;
for ($i = 0; $i < 99999999 - $n * 10000; $i++)
$x++;
echo "done {$n}\n";
return [$n, $x];
};
$option = @$argv[1] ?? '0';
echo "Running option {$option}\n\n";
$timer = microtime(true);
$runtimes = [];
$futures = [];
foreach (range(1, 10) as $n)
{
if ($option === '0')
{
$runtime = new Runtime();
$futures[] = $runtime->run($closure, [$n]);
}
elseif ($option === '1')
{
$runtime = new Runtime();
$futures[] = $runtime->run($closure, [$n]);
unset($runtime);
}
elseif ($option === '2')
{
$runtimes[$n] = new Runtime();
$futures[] = $runtimes[$n]->run($closure, [$n]);
}
}
$count = count($futures);
while ($count > 0)
{
$resolved = [];
$errored = [];
$count -= Future::select($futures, $resolved, $errored);
foreach ($resolved as $future)
{
$a = $future->value();
echo "{$a[0]} -> {$a[1]}\n";
}
}
echo "\n", number_format(1000 * (microtime(true) - $timer)), " ms\n";
echo "Parallel version ", phpversion('parallel'), "\n";
When run with option 0, it's not run in parallel, with one child process doing the work, and the next one sleeping/waiting:
Running option 0
1 ms to init run 1
done 1
1,894 ms to init run 2
done 2
1,889 ms to init run 3
done 3
1,897 ms to init run 4
done 4
1,889 ms to init run 5
done 5
1,896 ms to init run 6
done 6
1,907 ms to init run 7
done 7
1,891 ms to init run 8
done 8
1,924 ms to init run 9
done 9
1,885 ms to init run 10
1 -> 99989999
2 -> 99979999
3 -> 99969999
4 -> 99959999
5 -> 99949999
6 -> 99939999
7 -> 99929999
8 -> 99919999
9 -> 99909999
done 10
10 -> 99899999
18,966 ms
Parallel version 0.8.3
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 18132 3176 2692 S 0.0 0.0 0:00.04 bash
413 root 20 0 41040 3240 2760 R 0.0 0.0 0:00.81 `- top
800 root 20 0 332936 24284 18652 S 0.0 0.1 0:00.03 php
812 root 20 0 332936 24284 18652 R 51.0 0.1 0:01.53 `- php
813 root 20 0 332936 24284 18652 S 0.0 0.1 0:00.00 `- php
When run with option 1 (unsetting $runtime
), same as above, but no longer shows a waiting process:
Running option 1
done 1
1,895 ms to init run 1
done 2
1,929 ms to init run 2
done 3
1,885 ms to init run 3
done 4
1,892 ms to init run 4
done 5
1,887 ms to init run 5
done 6
1,887 ms to init run 6
done 7
1,922 ms to init run 7
done 8
1,910 ms to init run 8
done 9
1,889 ms to init run 9
done 10
1,898 ms to init run 10
1 -> 99989999
2 -> 99979999
3 -> 99969999
4 -> 99959999
5 -> 99949999
6 -> 99939999
7 -> 99929999
8 -> 99919999
9 -> 99909999
10 -> 99899999
18,994 ms
Parallel version 0.8.3
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 18132 3308 2824 S 0.0 0.0 0:00.03 bash
409 root 20 0 41040 3096 2616 R 0.0 0.0 0:00.12 `- top
517 root 20 0 256964 24184 18960 S 0.0 0.1 0:00.03 php
529 root 20 0 256964 24184 18960 R 42.3 0.1 0:01.27 `- php
When run with option 2 (storing all the runtimes in an array), works as expected in parallel and much faster:
Running option 2
1 ms to init run 1
0 ms to init run 2
0 ms to init run 3
0 ms to init run 4
1 ms to init run 5
1 ms to init run 6
6 ms to init run 7
4 ms to init run 8
8 ms to init run 9
16 ms to init run 10
done 6
done 5
done 2
done 10
done 4
done 9
done 7
done 8
done 3
done 1
1 -> 99989999
2 -> 99979999
3 -> 99969999
4 -> 99959999
5 -> 99949999
6 -> 99939999
7 -> 99929999
8 -> 99919999
9 -> 99909999
10 -> 99899999
4,615 ms
Parallel version 0.8.3
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 18132 3176 2692 S 0.0 0.0 0:00.04 bash
413 root 20 0 41040 3240 2760 R 0.0 0.0 0:00.88 `- top
849 root 20 0 940716 25836 18436 S 0.0 0.1 0:00.02 php
856 root 20 0 940716 25836 18436 R 79.1 0.1 0:02.55 `- php
857 root 20 0 940716 25836 18436 R 69.8 0.1 0:02.35 `- php
858 root 20 0 940716 25836 18436 R 69.4 0.1 0:02.36 `- php
859 root 20 0 940716 25836 18436 R 78.1 0.1 0:02.66 `- php
860 root 20 0 940716 25836 18436 R 85.4 0.1 0:02.83 `- php
861 root 20 0 940716 25836 18436 R 86.7 0.1 0:02.87 `- php
862 root 20 0 940716 25836 18436 R 74.4 0.1 0:02.48 `- php
863 root 20 0 940716 25836 18436 R 86.4 0.1 0:02.90 `- php
864 root 20 0 940716 25836 18436 R 71.8 0.1 0:02.33 `- php
865 root 20 0 940716 25836 18436 R 81.1 0.1 0:02.65 `- php
I'm assuming that this is because $runtime
is a type of resource, and it needs to wait for it to finish when it it replaced or unset? At first this was very confusing and I was wondering why my code wasn't running more than one thread.
If this is the case, perhaps an E_NOTICE
could be thrown when trying to replace a variable holding a running parallel\Runtime
. That is, unless you could find a solution for this and not have to depend on the variable staying.
Or perhaps when on __unset()
on a Runtime
it should kill it like $runtime->kill()
?