- Have you ever think how PDO work under the hood?
- What if tomorrow you need to write own DB driver from scratch?
- How to approach such tasks and get around the pitfalls?
- Is it possible to achieve in pure PHP performance comparable to the C extension?
In this talk I will try to answer these and other questions related to the development of clients for various binary protocols. We also analyze the nuances of the asynchronous driver implementation and dive into the world of low-level and not-so-optimizations.
19. Пакет данных. AMQP 0-9-1
01000100000014003c00280000000b62
617369635f717565756500ce
--------------------------------
0200010000000e003c00000000000000
0000160000ce
--------------------------------
0300010000001648656c6c6f20505048
20465744617973203230313921ce
Type
Channel
Size
Body
End Byte
21. Протокол передачи данных
Набор соглашений определяющий обмен данными
между различными программами.
Бинарный протокол
Протокол, который предназначен для чтения машиной, а
не человеком.
Теория
22. Протокол передачи данных
Набор соглашений определяющий обмен данными
между различными программами.
Бинарный протокол
Протокол, который предназначен для чтения машиной, а
не человеком.
Пакет данных
Блок информации определенной структуры.
Теория
23. function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
24. function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
25. function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
26. function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
27. c - знаковый char
C - беззнаковый char
Работа с бинарными данными в PHP
28. c - знаковый char
C - беззнаковый char
s - знаковый short (ME)
S - беззнаковый short (ME)
n - беззнаковый short (BE)
v - беззнаковый short (LE)
Работа с бинарными данными в PHP
29. c - знаковый char
C - беззнаковый char
s - знаковый short (ME)
S - беззнаковый short (ME)
n - беззнаковый short (BE)
v - беззнаковый short (LE)
i - знаковый int (ME)
I - беззнаковый int (ME)
N - беззнаковый int (BE)
V - беззнаковый int (LE)
Работа с бинарными данными в PHP
30. c - знаковый char
C - беззнаковый char
s - знаковый short (ME)
S - беззнаковый short (ME)
n - беззнаковый short (BE)
v - беззнаковый short (LE)
i - знаковый int (ME)
I - беззнаковый int (ME)
N - беззнаковый int (BE)
V - беззнаковый int (LE)
l - знаковый long (ME)
L - беззнаковый long (ME)
N - беззнаковый long (BE)
V - беззнаковый long (LE)
Работа с бинарными данными в PHP
f - float (ME)
G - float (BE)
g - float (LE)
d - double (ME)
E - double (BE)
e - double (LE)
...
30+
кодов
31. function packFrame(string $body): string
{
return (string) Binary::bigEndian()
->appendUint8($this->version)
->appendUint8($this->flags)
->appendUint16($this->stream)
->appendUint8($this->opcode)
->appendUint32(strlen($body))
->append($body)
;
}
Работа с бинарными данными в PHP
https://github.com/phpinnacle/buffer
32. class Binary
{
public function append(string $value): self
{
$this->data .= $value;
$this->size += strlen($value);
return $this;
}
public function appendInt8(int $value): self
{
return $this->append(pack("c", $value));
}
}
Работа с бинарными данными в PHP
33. class Binary
{
public function read(int $n, int $offset = 0): string
{
return substr($this->data, $offset, $n);
}
public function readInt8(int $offset = 0): int
{
return unpack("c", $this->read(1, $offset))[1];
}
}
Работа с бинарными данными в PHP
34. public function parse(Binary $data): ?Frame
{
if ($data->size() < HEADER_SIZE) {
return null;
}
$type = $data->readUint8(0);
$channel = $data->readUint16(1);
$size = $data->readUint32(3);
if ($data->size() < $size + HEADER_SIZE) {
return null;
}
$body = $data->read($size);
return new Frame($type, $channel, $body);
}
Клиент. Парсер
35. public function parse(Binary $data): ?Frame
{
if ($data->size() < HEADER_SIZE) {
return null;
}
$type = $data->readUint8(0);
$channel = $data->readUint16(1);
$size = $data->readUint32(3);
if ($data->size() < $size + HEADER_SIZE) {
return null;
}
$body = $data->read($size);
return new Frame($type, $channel, $body);
}
Клиент. Парсер
36. public function parse(Binary $data): ?Frame
{
if ($data->size() < HEADER_SIZE) {
return null;
}
$type = $data->readUint8(0);
$channel = $data->readUint16(1);
$size = $data->readUint32(3);
if ($data->size() < $size + HEADER_SIZE) {
return null;
}
$body = $data->read($size);
return new Frame($type, $channel, $body);
}
Клиент. Парсер
37. public function parse(Binary $data): ?Frame
{
if ($data->size() < HEADER_SIZE) {
return null;
}
$type = $data->readUint8(0);
$channel = $data->readUint16(1);
$size = $data->readUint32(3);
if ($data->size() < $size + HEADER_SIZE) {
return null;
}
$body = $data->read($size);
return new Frame($type, $channel, $body);
}
Клиент. Парсер
38. public function parse(Binary $data): ?Frame
{
if ($data->size() < HEADER_SIZE) {
return null;
}
$type = $data->readUint8(0);
$channel = $data->readUint16(1);
$size = $data->readUint32(3);
if ($data->size() < $size + HEADER_SIZE) {
return null;
}
$body = $data->read($size);
return new Frame($type, $channel, $body);
}
Клиент. Парсер
59. PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
60. PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
61. PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
62. PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
● Форматирование отчетов: html, xml, markdown
63. PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
● Форматирование отчетов: html, xml, markdown
● Расширения