From 1174b0c45cc9a190a3b4175c1e7659dabbac9dc5 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Wed, 10 Sep 2014 12:13:15 +0200 Subject: [PATCH] Added binary reading optimizations, faster 64-bit reading --- .../network/protocol/DataPacket.php | 4 +- src/pocketmine/utils/Binary.php | 122 ++++++++++-------- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/src/pocketmine/network/protocol/DataPacket.php b/src/pocketmine/network/protocol/DataPacket.php index f322d2270..94cf586d0 100644 --- a/src/pocketmine/network/protocol/DataPacket.php +++ b/src/pocketmine/network/protocol/DataPacket.php @@ -68,8 +68,8 @@ abstract class DataPacket extends \stdClass{ $this->buffer .= $str; } - protected function getLong($signed = true){ - return Binary::readLong($this->get(8), $signed); + protected function getLong(){ + return Binary::readLong($this->get(8)); } protected function putLong($v){ diff --git a/src/pocketmine/utils/Binary.php b/src/pocketmine/utils/Binary.php index fe474216a..7248db4b3 100644 --- a/src/pocketmine/utils/Binary.php +++ b/src/pocketmine/utils/Binary.php @@ -41,9 +41,7 @@ class Binary{ * @return mixed */ public static function readTriad($str){ - list(, $unpacked) = @unpack("N", "\x00" . $str); - - return $unpacked; + return @unpack("N", "\x00" . $str)[1]; } /** @@ -206,11 +204,16 @@ class Binary{ */ public static function readByte($c, $signed = true){ $b = ord($c{0}); - if($signed === true and ($b & 0x80) === 0x80){ //calculate Two's complement - $b = -0x80 + ($b & 0x7f); - } - return $b; + if($signed){ + if(PHP_INT_SIZE === 8){ + return $b << 56 >> 56; + }else{ + return $b << 24 >> 24; + } + }else{ + return $b; + } } /** @@ -221,10 +224,6 @@ class Binary{ * @return string */ public static function writeByte($c){ - if($c < 0 and $c >= -0x80){ - $c = 0xff + $c + 1; - } - return chr($c); } @@ -238,11 +237,16 @@ class Binary{ */ public static function readShort($str, $signed = true){ $unpacked = @unpack("n", $str)[1]; - if($unpacked > 0x7fff and $signed === true){ - $unpacked -= 0x10000; // Convert unsigned short to signed short - } - return $unpacked; + if($signed){ + if(PHP_INT_SIZE === 8){ + return $unpacked << 48 >> 48; + }else{ + return $unpacked << 16 >> 16; + } + }else{ + return $unpacked; + } } /** @@ -253,10 +257,6 @@ class Binary{ * @return string */ public static function writeShort($value){ - if($value < 0){ - $value += 0x10000; - } - return pack("n", $value); } @@ -270,11 +270,16 @@ class Binary{ */ public static function readLShort($str, $signed = true){ $unpacked = @unpack("v", $str)[1]; - if($unpacked > 0x7fff and $signed === true){ - $unpacked -= 0x10000; // Convert unsigned short to signed short - } - return $unpacked; + if($signed){ + if(PHP_INT_SIZE === 8){ + return $unpacked << 48 >> 48; + }else{ + return $unpacked << 16 >> 16; + } + }else{ + return $unpacked; + } } /** @@ -285,20 +290,15 @@ class Binary{ * @return string */ public static function writeLShort($value){ - if($value < 0){ - $value += 0x10000; - } - return pack("v", $value); } public static function readInt($str){ - $unpacked = @unpack("N", $str)[1]; - if($unpacked > 2147483647){ - $unpacked -= 4294967296; + if(PHP_INT_SIZE === 8){ + return @unpack("N", $str)[1] << 32 >> 32; + }else{ + return @unpack("N", $str)[1]; } - - return (int) $unpacked; } public static function writeInt($value){ @@ -306,12 +306,11 @@ class Binary{ } public static function readLInt($str){ - $unpacked = @unpack("V", $str)[1]; - if($unpacked >= 2147483648){ - $unpacked -= 4294967296; + if(PHP_INT_SIZE === 8){ + return @unpack("V", $str)[1] << 32 >> 32; + }else{ + return @unpack("V", $str)[1]; } - - return (int) $unpacked; } public static function writeLInt($value){ @@ -354,33 +353,42 @@ class Binary{ return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack("d", $value)) : pack("d", $value); } - public static function readLong($x, $signed = true){ - $value = "0"; - for($i = 0; $i < 8; $i += 2){ - $value = bcmul($value, "65536", 0); - $value = bcadd($value, self::readShort(substr($x, $i, 2), false), 0); - } + public static function readLong($x){ + if(PHP_INT_SIZE === 8){ + list(, $int1, $int2) = @unpack("N*", $x); + return ($int1 << 32) | $int2; + }else{ + $value = "0"; + for($i = 0; $i < 8; $i += 2){ + $value = bcmul($value, "65536", 0); + $value = bcadd($value, self::readShort(substr($x, $i, 2), false), 0); + } - if($signed === true and bccomp($value, "9223372036854775807") == 1){ - $value = bcadd($value, "-18446744073709551616"); - } + if(bccomp($value, "9223372036854775807") == 1){ + $value = bcadd($value, "-18446744073709551616"); + } - return $value; + return $value; + } } public static function writeLong($value){ - $x = ""; + if(PHP_INT_SIZE === 8){ + return pack("NN", $value >> 32, $value & 0xFFFFFFFF); + }else{ + $x = ""; - if(bccomp($value, "0") == -1){ - $value = bcadd($value, "18446744073709551616"); + if(bccomp($value, "0") == -1){ + $value = bcadd($value, "18446744073709551616"); + } + + $x .= self::writeShort(bcmod(bcdiv($value, "281474976710656"), "65536")); + $x .= self::writeShort(bcmod(bcdiv($value, "4294967296"), "65536")); + $x .= self::writeShort(bcmod(bcdiv($value, "65536"), "65536")); + $x .= self::writeShort(bcmod($value, "65536")); + + return $x; } - - $x .= self::writeShort(bcmod(bcdiv($value, "281474976710656"), "65536")); - $x .= self::writeShort(bcmod(bcdiv($value, "4294967296"), "65536")); - $x .= self::writeShort(bcmod(bcdiv($value, "65536"), "65536")); - $x .= self::writeShort(bcmod($value, "65536")); - - return $x; } public static function readLLong($str){