|
1 | 1 | <?php namespace lang; |
2 | 2 |
|
| 3 | +use Com, Closure; |
| 4 | + |
3 | 5 | /** |
4 | 6 | * User environment |
5 | 7 | * |
6 | | - * @test xp://net.xp_framework.unittest.core.EnvironmentTest |
| 8 | + * @test net.xp_framework.unittest.core.EnvironmentTest |
7 | 9 | */ |
8 | 10 | abstract class Environment { |
9 | 11 |
|
@@ -57,16 +59,15 @@ public static function variables($filter= null) { |
57 | 59 | */ |
58 | 60 | public static function variable($arg, ... $default) { |
59 | 61 | foreach ((array)$arg as $name) { |
60 | | - if (false === ($env= getenv($name))) continue; |
61 | | - return $env; |
| 62 | + if (false !== ($env= getenv($name))) return $env; |
62 | 63 | } |
63 | 64 |
|
64 | 65 | if (empty($default)) { |
65 | 66 | throw new IllegalArgumentException(is_array($arg) |
66 | 67 | ? 'None of the variables [$'.implode(', $', $arg).'] exists' |
67 | 68 | : 'No such environment variable $'.$name |
68 | 69 | ); |
69 | | - } else if ($default[0] instanceof \Closure) { |
| 70 | + } else if ($default[0] instanceof Closure) { |
70 | 71 | return $default[0]($arg); |
71 | 72 | } else { |
72 | 73 | return $default[0]; |
@@ -111,6 +112,54 @@ public static function platform(): string { |
111 | 112 | ; |
112 | 113 | } |
113 | 114 |
|
| 115 | + /** |
| 116 | + * Returns the number of processors available in this environment. First checks |
| 117 | + * for the `NUMBER_OF_PROCESSORS` environment variables, then uses platform- |
| 118 | + * specific files and tools. Returns NULL if no discovery method is available. |
| 119 | + * |
| 120 | + * @see https://stackoverflow.com/q/6481005 (Linux) |
| 121 | + * @see https://stackoverflow.com/q/1715580 (Mac OS) |
| 122 | + * @see https://stackoverflow.com/q/22919076 (Windows) |
| 123 | + * @see https://stackoverflow.com/a/49152519 (Docker w/ `--cpus=<n>`) |
| 124 | + * @see https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-computersystem |
| 125 | + * @return ?int|float |
| 126 | + */ |
| 127 | + public static function availableProcessors() { |
| 128 | + if ($n= getenv('NUMBER_OF_PROCESSORS')) { |
| 129 | + return (int)$n; |
| 130 | + } else if (class_exists(Com::class)) { |
| 131 | + $c= new Com('winmgmts://./root/cimv2'); |
| 132 | + foreach ($c->instancesOf('Win32_ComputerSystem') as $sys) { |
| 133 | + return $sys->NumberOfProcessors; |
| 134 | + } |
| 135 | + } else if (is_readable($f= '/sys/fs/cgroup/cpu/cpu.cfs_quota_us') && ($fd= fopen($f, 'r'))) { |
| 136 | + fscanf($fd, '%d', $n); |
| 137 | + fclose($fd); |
| 138 | + if ($n > 0) return (float)($n / 100000); |
| 139 | + // Fall through |
| 140 | + } |
| 141 | + |
| 142 | + if (is_readable($f= '/proc/cpuinfo') && ($fd= fopen($f, 'r'))) { |
| 143 | + $n= 0; |
| 144 | + do { |
| 145 | + $line= fgets($fd, 1024); |
| 146 | + if (0 === strncmp($line, 'processor', 9)) $n++; |
| 147 | + } while (!feof($fd)); |
| 148 | + fclose($fd); |
| 149 | + return $n; |
| 150 | + } else { |
| 151 | + $paths= explode(PATH_SEPARATOR, getenv('PATH')); |
| 152 | + foreach (['nproc' => '', 'sysctl' => ' -n hw.ncpu'] as $command => $args) { |
| 153 | + foreach ($paths as $path) { |
| 154 | + $binary= $path.DIRECTORY_SEPARATOR.$command; |
| 155 | + if (is_executable($binary)) return (int)exec($binary.$args); |
| 156 | + } |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + return null; |
| 161 | + } |
| 162 | + |
114 | 163 | /** |
115 | 164 | * Returns a path for display for a given directory. Will replace current |
116 | 165 | * and parent directories with `.` and `..`, the user's home directory with |
@@ -167,7 +216,7 @@ public static function path(string $dir= '.', ?string $platform= null): string { |
167 | 216 | * cannot be found, uses PHP's builtin functionality. |
168 | 217 | */ |
169 | 218 | public static function tempDir(): string { |
170 | | - $dir= self::variable(['TEMP', 'TMP', 'TMPDIR', 'TEMPDIR'], function() { return sys_get_temp_dir(); }); |
| 219 | + $dir= self::variable(['TEMP', 'TMP', 'TMPDIR', 'TEMPDIR'], fn() => sys_get_temp_dir()); |
171 | 220 | return rtrim($dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; |
172 | 221 | } |
173 | 222 |
|
|
0 commit comments