From e3c48b22cb6d2c4c7666b20a3ea3ef64ff4abf8a Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Sun, 19 Apr 2015 11:45:43 +0200 Subject: [PATCH] Anvil fixes, improved memory settings --- src/pocketmine/MemoryManager.php | 16 ++++++++++------ src/pocketmine/event/server/LowMemoryEvent.php | 13 +++++++++++-- src/pocketmine/level/Level.php | 4 ---- src/pocketmine/level/format/anvil/Chunk.php | 4 ++-- .../level/format/anvil/ChunkRequestTask.php | 3 ++- .../level/format/anvil/ChunkSection.php | 16 ++++++++-------- .../level/format/anvil/RegionLoader.php | 6 ++++-- .../level/format/generic/BaseChunk.php | 16 ++++++++-------- .../level/format/generic/BaseFullChunk.php | 2 +- src/pocketmine/level/format/leveldb/Chunk.php | 2 +- src/pocketmine/network/Network.php | 2 +- src/pocketmine/network/RakLibInterface.php | 6 +++--- .../network/protocol/AddEntityPacket.php | 3 ++- .../network/protocol/AddPlayerPacket.php | 3 ++- src/pocketmine/network/protocol/DataPacket.php | 8 ++++---- .../network/protocol/SetEntityDataPacket.php | 3 ++- 16 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/pocketmine/MemoryManager.php b/src/pocketmine/MemoryManager.php index 0f6f6cbfa..6ac15db26 100644 --- a/src/pocketmine/MemoryManager.php +++ b/src/pocketmine/MemoryManager.php @@ -62,9 +62,9 @@ class MemoryManager{ private function init(){ $this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 320)) * 1024 * 1024; $this->globalMemoryLimit = ((int) $this->server->getProperty("memory.global-limit", 512)) * 1024 * 1024; - $this->checkRate = ((int) $this->server->getProperty("memory.check-rate", 20)); + $this->checkRate = (int) $this->server->getProperty("memory.check-rate", 20); $this->continuousTrigger = (bool) $this->server->getProperty("memory.continuous-trigger", true); - $this->continuousTriggerRate = (int) $this->server->getProperty("memory.continuous-trigger-rate", 600); + $this->continuousTriggerRate = (int) $this->server->getProperty("memory.continuous-trigger-rate", 30); $this->garbageCollectionPeriod = (int) $this->server->getProperty("memory.garbage-collection.period", 12000); $this->garbageCollectionTrigger = (bool) $this->server->getProperty("memory.garbage-collection.low-memory-trigger", true); @@ -100,14 +100,15 @@ class MemoryManager{ } } - $ev = new LowMemoryEvent($memory, $limit, $triggerCount); + $ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount); $this->server->getPluginManager()->callEvent($ev); + $cycles = 0; if($this->garbageCollectionTrigger){ - $this->triggerGarbageCollector(); + $cycles = $this->triggerGarbageCollector(); } - $this->server->getLogger()->debug("[Memory Manager] Freed " . round(($ev->getMemoryFreed() / 1024) / 1024, 2)."MB"); + $this->server->getLogger()->debug("[Memory Manager] Freed " . round(($ev->getMemoryFreed() / 1024) / 1024, 2)."MB, $cycles cycles"); } public function check(){ @@ -145,7 +146,6 @@ class MemoryManager{ public function triggerGarbageCollector(){ Timings::$garbageCollectorTimer->startTiming(); - gc_collect_cycles(); if($this->garbageCollectionAsync){ $size = $this->server->getScheduler()->getAsyncTaskPoolSize(); @@ -154,6 +154,10 @@ class MemoryManager{ } } + $cycles = gc_collect_cycles(); + Timings::$garbageCollectorTimer->stopTiming(); + + return $cycles; } } \ No newline at end of file diff --git a/src/pocketmine/event/server/LowMemoryEvent.php b/src/pocketmine/event/server/LowMemoryEvent.php index 41d0d499e..b14a6ae13 100644 --- a/src/pocketmine/event/server/LowMemoryEvent.php +++ b/src/pocketmine/event/server/LowMemoryEvent.php @@ -33,10 +33,12 @@ class LowMemoryEvent extends ServerEvent{ private $memory; private $memoryLimit; private $triggerCount; + private $global; - public function __construct($memory, $memoryLimit, $triggerCount = 0){ + public function __construct($memory, $memoryLimit, $isGlobal = false, $triggerCount = 0){ $this->memory = $memory; $this->memoryLimit = $memoryLimit; + $this->global = (bool) $isGlobal; $this->triggerCount = (int) $triggerCount; } @@ -67,13 +69,20 @@ class LowMemoryEvent extends ServerEvent{ return $this->triggerCount; } + /** + * @return bool + */ + public function isGlobal(){ + return $this->global; + } + /** * Amount of memory already freed * * @return int */ public function getMemoryFreed(){ - return $this->getMemory() - Utils::getMemoryUsage(); + return $this->getMemory() - ($this->isGlobal() ? Utils::getMemoryUsage(true)[1] : Utils::getMemoryUsage(true)[0]); } } \ No newline at end of file diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index acab46959..6c3339b05 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -2200,10 +2200,6 @@ class Level implements ChunkManager, Metadatable{ unset($this->chunkTickList[$index]); unset($this->chunkCache[$index]); - $refs = \pocketmine\getReferenceCount($chunk); - - //$this->server->getLogger()->debug("Unloaded $x $z (".count($this->getChunks()).") [refs $refs]"); - $this->timings->doChunkUnload->stopTiming(); return true; diff --git a/src/pocketmine/level/format/anvil/Chunk.php b/src/pocketmine/level/format/anvil/Chunk.php index e50becebf..7bb8fb664 100644 --- a/src/pocketmine/level/format/anvil/Chunk.php +++ b/src/pocketmine/level/format/anvil/Chunk.php @@ -135,7 +135,7 @@ class Chunk extends BaseChunk{ * * @return Chunk */ - public static function fromBinary($data, LevelProvider $provider = null){ + public static function fromBinary(&$data, LevelProvider $provider = null){ $nbt = new NBT(NBT::BIG_ENDIAN); try{ @@ -152,7 +152,7 @@ class Chunk extends BaseChunk{ } } - public function toBinary(){ + public function &toBinary(){ $nbt = clone $this->getNBT(); $nbt->xPos = new Int("xPos", $this->x); diff --git a/src/pocketmine/level/format/anvil/ChunkRequestTask.php b/src/pocketmine/level/format/anvil/ChunkRequestTask.php index 1145a1db2..c57ade817 100644 --- a/src/pocketmine/level/format/anvil/ChunkRequestTask.php +++ b/src/pocketmine/level/format/anvil/ChunkRequestTask.php @@ -133,7 +133,8 @@ class ChunkRequestTask extends AsyncTask{ public function onCompletion(Server $server){ $level = $server->getLevel($this->levelId); if($level instanceof Level and $this->hasResult()){ - $level->chunkRequestCallback($this->chunkX, $this->chunkZ, $this->getResult()); + $result = $this->getResult(); + $level->chunkRequestCallback($this->chunkX, $this->chunkZ, $result); } } diff --git a/src/pocketmine/level/format/anvil/ChunkSection.php b/src/pocketmine/level/format/anvil/ChunkSection.php index bb42a551d..2bbf75257 100644 --- a/src/pocketmine/level/format/anvil/ChunkSection.php +++ b/src/pocketmine/level/format/anvil/ChunkSection.php @@ -155,7 +155,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ } } - public function getBlockIdColumn($x, $z){ + public function &getBlockIdColumn($x, $z){ $i = ($z << 4) + $x; $column = ""; for($y = 0; $y < 16; ++$y){ @@ -165,7 +165,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ return $column; } - public function getBlockDataColumn($x, $z){ + public function &getBlockDataColumn($x, $z){ $i = ($z << 3) + ($x >> 1); $column = ""; if(($x & 1) === 0){ @@ -181,7 +181,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ return $column; } - public function getBlockSkyLightColumn($x, $z){ + public function &getBlockSkyLightColumn($x, $z){ $i = ($z << 3) + ($x >> 1); $column = ""; if(($x & 1) === 0){ @@ -197,7 +197,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ return $column; } - public function getBlockLightColumn($x, $z){ + public function &getBlockLightColumn($x, $z){ $i = ($z << 3) + ($x >> 1); $column = ""; if(($x & 1) === 0){ @@ -213,19 +213,19 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ return $column; } - public function getIdArray(){ + public function &getIdArray(){ return $this->blocks; } - public function getDataArray(){ + public function &getDataArray(){ return $this->data; } - public function getSkyLightArray(){ + public function &getSkyLightArray(){ return $this->skyLight; } - public function getLightArray(){ + public function &getLightArray(){ return $this->blockLight; } diff --git a/src/pocketmine/level/format/anvil/RegionLoader.php b/src/pocketmine/level/format/anvil/RegionLoader.php index 90a368417..207a8f155 100644 --- a/src/pocketmine/level/format/anvil/RegionLoader.php +++ b/src/pocketmine/level/format/anvil/RegionLoader.php @@ -101,7 +101,8 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{ return null; } - $chunk = Chunk::fromBinary(fread($this->filePointer, $length - 1), $this->levelProvider); + $data = fread($this->filePointer, $length - 1); + $chunk = Chunk::fromBinary($data, $this->levelProvider); if($chunk instanceof Chunk){ return $chunk; }elseif($forward === false){ @@ -123,7 +124,8 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{ $nbt->TerrainPopulated = new Byte("TerrainPopulated", 0); $nbt->V = new Byte("V", self::VERSION); $nbt->InhabitedTime = new Long("InhabitedTime", 0); - $nbt->Biomes = new ByteArray("Biomes", str_repeat(Binary::writeByte(-1), 256)); + $biomes = str_repeat(Binary::writeByte(-1), 256); + $nbt->Biomes = new ByteArray("Biomes", $biomes); $nbt->BiomeColors = new IntArray("BiomeColors", array_fill(0, 156, Binary::readInt("\x00\x85\xb2\x4a"))); $nbt->HeightMap = new IntArray("HeightMap", array_fill(0, 256, 127)); $nbt->Sections = new Enum("Sections", []); diff --git a/src/pocketmine/level/format/generic/BaseChunk.php b/src/pocketmine/level/format/generic/BaseChunk.php index 74be57f9b..5fddaa50f 100644 --- a/src/pocketmine/level/format/generic/BaseChunk.php +++ b/src/pocketmine/level/format/generic/BaseChunk.php @@ -165,7 +165,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ } } - public function getBlockIdColumn($x, $z){ + public function &getBlockIdColumn($x, $z){ $column = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $column .= $this->sections[$y]->getBlockIdColumn($x, $z); @@ -174,7 +174,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $column; } - public function getBlockDataColumn($x, $z){ + public function &getBlockDataColumn($x, $z){ $column = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $column .= $this->sections[$y]->getBlockDataColumn($x, $z); @@ -183,7 +183,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $column; } - public function getBlockSkyLightColumn($x, $z){ + public function &getBlockSkyLightColumn($x, $z){ $column = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $column .= $this->sections[$y]->getBlockSkyLightColumn($x, $z); @@ -192,7 +192,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $column; } - public function getBlockLightColumn($x, $z){ + public function &getBlockLightColumn($x, $z){ $column = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $column .= $this->sections[$y]->getBlockLightColumn($x, $z); @@ -227,7 +227,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $this->getProvider() === null ? false : $this->getProvider()->getChunk($this->getX(), $this->getZ(), true) instanceof Chunk; } - public function getBlockIdArray(){ + public function &getBlockIdArray(){ $blocks = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $blocks .= $this->sections[$y]->getIdArray(); @@ -236,7 +236,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $blocks; } - public function getBlockDataArray(){ + public function &getBlockDataArray(){ $data = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $data .= $this->sections[$y]->getDataArray(); @@ -245,7 +245,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $data; } - public function getBlockSkyLightArray(){ + public function &getBlockSkyLightArray(){ $skyLight = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $skyLight .= $this->sections[$y]->getSkyLightArray(); @@ -254,7 +254,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ return $skyLight; } - public function getBlockLightArray(){ + public function &getBlockLightArray(){ $blockLight = ""; for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ $blockLight .= $this->sections[$y]->getLightArray(); diff --git a/src/pocketmine/level/format/generic/BaseFullChunk.php b/src/pocketmine/level/format/generic/BaseFullChunk.php index 0014904bd..063749afd 100644 --- a/src/pocketmine/level/format/generic/BaseFullChunk.php +++ b/src/pocketmine/level/format/generic/BaseFullChunk.php @@ -82,7 +82,7 @@ abstract class BaseFullChunk implements FullChunk{ * @param Compound[] $entities * @param Compound[] $tiles */ - protected function __construct($provider, $x, $z, $blocks, $data, $skyLight, $blockLight, $biomeIds = null, array $biomeColors = [], array $heightMap = [], array $entities = [], array $tiles = []){ + protected function __construct($provider, $x, $z, &$blocks, &$data, &$skyLight, &$blockLight, &$biomeIds = null, array $biomeColors = [], array $heightMap = [], array $entities = [], array $tiles = []){ $this->provider = $provider; $this->x = (int) $x; $this->z = (int) $z; diff --git a/src/pocketmine/level/format/leveldb/Chunk.php b/src/pocketmine/level/format/leveldb/Chunk.php index 40d7fe93b..921501ebc 100644 --- a/src/pocketmine/level/format/leveldb/Chunk.php +++ b/src/pocketmine/level/format/leveldb/Chunk.php @@ -32,7 +32,7 @@ class Chunk extends BaseFullChunk{ protected $isPopulated = false; protected $isGenerated = false; - public function __construct($level, $chunkX, $chunkZ, $terrain, array $entityData = null, array $tileData = null){ + public function __construct($level, $chunkX, $chunkZ, &$terrain, array $entityData = null, array $tileData = null){ $heightMap = array_fill(0, 256, 127); $offset = 0; diff --git a/src/pocketmine/network/Network.php b/src/pocketmine/network/Network.php index 7494c00c0..e3aa3d039 100644 --- a/src/pocketmine/network/Network.php +++ b/src/pocketmine/network/Network.php @@ -217,7 +217,7 @@ class Network{ if($pk->pid() === Info::BATCH_PACKET){ throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket"); } - $pk->setBuffer(substr($str, $offset)); + $pk->setBuffer($str, $offset); $pk->decode(); $p->handleDataPacket($pk); $offset += $pk->getOffset(); diff --git a/src/pocketmine/network/RakLibInterface.php b/src/pocketmine/network/RakLibInterface.php index 30a665408..ad2bd9b2f 100644 --- a/src/pocketmine/network/RakLibInterface.php +++ b/src/pocketmine/network/RakLibInterface.php @@ -147,10 +147,10 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{ $this->players[$identifier]->handleDataPacket($pk); } }catch(\Exception $e){ - if(\pocketmine\DEBUG > 1){ + if(\pocketmine\DEBUG > 1 and isset($pk)){ $logger = $this->server->getLogger(); if($logger instanceof MainLogger){ - //$logger->debug("Packet " . get_class($pk) . " 0x" . bin2hex($packet->buffer)); + $logger->debug("Packet " . get_class($pk) . " 0x" . bin2hex($packet->buffer)); $logger->logException($e); } } @@ -255,7 +255,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{ $data = new UnknownPacket(); $data->packetID = $pid; } - $data->setBuffer(substr($buffer, 1)); + $data->setBuffer($buffer, 1); return $data; } diff --git a/src/pocketmine/network/protocol/AddEntityPacket.php b/src/pocketmine/network/protocol/AddEntityPacket.php index e6b277e21..8f70184c8 100644 --- a/src/pocketmine/network/protocol/AddEntityPacket.php +++ b/src/pocketmine/network/protocol/AddEntityPacket.php @@ -65,7 +65,8 @@ class AddEntityPacket extends DataPacket{ $this->putFloat($this->speedZ); $this->putFloat($this->yaw); $this->putFloat($this->pitch); - $this->put(Binary::writeMetadata($this->metadata)); + $meta = Binary::writeMetadata($this->metadata); + $this->put($meta); $this->putShort(count($this->links)); foreach($this->links as $link){ $this->putLong($link[0]); diff --git a/src/pocketmine/network/protocol/AddPlayerPacket.php b/src/pocketmine/network/protocol/AddPlayerPacket.php index a4347b0a5..f1cc2c2af 100644 --- a/src/pocketmine/network/protocol/AddPlayerPacket.php +++ b/src/pocketmine/network/protocol/AddPlayerPacket.php @@ -78,7 +78,8 @@ class AddPlayerPacket extends DataPacket{ $this->putShort($this->meta); $this->putByte($this->slim ? 1 : 0); $this->putString($this->skin); - $this->put(Binary::writeMetadata($this->metadata)); + $meta = Binary::writeMetadata($this->metadata); + $this->put($meta); } } diff --git a/src/pocketmine/network/protocol/DataPacket.php b/src/pocketmine/network/protocol/DataPacket.php index e4723ed65..53571ab65 100644 --- a/src/pocketmine/network/protocol/DataPacket.php +++ b/src/pocketmine/network/protocol/DataPacket.php @@ -57,9 +57,9 @@ abstract class DataPacket extends \stdClass{ return $this->channel; } - public function setBuffer($buffer = ""){ + public function setBuffer(&$buffer = null, $offset = 0){ $this->buffer =& $buffer; - $this->offset = 0; + $this->offset = (int) $offset; } public function getOffset(){ @@ -81,7 +81,7 @@ abstract class DataPacket extends \stdClass{ return $len === 1 ? $this->buffer{$this->offset++} : substr($this->buffer, ($this->offset += $len) - $len, $len); } - protected function put($str){ + protected function put(&$str){ $this->buffer .= $str; } @@ -179,7 +179,7 @@ abstract class DataPacket extends \stdClass{ return $this->get($this->getShort()); } - protected function putString($v){ + protected function putString(&$v){ $this->putShort(strlen($v)); $this->put($v); } diff --git a/src/pocketmine/network/protocol/SetEntityDataPacket.php b/src/pocketmine/network/protocol/SetEntityDataPacket.php index 55178357e..539a5082d 100644 --- a/src/pocketmine/network/protocol/SetEntityDataPacket.php +++ b/src/pocketmine/network/protocol/SetEntityDataPacket.php @@ -46,7 +46,8 @@ class SetEntityDataPacket extends DataPacket{ public function encode(){ $this->reset(); $this->putLong($this->eid); - $this->put(Binary::writeMetadata($this->metadata)); + $meta = Binary::writeMetadata($this->metadata); + $this->put($meta); } }