SlideShare a Scribd company logo
Реализация клиентов
для бинарных
протоколов на PHP
Anton Shabouta
ONLINER
Зачем? Асинхронный PHP
$pdo = new PDO('mysql:host=...');
$rows = $pdo->query('SELECT ...');
foreach ($rows as $row) {
print_r($row);
}
PHP. Блокирующие операции
$pdo = new PDO('mysql:host=...');
$rows = $pdo->query('SELECT ...');
foreach ($rows as $row) {
print_r($row);
}
PHP. Блокирующие операции
Block
EventLoop
AMPHP. Неблокирующие драйверы
Beanstalkd
Зачем? Специализированное ПО
POST /index.php HTTP/1.1
Host: www.fwdays.com
Content-Type: application/json;
Content-Length: 34
{
"hello": "PHP FWDays 2019"
}
HTTP
POST /index.php HTTP/1.1
Host: www.fwdays.com
Content-Type: application/json;
Content-Length: 34
{
"hello": "PHP FWDays 2019"
}
HTTP
POST /index.php HTTP/1.1
Host: www.fwdays.com
Content-Type: application/json;
Content-Length: 34
{
"hello": "PHP FWDays 2019"
}
HTTP
POST /index.php HTTP/1.1
Host: www.fwdays.com
Content-Type: application/json;
Content-Length: 34
{
"hello": "PHP FWDays 2019"
}
HTTP
POST /index.php HTTP/1.1
Host: www.fwdays.com
Content-Type: application/json;
Content-Length: 34
{
"hello": "PHP FWDays 2019"
}
HTTP
Пакет данных. AMQP 0-9-1
01000100000014003c00280000000b62
617369635f717565756500ce02000100
00000e003c0000000000000000001600
00ce0300010000001648656c6c6f2050
504820465744617973203230313921ce
Пакет данных. AMQP 0-9-1
01000100000014003c00280000000b62
617369635f717565756500ce02000100
00000e003c0000000000000000001600
00ce0300010000001648656c6c6f2050
504820465744617973203230313921ce
Hello PHP
FWDays 2019!
Структура пакета
type channel
1 2 4
body size
Структура пакета
type channel
1 2 4
body size
body
Структура пакета
1
type channel
1 2 4
body size
CE
body
Порядок байт
3 2 1 0 От младшего к старшему
(Little Endian, LE)
123
Порядок байт
0 1 2 3От старшего к младшему
(Big Endian, BE)
123
Пакет данных. AMQP 0-9-1
01000100000014003c00280000000b62
617369635f717565756500ce
--------------------------------
0200010000000e003c00000000000000
0000160000ce
--------------------------------
0300010000001648656c6c6f20505048
20465744617973203230313921ce
Type
Channel
Size
Body
End Byte
Протокол передачи данных
Набор соглашений определяющий обмен данными
между различными программами.
Теория
Протокол передачи данных
Набор соглашений определяющий обмен данными
между различными программами.
Бинарный протокол
Протокол, который предназначен для чтения машиной, а
не человеком.
Теория
Протокол передачи данных
Набор соглашений определяющий обмен данными
между различными программами.
Бинарный протокол
Протокол, который предназначен для чтения машиной, а
не человеком.
Пакет данных
Блок информации определенной структуры.
Теория
function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
function packFrame(string $body): string
{
return pack(
'CCnCN',
$this->version,
$this->flags,
$this->stream,
$this->opcode,
strlen($body)
) . $body;
}
Работа с бинарными данными в PHP
c - знаковый char
C - беззнаковый char
Работа с бинарными данными в PHP
c - знаковый char
C - беззнаковый char
s - знаковый short (ME)
S - беззнаковый short (ME)
n - беззнаковый short (BE)
v - беззнаковый short (LE)
Работа с бинарными данными в PHP
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
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+
кодов
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
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
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
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);
}
Клиент. Парсер
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);
}
Клиент. Парсер
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);
}
Клиент. Парсер
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);
}
Клиент. Парсер
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);
}
Клиент. Парсер
Клиент. Схема работы
stream_socket_client()
Client Server
Клиент. Схема работы
stream_socket_client()
pack()
Client Server
Клиент. Схема работы
stream_socket_client()
pack()
stream_write()
Client Server
Клиент. Схема работы
stream_socket_client()
pack()
stream_write()
stream_read()
Client Server
Клиент. Схема работы
stream_socket_client()
pack()
stream_write()
stream_read()
unpack()
Client Server
Клиент. Схема работы
Client Server
stream_socket_client()
pack()
stream_write()
pack()
stream_write()
Пакет данных. Cassandra DB
version stream
1 1 2
body sizeflags opcode
1
body
4
Пакет данных. Cassandra DB
version stream
1 1 2
body sizeflags opcode
1
body
4
function writeAsync(Frame $frame)
{
$deferred = new Deferred;
yield $this->socket->write($frame->pack());
$this->defers[$frame->stream] = $deferred;
return $deferred->promise();
}
Клиент. Асинхронная запись
function writeAsync(Frame $frame)
{
$deferred = new Deferred;
yield $this->socket->write($frame->pack());
$this->defers[$frame->stream] = $deferred;
return $deferred->promise();
}
Клиент. Асинхронная запись
function writeAsync(Frame $frame)
{
$deferred = new Deferred;
yield $this->socket->write($frame->pack());
$this->defers[$frame->stream] = $deferred;
return $deferred->promise();
}
Клиент. Асинхронная запись
function writeAsync(Frame $frame)
{
$deferred = new Deferred;
yield $this->socket->write($frame->pack());
$this->defers[$frame->stream] = $deferred;
return $deferred->promise();
}
Клиент. Асинхронная запись
function writeAsync(Frame $frame)
{
$deferred = new Deferred;
yield $this->socket->write($frame->pack());
$this->defers[$frame->stream] = $deferred;
return $deferred->promise();
}
Клиент. Асинхронная запись
function readAsync(): void
{
while ($data = yield $this->socket->read()) {
$buffer = new Binary($data);
$frame = $this->parse($buffer);
$deferred = $this->defers[$frame->stream];
$deferred->resolve($frame);
}
}
Клиент. Асинхронное чтение
function readAsync(): void
{
while ($data = yield $this->socket->read()) {
$buffer = new Binary($data);
$frame = $this->parse($buffer);
$deferred = $this->defers[$frame->stream];
$deferred->resolve($frame);
}
}
Клиент. Асинхронное чтение
function readAsync(): void
{
while ($data = yield $this->socket->read()) {
$buffer = new Binary($data);
$frame = $this->parse($buffer);
$deferred = $this->defers[$frame->stream];
$deferred->resolve($frame);
}
}
Клиент. Асинхронное чтение
function readAsync(): void
{
while ($data = yield $this->socket->read()) {
$buffer = new Binary($data);
$frame = $this->parse($buffer);
$deferred = $this->defers[$frame->stream];
$deferred->resolve($frame);
}
}
Клиент. Асинхронное чтение
function readAsync(): void
{
while ($data = yield $this->socket->read()) {
$buffer = new Binary($data);
$frame = $this->parse($buffer);
$deferred = $this->defers[$frame->stream];
$deferred->resolve($frame);
}
}
Клиент. Асинхронное чтение
PHPBench
https://github.com/phpbench/phpbench
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
● Форматирование отчетов: html, xml, markdown
PHPBench
● Тесты запускаются в отдельных процессах, что
нивелирует накладные расходы.
● Поддержка ограничений (Asserters)
● Различные метрики: best, avg, mean, mode, worst
● Отложенные отчеты
● Форматирование отчетов: html, xml, markdown
● Расширения
PHPBench
/**
* @Warmup(2)
* @Iterations(10)
* @Revs(100)
*/
public function benchPublish($count = 1000)
{
$promises = [];
for ($i = 0; $i < $count; ++$i)
$promises[] = $this->channel->publish($i, 'bench');
wait($promises);
}
PHPBench
/**
* @Warmup(2)
* @Iterations(10)
* @Revs(100)
*/
public function benchPublish($count = 1000)
{
$promises = [];
for ($i = 0; $i < $count; ++$i)
$promises[] = $this->channel->publish($i, 'bench');
wait($promises);
}
PHPBench
/**
* @Warmup(2)
* @Iterations(10)
* @Revs(100)
*/
public function benchPublish($count = 1000)
{
$promises = [];
for ($i = 0; $i < $count; ++$i)
$promises[] = $this->channel->publish($i, 'bench');
wait($promises);
}
PHPBench
/**
* @Warmup(2)
* @Iterations(10)
* @Revs(100)
*/
public function benchPublish($count = 1000)
{
$promises = [];
for ($i = 0; $i < $count; ++$i)
$promises[] = $this->channel->publish($i, 'bench');
wait($promises);
}
PHPBench
/**
* @Warmup(2)
* @Iterations(10)
* @Revs(100)
*/
public function benchPublish($count = 1000)
{
$promises = [];
for ($i = 0; $i < $count; ++$i)
$promises[] = $this->channel->publish($i, 'bench');
wait($promises);
}
1000
итераций
Клиент на С vs PHP
* Меньше - лучше (μs)
Профилирование
Tideways
XHProf
Профилирование. Blackfire
Клиент. Оптимизация записи
Client Server
stream_socket_client()
pack()
stream_write()
pack()
stream_write()
Клиент. Оптимизация записи
Client Server
stream_socket_client()
pack()
pack()
stream_write()
pack()
function publish(string $body, array $headers = [])
{
$method = $this->methodFrame();
$headers = $this->headersFrame($headers);
$body = $this->bodyFrame($body);
$request = $method->append($headers)->append($body);
yield $this->socket->write((string) $request);
}
Клиент. Оптимизация записи
function publish(string $body, array $headers = [])
{
$method = $this->methodFrame();
$headers = $this->headersFrame($headers);
$body = $this->bodyFrame($body);
$request = $method->append($headers)->append($body);
yield $this->socket->write($request);
}
Клиент. Оптимизация записи
function publish(string $body, array $headers = [])
{
$method = $this->methodFrame();
$headers = $this->headersFrame($headers);
$body = $this->bodyFrame($body);
$request = $method->append($headers)->append($body);
yield $this->socket->write($request);
}
Клиент. Оптимизация записи
function publish(string $body, array $headers = [])
{
$method = $this->methodFrame();
$headers = $this->headersFrame($headers);
$body = $this->bodyFrame($body);
$request = $method->append($headers)->append($body);
yield $this->socket->write($request);
}
Клиент. Оптимизация записи
Клиент. Оптимизация чтения
Client Server
stream_socket_client()
stream_read()new Binary(...);parse()
Client Server
stream_socket_client()
stream_read()
stream_read()new Binary(...);
new Binary(...);parse()
parse()
Клиент. Оптимизация чтения
Client Server
stream_socket_client()
stream_read()
stream_read()
stream_read()
new Binary(...);
new Binary(...);
new Binary(...);parse()
parse()
parse()
Клиент. Оптимизация чтения
Бинарный буфер
App Socket
BinaryBuffer
Бинарный буфер
App Socket
BinaryBuffer
Бинарный буфер
App Socket
BinaryBuffer
Бинарный буфер
App Socket
Frame
BinaryBuffer
Бинарный буфер
App Socket
Frame
BinaryBuffer
Бинарный буфер
App Socket
BinaryBuffer
Бинарный буфер
App Socket
BinaryBuffer
Бинарный буфер
App Socket
Frame
BinaryBuffer
Client Server
stream_socket_client()
Клиент. Оптимизация чтения
new BinaryBuffer;
Client Server
stream_socket_client()
stream_read()BinaryBuffer::append();parse()
Клиент. Оптимизация чтения
new BinaryBuffer;
Client Server
stream_socket_client()
stream_read()
stream_read()
BinaryBuffer::append();
BinaryBuffer::append();parse()
parse()
Клиент. Оптимизация чтения
new BinaryBuffer;
Клиент на С vs PHP
* Меньше - лучше (μs)
Профилирование. Blackfire
Buffer::append
Buffer::discard
Buffer::appendUint8
Buffer::appendUint16
Buffer::read
Buffer::consume
Buffer::consumeUint8
34130
15094
12040
11027
9030
8042
7055
Anton Shabouta "Implementing async binary clients in pure PHP"
class Binary
{
public function append(string value) -> <Binary>
{
let this->data = this->data . value;
let this->size = this->size + strlen(value);
return this;
}
public function appendUint8(int value) -> <Binary>
{
return this->append(pack("C", value));
}
}
Zephir
Zephir vs PHP
* Меньше - лучше (μs)
PHP_METHOD(Binary, appendUint8)
{
zval *value_param = NULL, _0, _1, _2;
zephir_fetch_params(1, 1, 0, &value_param);
zend_long value = zephir_get_intval(value_param);
ZVAL_STRING(&_0, "C");
ZVAL_LONG(&_1, value);
ZEPHIR_CALL_FUNCTION(&_2, "pack", NULL, 2, &_0, &_1);
ZEPHIR_RETURN_CALL_METHOD(getThis(), "append", NULL, 0, &_2);
}
Zephir. Скомпилированный код
PHP_METHOD(Binary, appendUint8)
{
zval *value_param = NULL, _0, _1, _2;
zephir_fetch_params(1, 1, 0, &value_param);
zend_long value = zephir_get_intval(value_param);
ZVAL_STRING(&_0, "C");
ZVAL_LONG(&_1, value);
ZEPHIR_CALL_FUNCTION(&_2, "pack", NULL, 2, &_0, &_1);
ZEPHIR_RETURN_CALL_METHOD(getThis(), "append", NULL, 0, &_2);
}
Zephir. Скомпилированный код
Anton Shabouta "Implementing async binary clients in pure PHP"
std::vector<u_char>
Расширение C
std::deque<u_char>
std::vector<u_char>
vector::insert - O(1)*
vector::erase - O(n)
vector::begin - O(1)
vector::end - O(1)
vector::empty - O(1)
vector::size - O(1)
Расширение C
std::deque<u_char>
deque::insert - O(1)
deque::erase - O(1)
deque::begin - O(1)
deque::end - O(1)
deque::empty - O(1)
deque::size - O(1)
std::vector<u_char>
vector::insert - O(1)*
vector::erase - O(n)
vector::begin - O(1)
vector::end - O(1)
vector::empty - O(1)
vector::size - O(1)
Расширение C
std::deque<u_char>
deque::insert - O(1)
deque::erase - O(1)
deque::begin - O(1)
deque::end - O(1)
deque::empty - O(1)
deque::size - O(1)
PHP_METHOD(Binary, appendUInt8)
{
buffer *buf = buffer_from_zend(Z_OBJ_P(getThis()));
zend_long value;
if (!ZEND_PARSE_THROW(ZEND_NUM_ARGS(), "l", &value)) {
return;
}
buf->data->append<unsigned char>(value);
RETURN_ZVAL(getThis(), 1, 0);
}
Расширение C
https://github.com/phpinnacle/ext-buffer
PHP_METHOD(Binary, readUnsafe)
{
...
string res(buf.begin() + offset, buf.begin() + offset + size);
char * data = res.c_str();
RETURN_NEW_STR(zend_string_init(data, strlen(data), 0));
}
Расширение C
PHP_METHOD(Binary, readUnsafe)
{
...
string res(buf.begin() + offset, buf.begin() + offset + size);
// WRONG WAY! You lose your binary data
char * data = res.c_str();
RETURN_NEW_STR(zend_string_init(data, strlen(data), 0));
}
Расширение C
PHP_METHOD(Binary, readSafe)
{
...
string res(buf.begin() + offset, buf.begin() + offset + size);
RETURN_NEW_STR(zend_string_init(res.data(), res.size(), 0));
}
Расширение C
Binary
Safe
Zephir vs PHP vs C/C++
* Меньше - лучше (μs)
Итого
● https://github.com/Ostico/PhpOrient
● https://github.com/tarantool-php/client
Итого
● https://github.com/Ostico/PhpOrient
● https://github.com/tarantool-php/client
● https://github.com/markkimsal/amphp-mqtt
● https://github.com/prooph/event-store
Итого
● https://github.com/Ostico/PhpOrient
● https://github.com/tarantool-php/client
● https://github.com/markkimsal/amphp-mqtt
● https://github.com/prooph/event-store
● https://github.com/phpinnacle/cassis
● https://github.com/phpinnacle/ridge
Итого
● https://github.com/Ostico/PhpOrient
● https://github.com/tarantool-php/client
● https://github.com/markkimsal/amphp-mqtt
● https://github.com/prooph/event-store
● https://github.com/phpinnacle/cassis
● https://github.com/phpinnacle/ridge
СПАСИБО!
Вопросы?
zloyusr@gmail.com
https://github.com/phpinnacle

More Related Content

PPT
Юрий Гольцев - Сервис PLWWW
PPT
plwww (24.03) MEPHI (PHDays)
ODP
Программирование Linux
ODP
Программирование Linux
ODP
Отладка в Erlang, trace/dbg
PDF
Perl: Symbol table
PPT
Что нового в PHP-5.3
ODP
Программирование Linux
Юрий Гольцев - Сервис PLWWW
plwww (24.03) MEPHI (PHDays)
Программирование Linux
Программирование Linux
Отладка в Erlang, trace/dbg
Perl: Symbol table
Что нового в PHP-5.3
Программирование Linux

What's hot (20)

PPTX
Динамический код: модифицируем таблицу символов во время выполнения. Елена Ши...
PPTX
PHP basic
PPTX
Не верь никому или разработка эффективных приложений (Как писать по настоящем...
PDF
Что нового в Perl? 5.10 — 5.16
PPT
Rose::DB
PDF
Язык программирования Go для Perl-программистов
PPT
PHP Tricks
PPT
Импорт данных с фреймворком Migrate. Владислав Богатырев.
PDF
Python
PPT
Collider
PDF
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
PDF
Hf labs education day. rocket science
PDF
Параллельные вычисления в Perl 6
PPT
Js Http Request дмитрий котеров
PDF
PiterPy#3. DSL in Python. How and why?
PPTX
О безопасном использовании PHP wrappers
PDF
Разработка на Perl под Raspberry PI
PDF
Приручаем linux-консоль
PDF
JavaScript. Loops and functions (in russian)
PPTX
PHP Advanced
Динамический код: модифицируем таблицу символов во время выполнения. Елена Ши...
PHP basic
Не верь никому или разработка эффективных приложений (Как писать по настоящем...
Что нового в Perl? 5.10 — 5.16
Rose::DB
Язык программирования Go для Perl-программистов
PHP Tricks
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Python
Collider
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Hf labs education day. rocket science
Параллельные вычисления в Perl 6
Js Http Request дмитрий котеров
PiterPy#3. DSL in Python. How and why?
О безопасном использовании PHP wrappers
Разработка на Perl под Raspberry PI
Приручаем linux-консоль
JavaScript. Loops and functions (in russian)
PHP Advanced
Ad

Similar to Anton Shabouta "Implementing async binary clients in pure PHP" (20)

PDF
Роман Еникеев - PHP или откуда взялся слон
PDF
PHP 5.4 - особенности перехода
PDF
Сборник практических задании по Php
PPTX
PHP7 - что ожидать?
PDF
Как мы делаем модули PHP в Badoo – Антон Довгаль
PPT
The basic design of the PHP language
PDF
Релиз PHP7 - что нас ждет в октябре 2015
PPTX
Демоны на PHP (Денис Глазков)
PPTX
Язык программирования PHP
PPT
PPTX
Микрофреймворки PHP
PPTX
Base php 1
PPTX
Base php 1
PPTX
Base php 1
PDF
Лекции и задания по рнр
PDF
Памятка о php-шниках
PPT
Php 5.5 - idea generator!
PDF
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Роман Еникеев - PHP или откуда взялся слон
PHP 5.4 - особенности перехода
Сборник практических задании по Php
PHP7 - что ожидать?
Как мы делаем модули PHP в Badoo – Антон Довгаль
The basic design of the PHP language
Релиз PHP7 - что нас ждет в октябре 2015
Демоны на PHP (Денис Глазков)
Язык программирования PHP
Микрофреймворки PHP
Base php 1
Base php 1
Base php 1
Лекции и задания по рнр
Памятка о php-шниках
Php 5.5 - idea generator!
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Ad

More from Fwdays (20)

PDF
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
PDF
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
PPTX
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
PPTX
"Як ми переписали Сільпо на Angular", Євген Русаков
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
PDF
"Validation and Observability of AI Agents", Oleksandr Denisyuk
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
PPTX
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
PPTX
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
PDF
"AI is already here. What will happen to your team (and your role) tomorrow?"...
PPTX
"Is it worth investing in AI in 2025?", Alexander Sharko
PDF
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
PDF
"Scaling in space and time with Temporal", Andriy Lupa.pdf
PDF
"Database isolation: how we deal with hundreds of direct connections to the d...
PDF
"Scaling in space and time with Temporal", Andriy Lupa .pdf
PPTX
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
PPTX
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
PPTX
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
PPTX
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
"Як ми переписали Сільпо на Angular", Євген Русаков
"AI Transformation: Directions and Challenges", Pavlo Shaternik
"Validation and Observability of AI Agents", Oleksandr Denisyuk
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
"AI is already here. What will happen to your team (and your role) tomorrow?"...
"Is it worth investing in AI in 2025?", Alexander Sharko
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Database isolation: how we deal with hundreds of direct connections to the d...
"Scaling in space and time with Temporal", Andriy Lupa .pdf
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...

Anton Shabouta "Implementing async binary clients in pure PHP"