Created
October 14, 2022 14:47
-
-
Save SerafimArts/7d223310d55c330fa0da72f982ddc0f7 to your computer and use it in GitHub Desktop.
Revisions
-
SerafimArts created this gist
Oct 14, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,79 @@ benchInt8 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 0.972μs | ±22.36% | | PackBench | pack | 1.336μs | ±25.69% | +-----------+------+---------+---------+ benchUInt8 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 0.729μs | ±21.43% | | PackBench | pack | 1.369μs | ±24.68% | +-----------+------+---------+---------+ benchInt16 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.461μs | ±18.23% | | PackBench | pack | 1.345μs | ±24.70% | +-----------+------+---------+---------+ benchUInt16 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.275μs | ±25.66% | | PackBench | pack | 1.756μs | ±18.53% | +-----------+------+---------+---------+ benchInt32 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 2.033μs | ±19.11% | | PackBench | pack | 1.386μs | ±28.92% | +-----------+------+---------+---------+ benchUInt32 +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.828μs | ±25.15% | | PackBench | pack | 1.795μs | ±3.83% | +-----------+------+---------+---------+ benchInt64 (insignificant benchmark: Code is identical) +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.358μs | ±27.14% | | PackBench | pack | 1.363μs | ±28.97% | +-----------+------+---------+---------+ benchUInt64 (insignificant benchmark: Code is identical) +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.751μs | ±25.10% | | PackBench | pack | 1.779μs | ±27.52% | +-----------+------+---------+---------+ benchFloat32 (insignificant benchmark: Code is identical) +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.764μs | ±21.66% | | PackBench | pack | 1.766μs | ±27.28% | +-----------+------+---------+---------+ benchFloat64 (insignificant benchmark: Code is identical) +-----------+------+---------+---------+ | benchmark | set | mode | rstdev | +-----------+------+---------+---------+ | PackBench | raw | 1.761μs | ±24.82% | | PackBench | pack | 1.763μs | ±25.70% | +-----------+------+---------+---------+ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,265 @@ <?php declare(strict_types=1); namespace Bic\Bin; final class Converter implements ParserInterface, SerializerInterface { private Endianness $endianness; public function __construct( Endianness $endianness = null ) { $this->endianness = $endianness ?? Endianness::current(); } /** * {@inheritDoc} */ public function toInt8(string $data): int { $value = \ord($data[0]); return $value & 0x80 ? $value - 0x100 : $value; } /** * {@inheritDoc} */ public function fromInt8(int $data): string { return \chr($data); } /** * {@inheritDoc} */ public function toUInt8(string $data): int { return \ord($data); } /** * {@inheritDoc} */ public function fromUInt8(int $data): string { return \chr($data); } /** * {@inheritDoc} */ public function toInt16(string $data): int { $value = \ord($data[0]) | \ord($data[1]) << 8; return \ord($data[1]) & 0x80 ? $value - 0x1_0000 : $value; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromInt16(int $data): string { return \pack('s', $data); } /** * {@inheritDoc} */ public function toUInt16(string $data, Endianness $endianness = null): int { if (($endianness ?? $this->endianness) === Endianness::LITTLE) { return \ord($data[0]) | (\ord($data[1]) << 8); } return \ord($data[1]) | (\ord($data[0]) << 8); } /** * {@inheritDoc} */ public function fromUInt16(int $data, Endianness $endianness = null): string { if (($endianness ?? $this->endianness) === Endianness::LITTLE) { return \chr($data >> 0) . \chr($data >> 8); } return \chr($data >> 8) . \chr($data >> 0); } /** * {@inheritDoc} */ public function toInt32(string $data): int { $value = \ord($data[0]) | \ord($data[1]) << 8 | \ord($data[2]) << 16 | \ord($data[3]) << 24; return \ord($data[3]) & 0x80 ? $value - 0x1_0000_0000 : $value; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromInt32(int $data): string { return \pack('l', $data); } /** * {@inheritDoc} */ public function toUInt32(string $data, Endianness $endianness = null): int { if (($endianness ?? $this->endianness) === Endianness::LITTLE) { return \ord($data[0]) | \ord($data[1]) << 8 | \ord($data[2]) << 16 | \ord($data[3]) << 24; } return \ord($data[3]) | \ord($data[2]) << 8 | \ord($data[1]) << 16 | \ord($data[0]) << 24; } /** * {@inheritDoc} */ public function fromUInt32(int $data, Endianness $endianness = null): string { if (($endianness ?? $this->endianness) === Endianness::LITTLE) { return \chr($data >> 0) . \chr($data >> 8) . \chr($data >> 16) . \chr($data >> 24); } return \chr($data >> 24) . \chr($data >> 16) . \chr($data >> 8) . \chr($data >> 0); } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function toInt64(string $data): int { [1 => $int64] = \unpack('q', $data); return $int64; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromInt64(int $data): string { return \pack('q', $data); } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function toUInt64(string $data, Endianness $endianness = null): int { [1 => $uint64] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'P', Endianness::BIG => 'J', default => 'Q', }, $data); return $uint64; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromUInt64(int $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'P', Endianness::BIG => 'J', default => 'Q', }, $data); } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function toFloat32(string $data, Endianness $endianness = null): float { [1 => $float] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'g', Endianness::BIG => 'G', default => 'f', }, $data); return $float; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromFloat32(float $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'g', Endianness::BIG => 'G', default => 'f', }, $data); } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function toFloat64(string $data, Endianness $endianness = null): float { [1 => $double] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'e', Endianness::BIG => 'E', default => 'd', }, $data); return $double; } /** * TODO Replace pack/unpack to optimized binary algo * * {@inheritDoc} */ public function fromFloat64(float $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'e', Endianness::BIG => 'E', default => 'd', }, $data); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,236 @@ <?php declare(strict_types=1); namespace Bic\Bin; final class NativeConverter implements ParserInterface, SerializerInterface { private Endianness $endianness; public function __construct( Endianness $endianness = null ) { $this->endianness = $endianness ?? Endianness::current(); } /** * {@inheritDoc} */ public function toInt8(string $data): int { [1 => $int8] = \unpack('c', $data); return $int8; } /** * {@inheritDoc} */ public function fromInt8(int $data): string { return \pack('c', $data); } /** * {@inheritDoc} */ public function toUInt8(string $data): int { [1 => $uint8] = \unpack('C', $data); return $uint8; } /** * {@inheritDoc} */ public function fromUInt8(int $data): string { return \pack('C', $data); } /** * {@inheritDoc} */ public function toInt16(string $data): int { [1 => $int16] = \unpack('s', $data); return $int16; } /** * {@inheritDoc} */ public function fromInt16(int $data): string { return \pack('s', $data); } /** * {@inheritDoc} */ public function toUInt16(string $data, Endianness $endianness = null): int { [1 => $uint16] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'v', Endianness::BIG => 'n', default => 'S', }, $data); return $uint16; } /** * {@inheritDoc} */ public function fromUInt16(int $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'v', Endianness::BIG => 'n', default => 'S', }, $data); } /** * {@inheritDoc} */ public function toInt32(string $data): int { [1 => $int32] = \unpack('l', $data); return $int32; } /** * {@inheritDoc} */ public function fromInt32(int $data): string { return \pack('l', $data); } /** * {@inheritDoc} */ public function toUInt32(string $data, Endianness $endianness = null): int { [1 => $uint32] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'V', Endianness::BIG => 'N', default => 'L', }, $data); return $uint32; } /** * {@inheritDoc} */ public function fromUInt32(int $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'V', Endianness::BIG => 'N', default => 'L', }, $data); } /** * {@inheritDoc} */ public function toInt64(string $data): int { [1 => $int64] = \unpack('q', $data); return $int64; } /** * {@inheritDoc} */ public function fromInt64(int $data): string { return \pack('q', $data); } /** * {@inheritDoc} */ public function toUInt64(string $data, Endianness $endianness = null): int { [1 => $uint64] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'P', Endianness::BIG => 'J', default => 'Q', }, $data); return $uint64; } /** * {@inheritDoc} */ public function fromUInt64(int $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'P', Endianness::BIG => 'J', default => 'Q', }, $data); } /** * {@inheritDoc} */ public function toFloat32(string $data, Endianness $endianness = null): float { [1 => $float] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'g', Endianness::BIG => 'G', default => 'f', }, $data); return $float; } /** * {@inheritDoc} */ public function fromFloat32(float $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'g', Endianness::BIG => 'G', default => 'f', }, $data); } /** * {@inheritDoc} */ public function toFloat64(string $data, Endianness $endianness = null): float { [1 => $double] = \unpack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'e', Endianness::BIG => 'E', default => 'd', }, $data); return $double; } /** * {@inheritDoc} */ public function fromFloat64(float $data, Endianness $endianness = null): string { return \pack(match ($endianness ?? $this->endianness) { Endianness::LITTLE => 'e', Endianness::BIG => 'E', default => 'd', }, $data); } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,113 @@ <?php declare(strict_types=1); namespace Bic\Bin\Tests\Bench; use Bic\Bin\Converter; use Bic\Bin\NativeConverter; use PhpBench\Attributes\BeforeMethods; use PhpBench\Attributes\Iterations; use PhpBench\Attributes\ParamProviders; use PhpBench\Attributes\Revs; use PhpBench\Attributes\Warmup; #[BeforeMethods('boot')] #[Revs(10), Iterations(10), Warmup(1)] final class UnpackBench { private array $samples = []; public function boot(): void { for ($i = 0; $i < 10; ++$i) { $this->samples[] = \random_bytes(8); } } public function converters(): iterable { yield 'raw' => [new Converter()]; yield 'pack' => [new NativeConverter()]; } #[ParamProviders('converters')] public function benchInt8(array $params): void { foreach ($this->samples as $byte) { $params[0]->toInt8($byte); } } #[ParamProviders('converters')] public function benchUInt8(array $params): void { foreach ($this->samples as $byte) { $params[0]->toUInt8($byte); } } #[ParamProviders('converters')] public function benchInt16(array $params): void { foreach ($this->samples as $byte) { $params[0]->toInt16($byte); } } #[ParamProviders('converters')] public function benchUInt16(array $params): void { foreach ($this->samples as $byte) { $params[0]->toUInt16($byte); } } #[ParamProviders('converters')] public function benchInt32(array $params): void { foreach ($this->samples as $byte) { $params[0]->toInt32($byte); } } #[ParamProviders('converters')] public function benchUInt32(array $params): void { foreach ($this->samples as $byte) { $params[0]->toUInt32($byte); } } #[ParamProviders('converters')] public function benchInt64(array $params): void { foreach ($this->samples as $byte) { $params[0]->toInt64($byte); } } #[ParamProviders('converters')] public function benchUInt64(array $params): void { foreach ($this->samples as $byte) { $params[0]->toUInt64($byte); } } #[ParamProviders('converters')] public function benchFloat32(array $params): void { foreach ($this->samples as $byte) { $params[0]->toFloat32($byte); } } #[ParamProviders('converters')] public function benchFloat64(array $params): void { foreach ($this->samples as $byte) { $params[0]->toFloat64($byte); } } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,23 @@ { "runner.bootstrap": "vendor/autoload.php", "runner.php_config": [ "opcache.enable=1", "opcache.enable_cli=1", "opcache.jit_buffer_size=128M" ], "report.generators": { "expression": { "generator": "expression", "break": [ "subject" ], "cols": [ "benchmark", "subject", "set", "mode", "rstdev" ] } } }