mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Extract process-related functions from Utils into a separate Process class
This commit is contained in:
parent
1ea5316a37
commit
23071d257e
@ -27,6 +27,7 @@ use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use function arsort;
|
||||
use function count;
|
||||
@ -236,7 +237,7 @@ class MemoryManager{
|
||||
|
||||
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
|
||||
$this->checkTicker = 0;
|
||||
$memory = Utils::getMemoryUsage(true);
|
||||
$memory = Process::getMemoryUsage(true);
|
||||
$trigger = false;
|
||||
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
|
||||
$trigger = 0;
|
||||
|
@ -29,10 +29,10 @@ namespace {
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\Timezone;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
|
||||
@ -223,9 +223,9 @@ namespace pocketmine {
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
@ -268,7 +268,7 @@ namespace pocketmine {
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
Utils::kill(getmypid());
|
||||
Process::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
|
@ -97,6 +97,7 @@ use pocketmine\updater\AutoUpdater;
|
||||
use pocketmine\utils\Config;
|
||||
use pocketmine\utils\Internet;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
@ -1682,7 +1683,7 @@ class Server{
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
@Utils::kill(getmypid());
|
||||
@Process::kill(getmypid());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1807,7 +1808,7 @@ class Server{
|
||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||
sleep($spacing);
|
||||
}
|
||||
@Utils::kill(getmypid());
|
||||
@Process::kill(getmypid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1927,10 +1928,10 @@ class Server{
|
||||
|
||||
private function titleTick() : void{
|
||||
Timings::$titleTickTimer->startTiming();
|
||||
$d = Utils::getRealMemoryUsage();
|
||||
$d = Process::getRealMemoryUsage();
|
||||
|
||||
$u = Utils::getMemoryUsage(true);
|
||||
$usage = sprintf("%g/%g/%g/%g MB @ %d threads", round(($u[0] / 1024) / 1024, 2), round(($d[0] / 1024) / 1024, 2), round(($u[1] / 1024) / 1024, 2), round(($u[2] / 1024) / 1024, 2), Utils::getThreadCount());
|
||||
$u = Process::getMemoryUsage(true);
|
||||
$usage = sprintf("%g/%g/%g/%g MB @ %d threads", round(($u[0] / 1024) / 1024, 2), round(($d[0] / 1024) / 1024, 2), round(($u[1] / 1024) / 1024, 2), round(($u[2] / 1024) / 1024, 2), Process::getThreadCount());
|
||||
|
||||
$online = count($this->playerList);
|
||||
$connecting = $this->network->getConnectionCount() - $online;
|
||||
|
@ -24,8 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use function count;
|
||||
use function floor;
|
||||
use function microtime;
|
||||
@ -48,8 +48,8 @@ class StatusCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$rUsage = Utils::getRealMemoryUsage();
|
||||
$mUsage = Utils::getMemoryUsage(true);
|
||||
$rUsage = Process::getRealMemoryUsage();
|
||||
$mUsage = Process::getMemoryUsage(true);
|
||||
|
||||
$server = $sender->getServer();
|
||||
$sender->sendMessage(TextFormat::GREEN . "---- " . TextFormat::WHITE . "Server status" . TextFormat::GREEN . " ----");
|
||||
@ -94,7 +94,7 @@ class StatusCommand extends VanillaCommand{
|
||||
$sender->sendMessage(TextFormat::GOLD . "Network upload: " . TextFormat::RED . round($server->getNetwork()->getUpload() / 1024, 2) . " kB/s");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Network download: " . TextFormat::RED . round($server->getNetwork()->getDownload() / 1024, 2) . " kB/s");
|
||||
|
||||
$sender->sendMessage(TextFormat::GOLD . "Thread count: " . TextFormat::RED . Utils::getThreadCount());
|
||||
$sender->sendMessage(TextFormat::GOLD . "Thread count: " . TextFormat::RED . Process::getThreadCount());
|
||||
|
||||
$sender->sendMessage(TextFormat::GOLD . "Main thread memory: " . TextFormat::RED . number_format(round(($mUsage[0] / 1024) / 1024, 2), 2) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Total memory: " . TextFormat::RED . number_format(round(($mUsage[1] / 1024) / 1024, 2), 2) . " MB.");
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\event\server;
|
||||
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\Process;
|
||||
|
||||
|
||||
/**
|
||||
@ -87,6 +87,6 @@ class LowMemoryEvent extends ServerEvent{
|
||||
* @return int
|
||||
*/
|
||||
public function getMemoryFreed() : int{
|
||||
return $this->getMemory() - ($this->isGlobal() ? Utils::getMemoryUsage(true)[1] : Utils::getMemoryUsage(true)[0]);
|
||||
return $this->getMemory() - ($this->isGlobal() ? Process::getMemoryUsage(true)[1] : Process::getMemoryUsage(true)[0]);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\scheduler;
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Internet;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\UUID;
|
||||
use pocketmine\utils\VersionString;
|
||||
@ -135,12 +136,12 @@ class SendUsageTask extends AsyncTask{
|
||||
"historyList" => array_values($playerList)
|
||||
];
|
||||
|
||||
$info = Utils::getMemoryUsage(true);
|
||||
$info = Process::getMemoryUsage(true);
|
||||
$data["system"] = [
|
||||
"mainMemory" => $info[0],
|
||||
"totalMemory" => $info[1],
|
||||
"availableMemory" => $info[2],
|
||||
"threadCount" => Utils::getThreadCount()
|
||||
"threadCount" => Process::getThreadCount()
|
||||
];
|
||||
|
||||
break;
|
||||
|
171
src/pocketmine/utils/Process.php
Normal file
171
src/pocketmine/utils/Process.php
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use pocketmine\ThreadManager;
|
||||
use function count;
|
||||
use function exec;
|
||||
use function fclose;
|
||||
use function file;
|
||||
use function file_get_contents;
|
||||
use function function_exists;
|
||||
use function hexdec;
|
||||
use function memory_get_usage;
|
||||
use function preg_match;
|
||||
use function proc_close;
|
||||
use function proc_open;
|
||||
use function stream_get_contents;
|
||||
use function strpos;
|
||||
use function trim;
|
||||
|
||||
final class Process{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $advanced
|
||||
*
|
||||
* @return int[]|int
|
||||
*/
|
||||
public static function getMemoryUsage(bool $advanced = false){
|
||||
$reserved = memory_get_usage();
|
||||
$VmSize = null;
|
||||
$VmRSS = null;
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
$status = file_get_contents("/proc/self/status");
|
||||
if(preg_match("/VmRSS:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||
$VmRSS = $matches[1] * 1024;
|
||||
}
|
||||
|
||||
if(preg_match("/VmSize:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||
$VmSize = $matches[1] * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: more OS
|
||||
|
||||
if($VmRSS === null){
|
||||
$VmRSS = memory_get_usage();
|
||||
}
|
||||
|
||||
if(!$advanced){
|
||||
return $VmRSS;
|
||||
}
|
||||
|
||||
if($VmSize === null){
|
||||
$VmSize = memory_get_usage(true);
|
||||
}
|
||||
|
||||
return [$reserved, $VmRSS, $VmSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public static function getRealMemoryUsage() : array{
|
||||
$stack = 0;
|
||||
$heap = 0;
|
||||
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
$mappings = file("/proc/self/maps");
|
||||
foreach($mappings as $line){
|
||||
if(preg_match("#([a-z0-9]+)\\-([a-z0-9]+) [rwxp\\-]{4} [a-z0-9]+ [^\\[]*\\[([a-zA-z0-9]+)\\]#", trim($line), $matches) > 0){
|
||||
if(strpos($matches[3], "heap") === 0){
|
||||
$heap += hexdec($matches[2]) - hexdec($matches[1]);
|
||||
}elseif(strpos($matches[3], "stack") === 0){
|
||||
$stack += hexdec($matches[2]) - hexdec($matches[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$heap, $stack];
|
||||
}
|
||||
|
||||
|
||||
public static function getThreadCount() : int{
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
if(preg_match("/Threads:[ \t]+([0-9]+)/", file_get_contents("/proc/self/status"), $matches) > 0){
|
||||
return (int) $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: more OS
|
||||
|
||||
return count(ThreadManager::getInstance()->getAll()) + 3; //RakLib + MainLogger + Main Thread
|
||||
}
|
||||
|
||||
public static function kill($pid) : void{
|
||||
$logger = \GlobalLogger::get();
|
||||
if($logger instanceof MainLogger){
|
||||
$logger->syncFlushBuffer();
|
||||
}
|
||||
switch(Utils::getOS()){
|
||||
case "win":
|
||||
exec("taskkill.exe /F /PID " . ((int) $pid) . " > NUL");
|
||||
break;
|
||||
case "mac":
|
||||
case "linux":
|
||||
default:
|
||||
if(function_exists("posix_kill")){
|
||||
posix_kill($pid, 9); //SIGKILL
|
||||
}else{
|
||||
exec("kill -9 " . ((int) $pid) . " > /dev/null 2>&1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command Command to execute
|
||||
* @param string|null &$stdout Reference parameter to write stdout to
|
||||
* @param string|null &$stderr Reference parameter to write stderr to
|
||||
*
|
||||
* @return int process exit code
|
||||
*/
|
||||
public static function execute(string $command, string &$stdout = null, string &$stderr = null) : int{
|
||||
$process = proc_open($command, [
|
||||
["pipe", "r"],
|
||||
["pipe", "w"],
|
||||
["pipe", "w"]
|
||||
], $pipes);
|
||||
|
||||
if($process === false){
|
||||
$stderr = "Failed to open process";
|
||||
$stdout = "";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
|
||||
foreach($pipes as $p){
|
||||
fclose($p);
|
||||
}
|
||||
|
||||
return proc_close($process);
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ class ServerKiller extends Thread{
|
||||
});
|
||||
if(time() - $start >= $this->time){
|
||||
echo "\nTook too long to stop, server was killed forcefully!\n";
|
||||
@Utils::kill(getmypid());
|
||||
@Process::kill(getmypid());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use DaveRandom\CallbackValidator\CallbackType;
|
||||
use pocketmine\ThreadManager;
|
||||
use function array_combine;
|
||||
use function array_map;
|
||||
use function array_reverse;
|
||||
@ -41,7 +40,6 @@ use function debug_zval_dump;
|
||||
use function dechex;
|
||||
use function exec;
|
||||
use function explode;
|
||||
use function fclose;
|
||||
use function file;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
@ -51,7 +49,6 @@ use function get_current_user;
|
||||
use function get_loaded_extensions;
|
||||
use function getenv;
|
||||
use function gettype;
|
||||
use function hexdec;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
@ -61,20 +58,16 @@ use function is_readable;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function json_last_error_msg;
|
||||
use function memory_get_usage;
|
||||
use function ob_end_clean;
|
||||
use function ob_get_contents;
|
||||
use function ob_start;
|
||||
use function ord;
|
||||
use function php_uname;
|
||||
use function phpversion;
|
||||
use function posix_kill;
|
||||
use function preg_grep;
|
||||
use function preg_match;
|
||||
use function preg_match_all;
|
||||
use function preg_replace;
|
||||
use function proc_close;
|
||||
use function proc_open;
|
||||
use function rmdir;
|
||||
use function scandir;
|
||||
use function sha1;
|
||||
@ -82,7 +75,6 @@ use function spl_object_hash;
|
||||
use function str_pad;
|
||||
use function str_replace;
|
||||
use function str_split;
|
||||
use function stream_get_contents;
|
||||
use function stripos;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
@ -279,77 +271,6 @@ class Utils{
|
||||
return self::$os;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public static function getRealMemoryUsage() : array{
|
||||
$stack = 0;
|
||||
$heap = 0;
|
||||
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
$mappings = file("/proc/self/maps");
|
||||
foreach($mappings as $line){
|
||||
if(preg_match("#([a-z0-9]+)\\-([a-z0-9]+) [rwxp\\-]{4} [a-z0-9]+ [^\\[]*\\[([a-zA-z0-9]+)\\]#", trim($line), $matches) > 0){
|
||||
if(strpos($matches[3], "heap") === 0){
|
||||
$heap += hexdec($matches[2]) - hexdec($matches[1]);
|
||||
}elseif(strpos($matches[3], "stack") === 0){
|
||||
$stack += hexdec($matches[2]) - hexdec($matches[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$heap, $stack];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $advanced
|
||||
*
|
||||
* @return int[]|int
|
||||
*/
|
||||
public static function getMemoryUsage(bool $advanced = false){
|
||||
$reserved = memory_get_usage();
|
||||
$VmSize = null;
|
||||
$VmRSS = null;
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
$status = file_get_contents("/proc/self/status");
|
||||
if(preg_match("/VmRSS:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||
$VmRSS = $matches[1] * 1024;
|
||||
}
|
||||
|
||||
if(preg_match("/VmSize:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||
$VmSize = $matches[1] * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: more OS
|
||||
|
||||
if($VmRSS === null){
|
||||
$VmRSS = memory_get_usage();
|
||||
}
|
||||
|
||||
if(!$advanced){
|
||||
return $VmRSS;
|
||||
}
|
||||
|
||||
if($VmSize === null){
|
||||
$VmSize = memory_get_usage(true);
|
||||
}
|
||||
|
||||
return [$reserved, $VmRSS, $VmSize];
|
||||
}
|
||||
|
||||
public static function getThreadCount() : int{
|
||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||
if(preg_match("/Threads:[ \t]+([0-9]+)/", file_get_contents("/proc/self/status"), $matches) > 0){
|
||||
return (int) $matches[1];
|
||||
}
|
||||
}
|
||||
//TODO: more OS
|
||||
|
||||
return count(ThreadManager::getInstance()->getAll()) + 3; //RakLib + MainLogger + Main Thread
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $recalculate
|
||||
*
|
||||
@ -457,37 +378,6 @@ class Utils{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $command Command to execute
|
||||
* @param string|null &$stdout Reference parameter to write stdout to
|
||||
* @param string|null &$stderr Reference parameter to write stderr to
|
||||
*
|
||||
* @return int process exit code
|
||||
*/
|
||||
public static function execute(string $command, string &$stdout = null, string &$stderr = null) : int{
|
||||
$process = proc_open($command, [
|
||||
["pipe", "r"],
|
||||
["pipe", "w"],
|
||||
["pipe", "w"]
|
||||
], $pipes);
|
||||
|
||||
if($process === false){
|
||||
$stderr = "Failed to open process";
|
||||
$stdout = "";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
|
||||
foreach($pipes as $p){
|
||||
fclose($p);
|
||||
}
|
||||
|
||||
return proc_close($process);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
@ -513,26 +403,6 @@ class Utils{
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function kill($pid) : void{
|
||||
$logger = \GlobalLogger::get();
|
||||
if($logger instanceof MainLogger){
|
||||
$logger->syncFlushBuffer();
|
||||
}
|
||||
switch(Utils::getOS()){
|
||||
case "win":
|
||||
exec("taskkill.exe /F /PID " . ((int) $pid) . " > NUL");
|
||||
break;
|
||||
case "mac":
|
||||
case "linux":
|
||||
default:
|
||||
if(function_exists("posix_kill")){
|
||||
posix_kill($pid, 9); //SIGKILL
|
||||
}else{
|
||||
exec("kill -9 " . ((int) $pid) . " > /dev/null 2>&1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $value
|
||||
* @param bool $includeCurrent
|
||||
|
Loading…
x
Reference in New Issue
Block a user