Merge branch 'next-minor' into next-major

This commit is contained in:
Dylan K. Taylor 2023-01-13 17:29:25 +00:00
commit 8909aa6a18
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
9 changed files with 74 additions and 35 deletions

View File

@ -43,7 +43,7 @@
"pocketmine/classloader": "^0.2.0",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.16.0",
"pocketmine/locale-data": "~2.17.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.4.0",
"pocketmine/math": "^0.4.0",

14
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ecbdb7bda8ed93cb0499bfe486a68ff6",
"content-hash": "5c869a38ea239fff76262c1648cef623",
"packages": [
{
"name": "adhocore/json-comment",
@ -591,16 +591,16 @@
},
{
"name": "pocketmine/locale-data",
"version": "2.16.0",
"version": "2.17.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Language.git",
"reference": "b3bf9029c112414fdb7cd9de778df191565d3038"
"reference": "a2c7071117c98ccc0e333994271cab1072eb3c06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Language/zipball/b3bf9029c112414fdb7cd9de778df191565d3038",
"reference": "b3bf9029c112414fdb7cd9de778df191565d3038",
"url": "https://api.github.com/repos/pmmp/Language/zipball/a2c7071117c98ccc0e333994271cab1072eb3c06",
"reference": "a2c7071117c98ccc0e333994271cab1072eb3c06",
"shasum": ""
},
"type": "library",
@ -608,9 +608,9 @@
"description": "Language resources used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Language/issues",
"source": "https://github.com/pmmp/Language/tree/2.16.0"
"source": "https://github.com/pmmp/Language/tree/2.17.0"
},
"time": "2023-01-04T20:27:52+00:00"
"time": "2023-01-13T17:22:45+00:00"
},
{
"name": "pocketmine/log",

View File

@ -69,6 +69,10 @@ use const JSON_UNESCAPED_SLASHES;
use const SORT_NUMERIC;
class MemoryManager{
private const DEFAULT_CHECK_RATE = Server::TARGET_TICKS_PER_SECOND;
private const DEFAULT_CONTINUOUS_TRIGGER_RATE = Server::TARGET_TICKS_PER_SECOND * 2;
private const DEEFAULT_TICKS_PER_GC = 30 * 60 * Server::TARGET_TICKS_PER_SECOND;
private int $memoryLimit;
private int $globalMemoryLimit;
private int $checkRate;
@ -131,11 +135,11 @@ class MemoryManager{
}
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
$this->checkRate = $config->getPropertyInt("memory.check-rate", 20);
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", 30);
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", 36000);
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEEFAULT_TICKS_PER_GC);
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);

View File

@ -117,6 +117,7 @@ use pocketmine\world\WorldCreationOptions;
use pocketmine\world\WorldManager;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Filesystem\Path;
use function array_fill;
use function array_sum;
use function base64_encode;
use function cli_set_process_title;
@ -181,6 +182,27 @@ class Server{
public const DEFAULT_PORT_IPV6 = 19133;
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
/**
* Worlds, network, commands and most other things are polled this many times per second on average.
* Between ticks, the server will sleep to ensure that the average tick rate is maintained.
* It may wake up between ticks if a Snooze notification source is triggered (e.g. to process network packets).
*/
public const TARGET_TICKS_PER_SECOND = 20;
/**
* The average time between ticks, in seconds.
*/
public const TARGET_SECONDS_PER_TICK = 1 / self::TARGET_TICKS_PER_SECOND;
public const TARGET_NANOSECONDS_PER_TICK = 1_000_000_000 / self::TARGET_TICKS_PER_SECOND;
/**
* The TPS threshold below which the server will generate log warnings.
*/
private const TPS_OVERLOAD_WARNING_THRESHOLD = self::TARGET_TICKS_PER_SECOND * 0.6;
private const TICKS_PER_WORLD_CACHE_CLEAR = 5 * self::TARGET_TICKS_PER_SECOND;
private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND;
private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND;
private static ?Server $instance = null;
private SleeperHandler $tickSleeper;
@ -199,7 +221,7 @@ class Server{
private PluginManager $pluginManager;
private float $profilingTickRate = 20;
private float $profilingTickRate = self::TARGET_TICKS_PER_SECOND;
private UpdateChecker $updater;
@ -209,10 +231,10 @@ class Server{
private int $tickCounter = 0;
private float $nextTick = 0;
/** @var float[] */
private array $tickAverage = [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
private array $tickAverage;
/** @var float[] */
private array $useAverage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
private float $currentTPS = 20;
private array $useAverage;
private float $currentTPS = self::TARGET_TICKS_PER_SECOND;
private float $currentUse = 0;
private float $startTime;
@ -748,6 +770,8 @@ class Server{
}
self::$instance = $this;
$this->startTime = microtime(true);
$this->tickAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, self::TARGET_TICKS_PER_SECOND);
$this->useAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, 0);
$this->tickSleeper = new SleeperHandler();
@ -931,7 +955,7 @@ class Server{
Timings::init();
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", 20);
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
DefaultPermissions::registerCorePermissions();
@ -969,7 +993,7 @@ class Server{
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", 6000));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
@ -1009,7 +1033,7 @@ class Server{
}
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
$this->sendUsageTicker = 6000;
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
$this->sendUsage(SendUsageTask::TYPE_OPEN);
}
@ -1792,11 +1816,11 @@ class Server{
$this->network->tick();
Timings::$connection->stopTiming();
if(($this->tickCounter % 20) === 0){
if(($this->tickCounter % self::TARGET_TICKS_PER_SECOND) === 0){
if($this->doTitleTick){
$this->titleTick();
}
$this->currentTPS = 20;
$this->currentTPS = self::TARGET_TICKS_PER_SECOND;
$this->currentUse = 0;
$queryRegenerateEvent = new QueryRegenerateEvent(new QueryInfo($this));
@ -1808,18 +1832,18 @@ class Server{
}
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
$this->sendUsageTicker = 6000;
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
$this->sendUsage(SendUsageTask::TYPE_STATUS);
}
if(($this->tickCounter % 100) === 0){
if(($this->tickCounter % self::TICKS_PER_WORLD_CACHE_CLEAR) === 0){
foreach($this->worldManager->getWorlds() as $world){
$world->clearCache();
}
}
if($this->getTicksPerSecondAverage() < 12){
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
}
if(($this->tickCounter % self::TICKS_PER_TPS_OVERLOAD_WARNING) === 0 && $this->getTicksPerSecondAverage() < self::TPS_OVERLOAD_WARNING_THRESHOLD){
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
}
$this->getMemoryManager()->check();
@ -1836,19 +1860,19 @@ class Server{
Timings::$serverTick->stopTiming();
$now = microtime(true);
$this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime));
$this->currentUse = min(1, ($now - $tickTime) / 0.05);
$this->currentTPS = min(self::TARGET_TICKS_PER_SECOND, 1 / max(0.001, $now - $tickTime));
$this->currentUse = min(1, ($now - $tickTime) / self::TARGET_SECONDS_PER_TICK);
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
$idx = $this->tickCounter % 20;
$idx = $this->tickCounter % self::TARGET_TICKS_PER_SECOND;
$this->tickAverage[$idx] = $this->currentTPS;
$this->useAverage[$idx] = $this->currentUse;
if(($this->nextTick - $tickTime) < -1){
$this->nextTick = $tickTime;
}else{
$this->nextTick += 0.05;
$this->nextTick += self::TARGET_SECONDS_PER_TICK;
}
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Jukebox as JukeboxTile;
use pocketmine\item\Item;
use pocketmine\item\Record;
use pocketmine\lang\KnownTranslationKeys;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\RecordSound;
@ -44,7 +45,7 @@ class Jukebox extends Opaque{
if($this->record !== null){
$this->ejectRecord();
}elseif($item instanceof Record){
$player->sendJukeboxPopup("record.nowPlaying", [$player->getLanguage()->translate($item->getRecordType()->getTranslatableName())]);
$player->sendJukeboxPopup(KnownTranslationKeys::RECORD_NOWPLAYING, [$player->getLanguage()->translate($item->getRecordType()->getTranslatableName())]);
$this->insertRecord($item->pop());
}
}

View File

@ -2586,6 +2586,12 @@ final class KnownTranslationFactory{
return new Translatable(KnownTranslationKeys::QUERY_WARNING2, []);
}
public static function record_nowPlaying(Translatable|string $param0) : Translatable{
return new Translatable(KnownTranslationKeys::RECORD_NOWPLAYING, [
0 => $param0,
]);
}
public static function server_port() : Translatable{
return new Translatable(KnownTranslationKeys::SERVER_PORT, []);
}

View File

@ -549,6 +549,7 @@ final class KnownTranslationKeys{
public const QUERY_DISABLE = "query_disable";
public const QUERY_WARNING1 = "query_warning1";
public const QUERY_WARNING2 = "query_warning2";
public const RECORD_NOWPLAYING = "record.nowPlaying";
public const SERVER_PORT = "server_port";
public const SERVER_PORT_V4 = "server_port_v4";
public const SERVER_PORT_V6 = "server_port_v6";

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\timings;
use pocketmine\Server;
use function round;
use function spl_object_id;
@ -54,8 +55,8 @@ final class TimingsRecord{
public static function tick(bool $measure = true) : void{
if($measure){
foreach(self::$records as $record){
if($record->curTickTotal > 50000000){
$record->violations += (int) round($record->curTickTotal / 50000000);
if($record->curTickTotal > Server::TARGET_NANOSECONDS_PER_TICK){
$record->violations += (int) round($record->curTickTotal / Server::TARGET_NANOSECONDS_PER_TICK);
}
$record->curTickTotal = 0;
$record->curCount = 0;

View File

@ -55,12 +55,14 @@ use function strval;
use function trim;
class WorldManager{
public const TICKS_PER_AUTOSAVE = 300 * Server::TARGET_TICKS_PER_SECOND;
/** @var World[] */
private array $worlds = [];
private ?World $defaultWorld = null;
private bool $autoSave = true;
private int $autoSaveTicks = 6000;
private int $autoSaveTicks = self::TICKS_PER_AUTOSAVE;
private int $autoSaveTicker = 0;
public function __construct(
@ -348,8 +350,8 @@ class WorldManager{
$world->doTick($currentTick);
$tickMs = (microtime(true) - $worldTime) * 1000;
$world->tickRateTime = $tickMs;
if($tickMs >= 50){
$world->getLogger()->debug(sprintf("Tick took too long: %gms (%g ticks)", $tickMs, round($tickMs / 50, 2)));
if($tickMs >= Server::TARGET_SECONDS_PER_TICK){
$world->getLogger()->debug(sprintf("Tick took too long: %gms (%g ticks)", $tickMs, round($tickMs / Server::TARGET_SECONDS_PER_TICK, 2)));
}
}