Skip to content

Commit

Permalink
Introduce CPUCoreFinders (#14)
Browse files Browse the repository at this point in the history
Extract each find logic in its own isolated finder. This will make it easier to later:

- Add test
- Re-order the find logic
  • Loading branch information
theofidry authored Dec 4, 2022
1 parent 5392f6a commit bb5036a
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 34 deletions.
44 changes: 10 additions & 34 deletions src/CpuCoreCounter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,7 @@

namespace Fidry\CpuCounter;

use function count;
use function fgets;
use function file_get_contents;
use function function_exists;
use function is_file;
use function is_resource;
use function pclose;
use function popen;
use function preg_match_all;
use const DIRECTORY_SEPARATOR;

final class CpuCoreCounter
Expand Down Expand Up @@ -50,41 +42,25 @@ private static function findCount(): int
return 1;
}

// from brianium/paratest
if (is_file('/proc/cpuinfo')) {
// Linux (and potentially Windows with linux sub systems)
$cpuinfo = file_get_contents('/proc/cpuinfo');
/** @var list<class-string<CpuCoreFinder>> $finders */
$finders = [
CpuInfoFinder::class,
];

if (false !== $cpuinfo) {
preg_match_all('/^processor/m', $cpuinfo, $matches);

return count($matches[0]);
}
if (DIRECTORY_SEPARATOR === '\\') {
$finders[] = WindowsWmicFinder::class;
}

if (DIRECTORY_SEPARATOR === '\\') {
// Windows
$process = popen('wmic cpu get NumberOfLogicalProcessors', 'rb');
$finders[] = HwFinder::class;

if (is_resource($process)) {
fgets($process);
$cores = (int) fgets($process);
pclose($process);
foreach ($finders as $finder) {
$cores = $finder::find();

if (null !== $cores) {
return $cores;
}
}

$process = popen('sysctl -n hw.ncpu', 'rb');

if (is_resource($process)) {
// *nix (Linux, BSD and Mac)
$cores = (int) fgets($process);
pclose($process);

return $cores;
}

return 2;
}
}
22 changes: 22 additions & 0 deletions src/CpuCoreFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?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;

interface CpuCoreFinder
{
/**
* @return positive-int|null
*/
public static function find(): ?int;
}
53 changes: 53 additions & 0 deletions src/CpuInfoFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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 function count;
use function file_get_contents;
use function is_file;
use function preg_match_all;

/**
* Find the number of CPU cores looking up at the cpuinfo file which is available
* on Linux systems and Windows systems with a Linux sub-system.
*
* @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L903-L909
* @see https://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
*/
final class CpuInfoFinder implements CpuCoreFinder
{
private function __construct()
{
}

/**
* @return positive-int|null
*/
public static function find(): ?int
{
// from brianium/paratest
if (is_file('/proc/cpuinfo')) {
// Linux (and potentially Windows with linux sub systems)
$cpuinfo = file_get_contents('/proc/cpuinfo');

if (false !== $cpuinfo) {
preg_match_all('/^processor/m', $cpuinfo, $matches);

return count($matches[0]);
}
}

return null;
}
}
50 changes: 50 additions & 0 deletions src/HwFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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 function fgets;
use function is_resource;
use function pclose;
use function popen;

/**
* Find the number of CPU cores for Linux, BSD and OSX.
*
* @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L903-L909
* @see https://opensource.apple.com/source/xnu/xnu-792.2.4/libkern/libkern/sysctl.h.auto.html
*/
final class HwFinder implements CpuCoreFinder
{
private function __construct()
{
}

/**
* @return positive-int|null
*/
public static function find(): ?int
{
$process = popen('sysctl -n hw.ncpu', 'rb');

if (is_resource($process)) {
// *nix (Linux, BSD and Mac)
$cores = (int) fgets($process);
pclose($process);

return $cores;
}

return null;
}
}
50 changes: 50 additions & 0 deletions src/WindowsWmicFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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 function fgets;
use function is_resource;
use function pclose;
use function popen;

/**
* Find the number of CPU cores for Windows.
*
* @see https://github.com/paratestphp/paratest/blob/c163539818fd96308ca8dc60f46088461e366ed4/src/Runners/PHPUnit/Options.php#L912-L916
*/
final class WindowsWmicFinder implements CpuCoreFinder
{
private function __construct()
{
}

/**
* @return positive-int|null
*/
public static function find(): ?int
{
// Windows
$process = popen('wmic cpu get NumberOfLogicalProcessors', 'rb');

if (is_resource($process)) {
fgets($process);
$cores = (int) fgets($process);
pclose($process);

return $cores;
}

return null;
}
}

0 comments on commit bb5036a

Please sign in to comment.