Optimize get* operation

It's slightly faster to convert the value to signed value in PHP as
opposed to use pack and unpack.

For 1M get operation the difference is:

    getShort in 3.3272678852081 seconds
    getInt in 3.8338589668274 seconds
    getLong in 5.6381590366364 seconds
    getLong (neg) in 5.6149101257324 seconds

vs

    getShort in 2.7564418315887 seconds
    getInt in 3.1612701416016 seconds
    getLong in 3.1369340419769 seconds
    getLong (neg) in 3.1478710174561 seconds

And since pack("P") and unpack("q") has been removed now ByteBuffer
works for PHP >= 5.4
This commit is contained in:
Armen Baghumian 2015-12-04 06:10:11 +00:00
parent 77fbdd28e2
commit f622e5996c
2 changed files with 24 additions and 21 deletions

View File

@ -372,7 +372,11 @@ class ByteBuffer
{ {
$result = $this->readLittleEndian($index, 2); $result = $this->readLittleEndian($index, 2);
return self::convertHelper(self::__SHORT, $result); $sign = $index + (ByteBuffer::isLittleEndian() ? 1 : 0);
$issigned = isset($this->_buffer[$sign]) && ord($this->_buffer[$sign]) & 0x80;
// 65536 = 1 << 16 = Maximum unsigned 16-bit int
return $issigned ? $result - 65536 : $result;
} }
/** /**
@ -392,7 +396,11 @@ class ByteBuffer
{ {
$result = $this->readLittleEndian($index, 4); $result = $this->readLittleEndian($index, 4);
return self::convertHelper(self::__INT, $result); $sign = $index + (ByteBuffer::isLittleEndian() ? 3 : 0);
$issigned = isset($this->_buffer[$sign]) && ord($this->_buffer[$sign]) & 0x80;
// 4294967296 = 1 << 32 = Maximum unsigned 32-bit int
return $issigned ? $result - 4294967296 : $result;
} }
/** /**
@ -410,9 +418,7 @@ class ByteBuffer
*/ */
public function getLong($index) public function getLong($index)
{ {
$result = $this->readLittleEndian($index, 8); return $this->readLittleEndian($index, 8);
return self::convertHelper(self::__LONG, $result);
} }
/** /**
@ -459,22 +465,6 @@ class ByteBuffer
// see also: http://php.net/manual/en/function.pack.php // see also: http://php.net/manual/en/function.pack.php
switch ($type) { switch ($type) {
case self::__SHORT:
$helper = pack("v", $value);
$v = unpack("s", $helper);
return $v[1];
break;
case self::__INT:
$helper = pack("V", $value);
$v = unpack("l", $helper);
return $v[1];
break;
case self::__LONG:
$helper = pack("P", $value);
$v = unpack("q", $helper);
return $v[1];
break;
case self::__FLOAT: case self::__FLOAT:
$inthelper = pack("V", $value); $inthelper = pack("V", $value);
$v = unpack("f", $inthelper); $v = unpack("f", $inthelper);

View File

@ -539,6 +539,19 @@ function testByteBuffer(Assert $assert) {
$buffer[7] = chr(0x01); $buffer[7] = chr(0x01);
$uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer);
$assert->Equal(0x010203040A0B0C0D, $uut->getLong(0)); $assert->Equal(0x010203040A0B0C0D, $uut->getLong(0));
//Test: Signed Long
$buffer = str_repeat("\0", 8);
$buffer[0] = chr(0x00);
$buffer[1] = chr(0x00);
$buffer[2] = chr(0x00);
$buffer[3] = chr(0x00);
$buffer[4] = chr(0x00);
$buffer[5] = chr(0x00);
$buffer[6] = chr(0x00);
$buffer[7] = chr(0x80);
$uut = Google\FlatBuffers\ByteBuffer::wrap($buffer);
$assert->Equal(-1 << 63, $uut->getLong(0));
} }
//Test: ByteBuffer_GetLongChecksOffset //Test: ByteBuffer_GetLongChecksOffset