generated from ergebnis/php-package-template
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce `NProcFinder`, inspired from Infection.
- Loading branch information
Showing
4 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Fidry CPUCounter Config package. | ||
* | ||
* (c) Théo FIDRY <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fidry\CpuCounter\Exec; | ||
|
||
use ErrorException; | ||
use function error_get_last; | ||
|
||
// see https://github.com/thecodingmachine/safe/blob/master/generated/Exceptions/ExecException.php | ||
final class ExecException extends ErrorException | ||
{ | ||
public static function createFromPhpError(): self | ||
{ | ||
$error = error_get_last(); | ||
|
||
return new self($error['message'] ?? 'An error occured', 0, $error['type'] ?? 1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Fidry CPUCounter Config package. | ||
* | ||
* (c) Théo FIDRY <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fidry\CpuCounter\Exec; | ||
|
||
use function error_clear_last; | ||
use function shell_exec; | ||
|
||
/** | ||
* Mimicks Safe\shell_exec: this is to avoid to add an extra dependency to this | ||
* micro package. | ||
* | ||
* @see https://github.com/thecodingmachine/safe/blob/0653752f6c2d45e0640fa24bf789cae367a501d3/generated/exec.php#L114 | ||
*/ | ||
final class ShellExec | ||
{ | ||
private function __construct() | ||
{ | ||
} | ||
|
||
/** | ||
* @throws ExecException | ||
*/ | ||
public static function execute(string $command): string | ||
{ | ||
error_clear_last(); | ||
|
||
$safeResult = shell_exec($command); | ||
|
||
if (null === $safeResult || false === $safeResult) { | ||
throw ExecException::createFromPhpError(); | ||
} | ||
|
||
return $safeResult; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Fidry CPUCounter Config package. | ||
* | ||
* (c) Théo FIDRY <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fidry\CpuCounter; | ||
|
||
use Fidry\CpuCounter\Exec\ExecException; | ||
use Fidry\CpuCounter\Exec\ShellExec; | ||
use function filter_var; | ||
use function is_int; | ||
use function trim; | ||
use const FILTER_VALIDATE_INT; | ||
|
||
/** | ||
* @see https://github.com/infection/infection/blob/fbd8c44/src/Resource/Processor/CpuCoresCountProvider.php#L69-L82 | ||
* @see https://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo | ||
*/ | ||
final class NProcFinder | ||
{ | ||
private function __construct() | ||
{ | ||
} | ||
|
||
/** | ||
* @return positive-int|null | ||
*/ | ||
public static function find(): ?int | ||
{ | ||
if (!self::supportsNproc()) { | ||
return null; | ||
} | ||
|
||
try { | ||
$nproc = ShellExec::execute('nproc --all'); | ||
} catch (ExecException $nprocFailed) { | ||
return null; | ||
} | ||
|
||
return self::countCpuCores($nproc); | ||
} | ||
|
||
private static function supportsNproc(): bool | ||
{ | ||
try { | ||
$commandNproc = ShellExec::execute('command -v nproc'); | ||
} catch (ExecException $noNprocCommand) { | ||
return false; | ||
} | ||
|
||
return '' !== trim($commandNproc); | ||
} | ||
|
||
/** | ||
* @return positive-int|null | ||
*/ | ||
public static function countCpuCores(string $nproc): ?int | ||
{ | ||
$cpuCount = filter_var(trim($nproc), FILTER_VALIDATE_INT); | ||
|
||
return is_int($cpuCount) && $cpuCount > 0 ? $cpuCount : null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Fidry CPUCounter Config package. | ||
* | ||
* (c) Théo FIDRY <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fidry\CpuCounter\Test; | ||
|
||
use Fidry\CpuCounter\NProcFinder; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* @covers \Fidry\CpuCounter\NProcFinder | ||
* | ||
* @internal | ||
*/ | ||
final class NProcFinderTest extends TestCase | ||
{ | ||
/** | ||
* @dataProvider nprocProvider | ||
*/ | ||
public function test_it_can_count_the_number_of_cpu_cores( | ||
string $nproc, | ||
?int $expected | ||
): void { | ||
$actual = NProcFinder::countCpuCores($nproc); | ||
|
||
self::assertSame($expected, $actual); | ||
} | ||
|
||
public static function nprocProvider(): iterable | ||
{ | ||
yield 'empty' => [ | ||
<<<'EOF' | ||
|
||
EOF, | ||
null, | ||
]; | ||
|
||
// $ docker run --tty --rm --platform linux/amd64 alpine:3.14 nproc --all | ||
yield 'example from an alpine Docker image' => [ | ||
<<<'EOF' | ||
3 | ||
|
||
EOF, | ||
3, | ||
]; | ||
|
||
yield 'no processor' => [ | ||
<<<'EOF' | ||
0 | ||
|
||
EOF, | ||
null, | ||
]; | ||
} | ||
} |