Anvil fixes, improved memory settings

This commit is contained in:
Shoghi Cervantes 2015-04-19 11:45:43 +02:00
parent 5860bdcc4d
commit e3c48b22cb
No known key found for this signature in database
GPG Key ID: 78464DB0A7837F89
16 changed files with 61 additions and 46 deletions

View File

@ -62,9 +62,9 @@ class MemoryManager{
private function init(){ private function init(){
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 320)) * 1024 * 1024; $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->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->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->garbageCollectionPeriod = (int) $this->server->getProperty("memory.garbage-collection.period", 12000);
$this->garbageCollectionTrigger = (bool) $this->server->getProperty("memory.garbage-collection.low-memory-trigger", true); $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); $this->server->getPluginManager()->callEvent($ev);
$cycles = 0;
if($this->garbageCollectionTrigger){ 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(){ public function check(){
@ -145,7 +146,6 @@ class MemoryManager{
public function triggerGarbageCollector(){ public function triggerGarbageCollector(){
Timings::$garbageCollectorTimer->startTiming(); Timings::$garbageCollectorTimer->startTiming();
gc_collect_cycles();
if($this->garbageCollectionAsync){ if($this->garbageCollectionAsync){
$size = $this->server->getScheduler()->getAsyncTaskPoolSize(); $size = $this->server->getScheduler()->getAsyncTaskPoolSize();
@ -154,6 +154,10 @@ class MemoryManager{
} }
} }
$cycles = gc_collect_cycles();
Timings::$garbageCollectorTimer->stopTiming(); Timings::$garbageCollectorTimer->stopTiming();
return $cycles;
} }
} }

View File

@ -33,10 +33,12 @@ class LowMemoryEvent extends ServerEvent{
private $memory; private $memory;
private $memoryLimit; private $memoryLimit;
private $triggerCount; private $triggerCount;
private $global;
public function __construct($memory, $memoryLimit, $triggerCount = 0){ public function __construct($memory, $memoryLimit, $isGlobal = false, $triggerCount = 0){
$this->memory = $memory; $this->memory = $memory;
$this->memoryLimit = $memoryLimit; $this->memoryLimit = $memoryLimit;
$this->global = (bool) $isGlobal;
$this->triggerCount = (int) $triggerCount; $this->triggerCount = (int) $triggerCount;
} }
@ -67,13 +69,20 @@ class LowMemoryEvent extends ServerEvent{
return $this->triggerCount; return $this->triggerCount;
} }
/**
* @return bool
*/
public function isGlobal(){
return $this->global;
}
/** /**
* Amount of memory already freed * Amount of memory already freed
* *
* @return int * @return int
*/ */
public function getMemoryFreed(){ public function getMemoryFreed(){
return $this->getMemory() - Utils::getMemoryUsage(); return $this->getMemory() - ($this->isGlobal() ? Utils::getMemoryUsage(true)[1] : Utils::getMemoryUsage(true)[0]);
} }
} }

View File

@ -2200,10 +2200,6 @@ class Level implements ChunkManager, Metadatable{
unset($this->chunkTickList[$index]); unset($this->chunkTickList[$index]);
unset($this->chunkCache[$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(); $this->timings->doChunkUnload->stopTiming();
return true; return true;

View File

@ -135,7 +135,7 @@ class Chunk extends BaseChunk{
* *
* @return Chunk * @return Chunk
*/ */
public static function fromBinary($data, LevelProvider $provider = null){ public static function fromBinary(&$data, LevelProvider $provider = null){
$nbt = new NBT(NBT::BIG_ENDIAN); $nbt = new NBT(NBT::BIG_ENDIAN);
try{ try{
@ -152,7 +152,7 @@ class Chunk extends BaseChunk{
} }
} }
public function toBinary(){ public function &toBinary(){
$nbt = clone $this->getNBT(); $nbt = clone $this->getNBT();
$nbt->xPos = new Int("xPos", $this->x); $nbt->xPos = new Int("xPos", $this->x);

View File

@ -133,7 +133,8 @@ class ChunkRequestTask extends AsyncTask{
public function onCompletion(Server $server){ public function onCompletion(Server $server){
$level = $server->getLevel($this->levelId); $level = $server->getLevel($this->levelId);
if($level instanceof Level and $this->hasResult()){ 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);
} }
} }

View File

@ -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; $i = ($z << 4) + $x;
$column = ""; $column = "";
for($y = 0; $y < 16; ++$y){ for($y = 0; $y < 16; ++$y){
@ -165,7 +165,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
return $column; return $column;
} }
public function getBlockDataColumn($x, $z){ public function &getBlockDataColumn($x, $z){
$i = ($z << 3) + ($x >> 1); $i = ($z << 3) + ($x >> 1);
$column = ""; $column = "";
if(($x & 1) === 0){ if(($x & 1) === 0){
@ -181,7 +181,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
return $column; return $column;
} }
public function getBlockSkyLightColumn($x, $z){ public function &getBlockSkyLightColumn($x, $z){
$i = ($z << 3) + ($x >> 1); $i = ($z << 3) + ($x >> 1);
$column = ""; $column = "";
if(($x & 1) === 0){ if(($x & 1) === 0){
@ -197,7 +197,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
return $column; return $column;
} }
public function getBlockLightColumn($x, $z){ public function &getBlockLightColumn($x, $z){
$i = ($z << 3) + ($x >> 1); $i = ($z << 3) + ($x >> 1);
$column = ""; $column = "";
if(($x & 1) === 0){ if(($x & 1) === 0){
@ -213,19 +213,19 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
return $column; return $column;
} }
public function getIdArray(){ public function &getIdArray(){
return $this->blocks; return $this->blocks;
} }
public function getDataArray(){ public function &getDataArray(){
return $this->data; return $this->data;
} }
public function getSkyLightArray(){ public function &getSkyLightArray(){
return $this->skyLight; return $this->skyLight;
} }
public function getLightArray(){ public function &getLightArray(){
return $this->blockLight; return $this->blockLight;
} }

View File

@ -101,7 +101,8 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{
return null; 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){ if($chunk instanceof Chunk){
return $chunk; return $chunk;
}elseif($forward === false){ }elseif($forward === false){
@ -123,7 +124,8 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{
$nbt->TerrainPopulated = new Byte("TerrainPopulated", 0); $nbt->TerrainPopulated = new Byte("TerrainPopulated", 0);
$nbt->V = new Byte("V", self::VERSION); $nbt->V = new Byte("V", self::VERSION);
$nbt->InhabitedTime = new Long("InhabitedTime", 0); $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->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->HeightMap = new IntArray("HeightMap", array_fill(0, 256, 127));
$nbt->Sections = new Enum("Sections", []); $nbt->Sections = new Enum("Sections", []);

View File

@ -165,7 +165,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
} }
} }
public function getBlockIdColumn($x, $z){ public function &getBlockIdColumn($x, $z){
$column = ""; $column = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$column .= $this->sections[$y]->getBlockIdColumn($x, $z); $column .= $this->sections[$y]->getBlockIdColumn($x, $z);
@ -174,7 +174,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $column; return $column;
} }
public function getBlockDataColumn($x, $z){ public function &getBlockDataColumn($x, $z){
$column = ""; $column = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$column .= $this->sections[$y]->getBlockDataColumn($x, $z); $column .= $this->sections[$y]->getBlockDataColumn($x, $z);
@ -183,7 +183,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $column; return $column;
} }
public function getBlockSkyLightColumn($x, $z){ public function &getBlockSkyLightColumn($x, $z){
$column = ""; $column = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$column .= $this->sections[$y]->getBlockSkyLightColumn($x, $z); $column .= $this->sections[$y]->getBlockSkyLightColumn($x, $z);
@ -192,7 +192,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $column; return $column;
} }
public function getBlockLightColumn($x, $z){ public function &getBlockLightColumn($x, $z){
$column = ""; $column = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$column .= $this->sections[$y]->getBlockLightColumn($x, $z); $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; return $this->getProvider() === null ? false : $this->getProvider()->getChunk($this->getX(), $this->getZ(), true) instanceof Chunk;
} }
public function getBlockIdArray(){ public function &getBlockIdArray(){
$blocks = ""; $blocks = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$blocks .= $this->sections[$y]->getIdArray(); $blocks .= $this->sections[$y]->getIdArray();
@ -236,7 +236,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $blocks; return $blocks;
} }
public function getBlockDataArray(){ public function &getBlockDataArray(){
$data = ""; $data = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$data .= $this->sections[$y]->getDataArray(); $data .= $this->sections[$y]->getDataArray();
@ -245,7 +245,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $data; return $data;
} }
public function getBlockSkyLightArray(){ public function &getBlockSkyLightArray(){
$skyLight = ""; $skyLight = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$skyLight .= $this->sections[$y]->getSkyLightArray(); $skyLight .= $this->sections[$y]->getSkyLightArray();
@ -254,7 +254,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{
return $skyLight; return $skyLight;
} }
public function getBlockLightArray(){ public function &getBlockLightArray(){
$blockLight = ""; $blockLight = "";
for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){ for($y = 0; $y < Chunk::SECTION_COUNT; ++$y){
$blockLight .= $this->sections[$y]->getLightArray(); $blockLight .= $this->sections[$y]->getLightArray();

View File

@ -82,7 +82,7 @@ abstract class BaseFullChunk implements FullChunk{
* @param Compound[] $entities * @param Compound[] $entities
* @param Compound[] $tiles * @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->provider = $provider;
$this->x = (int) $x; $this->x = (int) $x;
$this->z = (int) $z; $this->z = (int) $z;

View File

@ -32,7 +32,7 @@ class Chunk extends BaseFullChunk{
protected $isPopulated = false; protected $isPopulated = false;
protected $isGenerated = 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); $heightMap = array_fill(0, 256, 127);
$offset = 0; $offset = 0;

View File

@ -217,7 +217,7 @@ class Network{
if($pk->pid() === Info::BATCH_PACKET){ if($pk->pid() === Info::BATCH_PACKET){
throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket"); throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket");
} }
$pk->setBuffer(substr($str, $offset)); $pk->setBuffer($str, $offset);
$pk->decode(); $pk->decode();
$p->handleDataPacket($pk); $p->handleDataPacket($pk);
$offset += $pk->getOffset(); $offset += $pk->getOffset();

View File

@ -147,10 +147,10 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
$this->players[$identifier]->handleDataPacket($pk); $this->players[$identifier]->handleDataPacket($pk);
} }
}catch(\Exception $e){ }catch(\Exception $e){
if(\pocketmine\DEBUG > 1){ if(\pocketmine\DEBUG > 1 and isset($pk)){
$logger = $this->server->getLogger(); $logger = $this->server->getLogger();
if($logger instanceof MainLogger){ 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); $logger->logException($e);
} }
} }
@ -255,7 +255,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
$data = new UnknownPacket(); $data = new UnknownPacket();
$data->packetID = $pid; $data->packetID = $pid;
} }
$data->setBuffer(substr($buffer, 1)); $data->setBuffer($buffer, 1);
return $data; return $data;
} }

View File

@ -65,7 +65,8 @@ class AddEntityPacket extends DataPacket{
$this->putFloat($this->speedZ); $this->putFloat($this->speedZ);
$this->putFloat($this->yaw); $this->putFloat($this->yaw);
$this->putFloat($this->pitch); $this->putFloat($this->pitch);
$this->put(Binary::writeMetadata($this->metadata)); $meta = Binary::writeMetadata($this->metadata);
$this->put($meta);
$this->putShort(count($this->links)); $this->putShort(count($this->links));
foreach($this->links as $link){ foreach($this->links as $link){
$this->putLong($link[0]); $this->putLong($link[0]);

View File

@ -78,7 +78,8 @@ class AddPlayerPacket extends DataPacket{
$this->putShort($this->meta); $this->putShort($this->meta);
$this->putByte($this->slim ? 1 : 0); $this->putByte($this->slim ? 1 : 0);
$this->putString($this->skin); $this->putString($this->skin);
$this->put(Binary::writeMetadata($this->metadata)); $meta = Binary::writeMetadata($this->metadata);
$this->put($meta);
} }
} }

View File

@ -57,9 +57,9 @@ abstract class DataPacket extends \stdClass{
return $this->channel; return $this->channel;
} }
public function setBuffer($buffer = ""){ public function setBuffer(&$buffer = null, $offset = 0){
$this->buffer =& $buffer; $this->buffer =& $buffer;
$this->offset = 0; $this->offset = (int) $offset;
} }
public function getOffset(){ 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); 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; $this->buffer .= $str;
} }
@ -179,7 +179,7 @@ abstract class DataPacket extends \stdClass{
return $this->get($this->getShort()); return $this->get($this->getShort());
} }
protected function putString($v){ protected function putString(&$v){
$this->putShort(strlen($v)); $this->putShort(strlen($v));
$this->put($v); $this->put($v);
} }

View File

@ -46,7 +46,8 @@ class SetEntityDataPacket extends DataPacket{
public function encode(){ public function encode(){
$this->reset(); $this->reset();
$this->putLong($this->eid); $this->putLong($this->eid);
$this->put(Binary::writeMetadata($this->metadata)); $meta = Binary::writeMetadata($this->metadata);
$this->put($meta);
} }
} }