Added MemoryManager, new memory properties, improved performance, updated RakLib, fixed misc. bugs

This commit is contained in:
Shoghi Cervantes
2015-04-18 20:13:52 +02:00
parent ddc152ae0a
commit b2c25eaf36
32 changed files with 652 additions and 164 deletions

View File

@ -93,12 +93,10 @@ use pocketmine\scheduler\AsyncTask;
use pocketmine\Server;
use pocketmine\tile\Chest;
use pocketmine\tile\Tile;
use pocketmine\utils\Cache;
use pocketmine\utils\LevelException;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Random;
use pocketmine\utils\ReversePriorityQueue;
use pocketmine\utils\TextFormat;
use pocketmine\level\particle\Particle;
use pocketmine\level\sound\Sound;
use pocketmine\entity\Effect;
@ -145,6 +143,8 @@ class Level implements ChunkManager, Metadatable{
private $cacheChunks = false;
private $sendTimeTicker = 0;
/** @var Server */
private $server;
@ -512,6 +512,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function freeChunk($X, $Z, Player $player){
unset($this->usedChunks[$index = Level::chunkHash($X, $Z)][$player->getId()]);
$this->unloadChunkRequest($X, $Z, true);
}
@ -553,8 +554,9 @@ class Level implements ChunkManager, Metadatable{
$this->checkTime();
if(($currentTick % 200) === 0){
if(++$this->sendTimeTicker === 200){
$this->sendTime();
$this->sendTimeTicker = 0;
}
$this->unloadChunks();
@ -646,7 +648,11 @@ class Level implements ChunkManager, Metadatable{
Server::broadcastPacket($target, $pk->setChannel(Network::CHANNEL_BLOCKS));
}
public function clearCache(){
public function clearCache($full = false){
if($full){
$this->chunkCache = [];
}
$this->blockCache = [];
}
@ -1987,11 +1993,11 @@ class Level implements ChunkManager, Metadatable{
}
}
public function chunkRequestCallback($x, $z, $payload){
public function chunkRequestCallback($x, $z, &$payload){
$index = Level::chunkHash($x, $z);
if(!isset($this->chunkCache[$index]) and $this->cacheChunks){
$this->chunkCache[$index] = $payload;
if(!isset($this->chunkCache[$index]) and $this->cacheChunks and $this->server->getMemoryManager()->canUseChunkCache()){
$this->chunkCache[$index] =& $payload;
}
if(isset($this->chunkSendTasks[$index])){
@ -2077,7 +2083,7 @@ class Level implements ChunkManager, Metadatable{
* @return bool
*/
public function isChunkInUse($x, $z){
return isset($this->usedChunks[Level::chunkHash($x, $z)]) and count($this->usedChunks[Level::chunkHash($x, $z)]) > 0;
return isset($this->usedChunks[$index = Level::chunkHash($x, $z)]) and count($this->usedChunks[$index]) > 0;
}
/**
@ -2118,6 +2124,8 @@ class Level implements ChunkManager, Metadatable{
return false;
}
$chunk->setChanged(false);
return true;
}
@ -2145,6 +2153,10 @@ class Level implements ChunkManager, Metadatable{
return false;
}
if(!$this->isChunkLoaded($x, $z)){
return true;
}
$this->timings->doChunkUnload->startTiming();
$index = Level::chunkHash($x, $z);
@ -2154,6 +2166,7 @@ class Level implements ChunkManager, Metadatable{
if($chunk !== null and $chunk->getProvider() !== null){
$this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk));
if($ev->isCancelled()){
$this->timings->doChunkUnload->stopTiming();
return false;
}
}
@ -2187,6 +2200,10 @@ 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;

View File

@ -288,25 +288,25 @@ interface FullChunk{
/**
* @return string[]
*/
public function getBiomeIdArray();
public function &getBiomeIdArray();
/**
* @return int[]
*/
public function getBiomeColorArray();
public function &getBiomeColorArray();
/**
* @return int[]
*/
public function getHeightMapArray();
public function &getHeightMapArray();
public function getBlockIdArray();
public function &getBlockIdArray();
public function getBlockDataArray();
public function &getBlockDataArray();
public function getBlockSkyLightArray();
public function &getBlockSkyLightArray();
public function getBlockLightArray();
public function &getBlockLightArray();
public function toBinary();
@ -328,7 +328,7 @@ interface FullChunk{
*
* @return FullChunk
*/
public static function fromBinary($data, LevelProvider $provider = null);
public static function fromBinary(&$data, LevelProvider $provider = null);
/**
* @param string $data
@ -336,6 +336,6 @@ interface FullChunk{
*
* @return FullChunk
*/
public static function fromFastBinary($data, LevelProvider $provider = null);
public static function fromFastBinary(&$data, LevelProvider $provider = null);
}

View File

@ -87,13 +87,13 @@ abstract class BaseFullChunk implements FullChunk{
$this->x = (int) $x;
$this->z = (int) $z;
$this->blocks = $blocks;
$this->data = $data;
$this->skyLight = $skyLight;
$this->blockLight = $blockLight;
$this->blocks =& $blocks;
$this->data =& $data;
$this->skyLight =& $skyLight;
$this->blockLight =& $blockLight;
if(strlen($biomeIds) === 256){
$this->biomeIds = $biomeIds;
$this->biomeIds =& $biomeIds;
}else{
$this->biomeIds = str_repeat("\x01", 256);
}
@ -321,31 +321,31 @@ abstract class BaseFullChunk implements FullChunk{
return true;
}
public function getBlockIdArray(){
public function &getBlockIdArray(){
return $this->blocks;
}
public function getBlockDataArray(){
public function &getBlockDataArray(){
return $this->data;
}
public function getBlockSkyLightArray(){
public function &getBlockSkyLightArray(){
return $this->skyLight;
}
public function getBlockLightArray(){
public function &getBlockLightArray(){
return $this->blockLight;
}
public function getBiomeIdArray(){
public function &getBiomeIdArray(){
return $this->biomeIds;
}
public function getBiomeColorArray(){
public function &getBiomeColorArray(){
return $this->biomeColors;
}
public function getHeightMapArray(){
public function &getHeightMapArray(){
return $this->heightMap;
}
@ -357,11 +357,11 @@ abstract class BaseFullChunk implements FullChunk{
$this->hasChanged = (bool) $changed;
}
public static function fromFastBinary($data, LevelProvider $provider = null){
public static function &fromFastBinary(&$data, LevelProvider $provider = null){
static::fromBinary($data, $provider);
}
public function toFastBinary(){
public function &toFastBinary(){
return $this->toBinary();
}

View File

@ -221,7 +221,7 @@ class Chunk extends BaseFullChunk{
$this->isGenerated = (bool) $value;
}
public static function fromFastBinary($data, LevelProvider $provider = null){
public static function fromFastBinary(&$data, LevelProvider $provider = null){
return self::fromBinary($data, $provider);
}
@ -231,7 +231,7 @@ class Chunk extends BaseFullChunk{
*
* @return Chunk
*/
public static function fromBinary($data, LevelProvider $provider = null){
public static function fromBinary(&$data, LevelProvider $provider = null){
try{
$chunkX = Binary::readLInt(substr($data, 0, 4));
$chunkZ = Binary::readLInt(substr($data, 4, 4));

View File

@ -276,7 +276,7 @@ class Chunk extends BaseFullChunk{
*
* @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{
@ -293,7 +293,7 @@ class Chunk extends BaseFullChunk{
}
}
public static function fromFastBinary($data, LevelProvider $provider = null){
public static function fromFastBinary(&$data, LevelProvider $provider = null){
try{
$offset = 0;
@ -340,11 +340,11 @@ class Chunk extends BaseFullChunk{
}
}
public function toFastBinary(){
public function &toFastBinary(){
$biomeColors = pack("N*", ...$this->getBiomeColorArray());
$heightMap = pack("N*", ...$this->getHeightMapArray());
return
$data =
Binary::writeInt($this->x) .
Binary::writeInt($this->z) .
$this->getBlockIdArray() .
@ -355,9 +355,10 @@ class Chunk extends BaseFullChunk{
$biomeColors .
$heightMap .
chr(($this->isPopulated() ? 1 << 1 : 0) + ($this->isGenerated() ? 1 : 0));
return $data;
}
public function toBinary(){
public function &toBinary(){
$nbt = clone $this->getNBT();
$nbt->xPos = new Int("xPos", $this->x);
@ -400,7 +401,8 @@ class Chunk extends BaseFullChunk{
$nbt->setName("Level");
$writer->setData(new Compound("", ["Level" => $nbt]));
return $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL);
$data =& $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL);
return $data;
}
/**

View File

@ -130,7 +130,8 @@ class 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){
@ -156,12 +157,15 @@ class 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->HeightMap = new IntArray("HeightMap", array_fill(0, 256, 127));
$nbt->BiomeColors = new IntArray("BiomeColors", array_fill(0, 256, Binary::readInt("\x00\x85\xb2\x4a")));
$nbt->Blocks = new ByteArray("Blocks", str_repeat("\x00", 32768));
$nbt->Data = new ByteArray("Data", $half = str_repeat("\x00", 16384));
$half = str_repeat("\x00", 16384);
$full = $half . $half;
$nbt->Blocks = new ByteArray("Blocks", $full);
$nbt->Data = new ByteArray("Data", $half);
$nbt->SkyLight = new ByteArray("SkyLight", $half);
$nbt->BlockLight = new ByteArray("BlockLight", $half);
@ -181,7 +185,7 @@ class RegionLoader{
}
}
protected function saveChunk($x, $z, $chunkData){
protected function saveChunk($x, $z, &$chunkData){
$length = strlen($chunkData) + 1;
if($length + 4 > self::MAX_SECTOR_LENGTH){
throw new ChunkException("Chunk is too big! ".($length + 4)." > ".self::MAX_SECTOR_LENGTH);
@ -208,7 +212,7 @@ class RegionLoader{
public function writeChunk(FullChunk $chunk){
$this->lastUsed = time();
$chunkData = $chunk->toBinary();
$chunkData = &$chunk->toBinary();
if($chunkData !== false){
$this->saveChunk($chunk->getX() - ($this->getX() * 32), $chunk->getZ() - ($this->getZ() * 32), $chunkData);
}