SlideShare a Scribd company logo
1 of 58
Download to read offline
Антон Довгаль
20 июля 2017
Модули PHP
в Badoo
● Свой первый модуль написал в 16 лет 2004 году - PECL/memcache
● Когда-то давно написал PECL/rar, PECL/sphinx, PECL/memtrack и ещё
какой-то трэш, по пути исправив сотни багов в PHP
● Успел 3 года поработать в Zend (в основном над Zend Server), в
процессе переписал заново PECL/oci8
● 10 лет в Badoo: поддержка/доработка PHP, разработка сервисов на C,
недорого
Про меня
● Крупнейший сервис знакомств в мире - 350 млн пользователей
● ~3 млн строк кода на PHP + ~1.5 млн строк тестов
● ~1000 серверов с PHP-FPM (разработан в Badoo, добавлен в PHP в 2010
году)
● ~600 серверов MySQL
● >200 инженеров
● 2 + 0.5 + 0.5 (=3?) датацентра
● 2 офиса разработки - Москва и Лондон
Про Badoo
Модули PHP
они же - экстеншены
● Как работает PHP с модулями?
● Что представляют из себя модули PHP?
● Как и на чём их пишут?
● Зачем их (иногда) нужно писать?
● Как они работают?
● Как начать писать свой модуль PHP
● Пара примеров из жизни
У меня был план
Архитектура PHP в двух словах
● Пишутся на C/C++
● Статические модули - встроены в PHP, нельзя выгрузить
● Динамические - обычный .so/.dll, можно загрузить dl()
● Могут использовать сторонние библиотеки на C/C++
Модули PHP
● встроенные (standard, date, pcre, SPL, Reflection)
● собираемые по умолчанию (ctype, dom, hash, json etc.)
● поставляемые в дистрибуции
● модули из PECL - pecl.php.net
● сторонние модули - Github & Co.
Виды модулей PHP
bcmath
bz2
calendar
com_dotnet
ctype
curl
date
dba
dom
enchant
exif
fileinfo
filter
Модули в дистрибуции
ftp
gd
gettext
gmp
hash
iconv
imap
interbase
intl
json
ldap
libxml
mbstring
mysqli
mysqlnd
oci8
odbc
opcache
openssl
pcntl
pcre
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_oci
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phar
posix
pspell
readline
recode
reflection
session
shmop
simplexml
skeleton
snmp
soap
sockets
spl
sqlite3
standard
sysvmsg
sysvsem
sysvshm
tidy
tokenizer
wddx
xml
xmlreader
xmlrpc
xmlwriter
xsl
zend_test
zip
zlib
● обычные модули
○ имплементируют функции, классы, методы
● Zend extension
○ имплементируют функции, классы, методы
○ вмешиваются в работу ядра (opcache, XDebug)
Типы модулей PHP
● blitz - движок шаблонов на C
● geoi - используется для гео-поиска
● gpbs - общий интерфейс к нашим сервисам на C/C++/Go
● handlersocketi - интерфейс к HS
● imatch - сравнение изображений, поиск дубликатов
● leptonica - работа с изображениями: ресайз, поворот, искажения для
капчи
● memtrack - следит за использованием памяти в PHP, ищет прожорливые
функции
● pinba - клиент для нашего сервиса статистики на базе MySQL
Нестандартные модули PHP в Badoo
● Нужен интерфейс к библиотеке на C/C++ (mysql, oci8)
● Есть задача, которая не решается на PHP (gpbs)
● Есть узкое место в коде, которое можно оптимизировать на C (blitz)
● Нужно добавить функционал в сам PHP (xdebug)
● Хочется посмотреть “что у ней внутре”
Причины написания своего модуля
Пишем модуль PHP
crash course
> git clone https://github.com/php/php-src
> cd php-src/ext
> ./ext_skel
./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir]
[--full-xml] [--no-help]
--extname=module module is the name of your extension
--proto=file file contains prototypes of functions to create
--stubs=file generate only function stubs in file
--xml generate xml documentation to be added to phpdoc-svn
--skel=dir path to the skeleton directory
--full-xml generate xml documentation for a self-contained extension (not yet
implemented)
--no-help don't try to be nice and create comments in the code and helper functions
to test if the module compiled
Пишем модуль PHP
> ./ext_skel --extname=example
Creating directory example
Creating basic files: config.m4 config.w32 .gitignore example.c
php_example.h CREDITS EXPERIMENTAL tests/001.phpt example.php [done].
Пишем модуль PHP
config.m4 - опции configure и проверки библиотек, хидеров и пр.
config.w32 - используется для сборки под Windows
CREDITS - информация об авторах
EXPERIMENTAL - файл-метка, показывающий статус модуля
.gitignore - игнорируем мусор от сборки
php_example.h - заголовок модуля
example.c - исходник модуля
example.php - небольшой скрипт для демонстрации работы
tests/ - ??? какие тесты ???
Пишем модуль PHP
config.m4:
PHP_ARG_ENABLE(example, whether to enable example support,
[ --enable-example Enable example support])
if test "$PHP_EXAMPLE" != "no"; then
PHP_NEW_EXTENSION(example, example.c, $ext_shared)
fi
Пишем модуль PHP
● Функции-обработчики:
○ MINIT - при загрузке/старт PHP
○ MSHUTDOWN - при выгрузке/окончание работы PHP
○ MINFO - вывод в phpinfo()
○ RINIT - начало запроса, на каждый запрос
○ RSHUTDOWN - конец запроса, на каждый запрос
● Функции, методы классов
● Список функций модуля - zend_function_entry[]
● Структура модуля - zend_module_entry
Структура модуля PHP
php_example.h:
#ifndef PHP_EXAMPLE_H
#define PHP_EXAMPLE_H
extern zend_module_entry example_module_entry;
#define phpext_example_ptr &example_module_entry
#define PHP_EXAMPLE_VERSION "0.1.0"
#endif /* PHP_EXAMPLE_H */
Пишем модуль PHP
example.c:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_example.h"
…
Пишем модуль PHP
example.c:
…
/* {{{ proto string confirm_example_compiled(string arg)
Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_example_compiled)
{
char *arg = NULL;
size_t arg_len, len;
zend_string *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
return;
}
strg = strpprintf(0, "Congratulations! You have successfully modified ext/%s/config.m4.
Module %s is now compiled into PHP.", "example", arg);
RETURN_STR(strg);
}
/* }}} */
…
Пишем модуль PHP
БЕЗ ПАНИКИ!
всё это можно потом найти тут:
github.com/tony2001/example
example.c:
…
/* {{{ proto string confirm_example_compiled(string arg)
Return a string to confirm that the module is compiled in */
/* }}} */
…
Пишем модуль PHP
example.c:
…
PHP_FUNCTION(confirm_example_compiled)
{
RETURN_STR(strg);
}
…
Пишем модуль PHP
#define PHP_FUNCTION(name) ZEND_FUNCTION(name)
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_FN(name) zif_##name
#define ZEND_NAMED_FUNCTION(name) name(INTERNAL_FUNCTION_PARAMETERS)
#define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval
*return_value
PHP_FUNCTION(name) => zif_name(zend_execute_data *execute_data, zval
*return_value)
PHP + макросы = ❤
#define RETURN_STR(s) { RETVAL_STR(s); return; }
#define RETVAL_STR(s) ZVAL_STR(return_value, s)
#define ZVAL_STR(z, s) do { 
zval *__z = (z); 
zend_string *__s = (s); 
Z_STR_P(__z) = __s; 
/* interned strings support */ 
Z_TYPE_INFO_P(__z) = ZSTR_IS_INTERNED(__s) ? 
IS_INTERNED_STRING_EX : 
IS_STRING_EX; 
} while (0)
PHP + макросы = ❤
typedef union _zend_value {
zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv; <---------- :)
void *ptr;
zend_class_entry *ce;
zend_function *func;
struct {
uint32_t w1;
uint32_t w2;
} ww;
} zend_value;
Переменные в PHP. ZVAL
ZVAL в PHP7
example.c:
…
char *arg = NULL;
size_t arg_len, len;
zend_string *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
return;
}
…
Пишем модуль PHP
example.c:
…
strg = strpprintf(0, "Congratulations! You have successfully modified ext/%s/config.m4.
Module %s is now compiled into PHP.", "example", arg);
RETURN_STR(strg);
}
/* }}} */
…
Пишем модуль PHP
example.c:
…
PHP_MINFO_FUNCTION(example)
{
php_info_print_table_start();
php_info_print_table_header(2, "example support", "enabled");
php_info_print_table_end();
}
…
Пишем модуль PHP
example.c:
…
const zend_function_entry example_functions[] = {
PHP_FE(confirm_example_compiled, NULL)
PHP_FE_END
};
zend_module_entry example_module_entry = {
STANDARD_MODULE_HEADER,
"example",
example_functions,
NULL, //MINIT
NULL, //MSHUTDOWN
NULL, //RINIT
NULL, //RSHUTDOWN
PHP_MINFO(example),
PHP_EXAMPLE_VERSION,
STANDARD_MODULE_PROPERTIES
};
Пишем модуль PHP
Нам понадобится phpize и заголовки PHP.
Обычно они есть в пакетах:
● php7-devel
● или php-devel
● или php-dev
Пишем Собираем модуль PHP
> phpize
Configuring for:
PHP Api Version: 20160303
Zend Module Api No: 20160303
Zend Extension Api No: 320160303
> ./configure --with-php-config=/path/to/php/php-config
configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu
checking for grep that handles long lines and -e... /usr/bin/grep
…
…
> make install
Installing shared extensions: /path/to/php/lib64/extensions/debug-non-zts-20160303/
Пишем Собираем модуль PHP
<?php
dl('example.so');
echo confirm_example_compiled(“example”);
?>
Используем модуль PHP
Congratulations! You have successfully modified ext/example/config.m4. Module
“example” is now compiled into PHP.
Cсылка на исходники
github.com/tony2001/example
Пример из жизни #1
совсем простой
Код для “шифрования” ID пользователя:
    function map_canonical($n, $d = true)
    {
$seed = 3358638055;
$map1 = array(31, 27, 23, 19, 15, 11, 7, 3, 28, 24, 20, 16, 12, 8, 4, 0, 29, 25, 21,
17, 13, 9, 5, 1, 30, 26, 22, 18, 14, 10, 6, 2);
$map2 = array(15, 23, 31, 7, 14, 22, 30, 6, 13, 21, 29, 5, 12, 20, 28, 4, 11, 19, 27,
3, 10, 18, 26, 2, 9, 17, 25, 1, 8, 16, 24, 0);
        $m = 0;
        $n = $d ? $n : ($n ^ $seed);
        foreach ($d ? $map1 : $map2 as $i => $l) {
            $k = $n & (1 << $i);
            if ($k) $m |= 1 << $l;
        }
        return $d ? $m ^ $seed : $m;
    }
Пример #1. Оригинал на PHP
Вызовем 100 млн раз:
# time php5.3 /tmp/original.php
real 9m9.008s
user 9m8.904s
sys 0m0.028s
~180 тысяч вызовов в секунду
Пример #1. Оригинал на PHP
static PHP_FUNCTION(bi_map_encode) /* {{{ */
{
long n;
unsigned int result = 0;
unsigned int number;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) {
return;
}
number = (unsigned int)n;
#define K(i) (number & (1 << i))
#define ITER(i, n) result += (n > i) ? (K(i) << (n - i)) : (K(i) >> (i - n));
ITER(0, 31);
ITER(1, 27);
ITER(2, 23);
ITER(3, 19);
…
Пример #1. Жалкая пародия на C
Вызовем 100 млн раз:
# time php5.3 /tmp/copy.php
real 0m9.427s
user 0m9.417s
sys 0m0.008s
~11 млн вызовов в секунду
т.е. в 60 раз быстрее
Пример #1. Жалкая пародия на C
5.3
PHP - ~550 секунд
Модуль - ~9 секунд
Мини-бенчмарк PHP 5.3 vs PHP 7.1
7.1
PHP - ~100 секунды
Модуль - ~4 секунды
Обновляйте PHP!
Мораль:
Пример из жизни #2
чуть посложнее
<?php
$connect = memcache_connect(“service.host”, 3113);
$result = memcache_laccess_update($connect, $anketa_id, $user_id,
$mode, $command, $partner_id);
C:
модуль - snprintf(buf, sizeof(buf), "laccess_update v17 %u %u %c %c %u
%s %u", aid, user_id, mode, command, partner_id, ip, country_id);
сервис - sscanf(buf, "%u %ld %ld %c %f %f %c %*s %*s %ld %*s %*s %ld
%*s %*s %*s %*s %ld"....); >_<
Пример #2. Текстовый протокол
Минусы:
○ приходится постоянно менять модуль PHP вместе с API сервисов
○ неэкономно расходуется сеть
○ сложный разбор аргументов методов
Плюсы:
○ человеко-читабельность протокола
Пример #2. Текстовый протокол
● Google Protobuf: формат сериализации, бинарная
альтернатива XML, JSON и пр.
● Google Protocol Buffers Service - RPC на базе GPB
● Формат данных задаётся proto-файлом
● Из proto можно генерировать код на C, C++, PHP, Go,
Java, Python и прочих языках
● gRPC - официальный RPC от Google 2015 года, но у нас
всё работает c 2011 года
Пример #2. GPBS
Пример #2. GPBS
package badoo.cityd2;
message city {
required uint32 id = 1;
required string name = 2;
required uint32 lang_id = 3;
required uint32 user_cnt = 4;
optional float lat = 5;
optional float lon = 6;
}
message request_find_city {
required string name = 1;
optional uint32 limit = 2;
repeated uint32 lang_ids = 3;
}
message response_cities {
repeated city cities = 1;
}
- с помощью protobuf-c генерируем из proto-файла код на C и
дескриптор (описывает все структуры в proto a-la reflection)
- собираем код в .so, добавляя дескриптор
- подгружаем .so в PHP (dlopen, dlsym)
- используем для кодирования/декодирования пакетов Protobuf в модуле
Пример #2. GPBS
<?php
$module = gpbs_import(“cityd.so”);
$connect = gpbs_connect(“cityd.host”, 1331, $module);
$call_result = gpbs_call(“find_city”, array(“name” => ”mos”));
//добавляем новый аргумент
$call_result = gpbs_call(“find_city”, array(“name” => ”mos”,
“country_id” => 1));
Пример #2. GPBS
Разница между GPB и JSON:
<?php
//грузим .so, создаём объект модуля со всеми методами из дескриптора
$so = gpbs_import(“cityd.so");
//сериализуем запрос в Protobuf
$j = gpbs_serialize($so->request_find_city, array("name" => "mos",
"limit"=>10, "lang_ids"=>array(1,2,3)));
var_dump($j); // string(13). Тот же самый запрос в JSON - 44 байта!
Пример #2. GPBS
Плюсы:
● все сервисы унифицированы, используют общую базу кода
● бинарный протокол - меньше потребление сети
● при изменениях в API сервиса нужно пересобрать .so из proto-файла,
в остальном меняется только PHP-код клиентской части
Пример #2. RPC на Google Protobufs
Минусы:
● бинарный протокол приходится разбирать Wireshark
Плюсы:
● все сервисы унифицированы, используют общую базу кода
● бинарный протокол - меньше потребление сети
● при изменениях в API сервиса нужно пересобрать .so из proto-файла,
в остальном меняется только PHP-код клиентской части
Пример #2. RPC на Google Protobufs
Ещё плюсы:
● можно генерить JSON!
PHP:
● PHP at the Core: A Hacker's Guide php.net/manual/en/internals2.php
● Extending and Embedding PHP, Sara Golemon 2006 (местами устарела).
● Читайте исходники PHP и других модулей!
Google Protobuf:
● github.com/google/protobuf
● github.com/grpc/grpc
Badoo:
● techblog.badoo.com
● habrahabr.ru/company/badoo
Полезные ссылки
Спасибо!
github.com/tony2001
antony.dovgal@gmail.com

More Related Content

What's hot

Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Stas Vyschepan
 
Perl Debugger и mod_perl
Perl Debugger и mod_perlPerl Debugger и mod_perl
Perl Debugger и mod_perlИван mrRico
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerLEDC 2016
 
Python и Django – платформа для фрилансера
Python и Django – платформа для фрилансераPython и Django – платформа для фрилансера
Python и Django – платформа для фрилансераAlexander Koshelev
 
Hunting for a C++ package manager
Hunting for a C++ package managerHunting for a C++ package manager
Hunting for a C++ package managercorehard_by
 
Про асинхронное сетевое программирование
Про асинхронное сетевое программированиеПро асинхронное сетевое программирование
Про асинхронное сетевое программированиеPython Meetup
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноKrivoy Rog IT Community
 
Язык программирования GO
Язык программирования GOЯзык программирования GO
Язык программирования GOPython Meetup
 
Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutinescorehard_by
 
Семь тысяч Rps, один go
Семь тысяч Rps, один goСемь тысяч Rps, один go
Семь тысяч Rps, один goBadoo Development
 
poudriere или как я перестал волноваться и полюбил pkg
poudriere или как я перестал волноваться и полюбил pkgpoudriere или как я перестал волноваться и полюбил pkg
poudriere или как я перестал волноваться и полюбил pkgAndrey Fesenko
 
Flask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаFlask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаPython Meetup
 
Groovy On Grails
Groovy On GrailsGroovy On Grails
Groovy On Grailsguest32215a
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычностьStepan Tanasiychuk
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееGetDev.NET
 
Practical Python Packaging / Стас Рудаков / Web Developer Wargaming
 Practical Python Packaging / Стас Рудаков / Web Developer Wargaming Practical Python Packaging / Стас Рудаков / Web Developer Wargaming
Practical Python Packaging / Стас Рудаков / Web Developer WargamingPython Meetup
 
Применение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияПрименение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияcorehard_by
 

What's hot (20)

Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
 
Perl Debugger и mod_perl
Perl Debugger и mod_perlPerl Debugger и mod_perl
Perl Debugger и mod_perl
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developer
 
Python и Django – платформа для фрилансера
Python и Django – платформа для фрилансераPython и Django – платформа для фрилансера
Python и Django – платформа для фрилансера
 
php frameworks
php frameworksphp frameworks
php frameworks
 
Hunting for a C++ package manager
Hunting for a C++ package managerHunting for a C++ package manager
Hunting for a C++ package manager
 
Про асинхронное сетевое программирование
Про асинхронное сетевое программированиеПро асинхронное сетевое программирование
Про асинхронное сетевое программирование
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
 
Язык программирования GO
Язык программирования GOЯзык программирования GO
Язык программирования GO
 
Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutines
 
Семь тысяч Rps, один go
Семь тысяч Rps, один goСемь тысяч Rps, один go
Семь тысяч Rps, один go
 
poudriere или как я перестал волноваться и полюбил pkg
poudriere или как я перестал волноваться и полюбил pkgpoudriere или как я перестал волноваться и полюбил pkg
poudriere или как я перестал волноваться и полюбил pkg
 
Flask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаFlask как хорошее решение для веб проекта
Flask как хорошее решение для веб проекта
 
Component Inspector
Component InspectorComponent Inspector
Component Inspector
 
Groovy On Grails
Groovy On GrailsGroovy On Grails
Groovy On Grails
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычность
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущее
 
Practical Python Packaging / Стас Рудаков / Web Developer Wargaming
 Practical Python Packaging / Стас Рудаков / Web Developer Wargaming Practical Python Packaging / Стас Рудаков / Web Developer Wargaming
Practical Python Packaging / Стас Рудаков / Web Developer Wargaming
 
Применение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияПрименение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюдения
 
Symfony 3
Symfony 3Symfony 3
Symfony 3
 

Similar to Как мы делаем модули PHP в Badoo – Антон Довгаль

Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Ontico
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf Conference
 
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art) DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art) it-people
 
Сборник практических задании по Php
Сборник практических задании по PhpСборник практических задании по Php
Сборник практических задании по PhpRauan Ibraikhan
 
От Make к Ansible
От Make к AnsibleОт Make к Ansible
От Make к AnsibleIvan Grishaev
 
Saint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demoSaint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demomegakott
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.Igor Shkulipa
 
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Ontico
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word pressvovasik
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй этоRoman Dvornov
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bashkuchinskaya
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"oelifantiev
 
инструментарий
инструментарийинструментарий
инструментарийigdweb
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 

Similar to Как мы делаем модули PHP в Badoo – Антон Довгаль (20)

Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
Zend Framework и Doctrine
Zend Framework и DoctrineZend Framework и Doctrine
Zend Framework и Doctrine
 
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art) DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)
DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)
 
Сборник практических задании по Php
Сборник практических задании по PhpСборник практических задании по Php
Сборник практических задании по Php
 
PHP
PHPPHP
PHP
 
От Make к Ansible
От Make к AnsibleОт Make к Ansible
От Make к Ansible
 
Saint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demoSaint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demo
 
бегун
бегунбегун
бегун
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
JPHP
JPHPJPHP
JPHP
 
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word press
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
 
бегун
бегунбегун
бегун
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bash
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
 
инструментарий
инструментарийинструментарий
инструментарий
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 

More from Badoo Development

Viktar Karanevich – iOS Parallel Automation
Viktar Karanevich – iOS Parallel AutomationViktar Karanevich – iOS Parallel Automation
Viktar Karanevich – iOS Parallel AutomationBadoo Development
 
Григорий Джанелидзе, OK.RU
Григорий Джанелидзе, OK.RUГригорий Джанелидзе, OK.RU
Григорий Джанелидзе, OK.RUBadoo Development
 
Андрей Сидоров, Яндекс.Браузер
Андрей Сидоров, Яндекс.БраузерАндрей Сидоров, Яндекс.Браузер
Андрей Сидоров, Яндекс.БраузерBadoo Development
 
Филипп Уваров, Avito
Филипп Уваров, AvitoФилипп Уваров, Avito
Филипп Уваров, AvitoBadoo Development
 
Cocoaheads Meetup / Alex Zimin / Swift magic
Cocoaheads Meetup / Alex Zimin / Swift magicCocoaheads Meetup / Alex Zimin / Swift magic
Cocoaheads Meetup / Alex Zimin / Swift magicBadoo Development
 
Cocoaheads Meetup / Kateryna Trofimenko / Feature development
Cocoaheads Meetup / Kateryna Trofimenko / Feature developmentCocoaheads Meetup / Kateryna Trofimenko / Feature development
Cocoaheads Meetup / Kateryna Trofimenko / Feature developmentBadoo Development
 
Alex Krasheninnikov – Hadoop High Availability
Alex Krasheninnikov – Hadoop High AvailabilityAlex Krasheninnikov – Hadoop High Availability
Alex Krasheninnikov – Hadoop High AvailabilityBadoo Development
 
Андрей Денисов – В ожидании мониторинга баз данных
Андрей Денисов – В ожидании мониторинга баз данныхАндрей Денисов – В ожидании мониторинга баз данных
Андрей Денисов – В ожидании мониторинга баз данныхBadoo Development
 
Александр Зобнин, Grafana Labs
Александр Зобнин, Grafana LabsАлександр Зобнин, Grafana Labs
Александр Зобнин, Grafana LabsBadoo Development
 
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественно
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественноИлья Аблеев – Zabbix в Badoo: реагируем быстро и качественно
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественноBadoo Development
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruBadoo Development
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooBadoo Development
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma Badoo Development
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoBadoo Development
 
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»  Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов» Badoo Development
 
Как мы готовим MySQL
 Как мы готовим MySQL  Как мы готовим MySQL
Как мы готовим MySQL Badoo Development
 
Архитектура хранения и отдачи фотографий в Badoo
Архитектура хранения и отдачи фотографий в Badoo Архитектура хранения и отдачи фотографий в Badoo
Архитектура хранения и отдачи фотографий в Badoo Badoo Development
 
5 способов деплоя PHP-кода в условиях хайлоада
5 способов деплоя PHP-кода в условиях хайлоада5 способов деплоя PHP-кода в условиях хайлоада
5 способов деплоя PHP-кода в условиях хайлоадаBadoo Development
 
Git хуки на страже качества кода
Git хуки на страже качества кодаGit хуки на страже качества кода
Git хуки на страже качества кодаBadoo Development
 

More from Badoo Development (20)

Viktar Karanevich – iOS Parallel Automation
Viktar Karanevich – iOS Parallel AutomationViktar Karanevich – iOS Parallel Automation
Viktar Karanevich – iOS Parallel Automation
 
Григорий Джанелидзе, OK.RU
Григорий Джанелидзе, OK.RUГригорий Джанелидзе, OK.RU
Григорий Джанелидзе, OK.RU
 
Андрей Сидоров, Яндекс.Браузер
Андрей Сидоров, Яндекс.БраузерАндрей Сидоров, Яндекс.Браузер
Андрей Сидоров, Яндекс.Браузер
 
Филипп Уваров, Avito
Филипп Уваров, AvitoФилипп Уваров, Avito
Филипп Уваров, Avito
 
Cocoaheads Meetup / Alex Zimin / Swift magic
Cocoaheads Meetup / Alex Zimin / Swift magicCocoaheads Meetup / Alex Zimin / Swift magic
Cocoaheads Meetup / Alex Zimin / Swift magic
 
Cocoaheads Meetup / Kateryna Trofimenko / Feature development
Cocoaheads Meetup / Kateryna Trofimenko / Feature developmentCocoaheads Meetup / Kateryna Trofimenko / Feature development
Cocoaheads Meetup / Kateryna Trofimenko / Feature development
 
Alex Krasheninnikov – Hadoop High Availability
Alex Krasheninnikov – Hadoop High AvailabilityAlex Krasheninnikov – Hadoop High Availability
Alex Krasheninnikov – Hadoop High Availability
 
Андрей Денисов – В ожидании мониторинга баз данных
Андрей Денисов – В ожидании мониторинга баз данныхАндрей Денисов – В ожидании мониторинга баз данных
Андрей Денисов – В ожидании мониторинга баз данных
 
Александр Зобнин, Grafana Labs
Александр Зобнин, Grafana LabsАлександр Зобнин, Grafana Labs
Александр Зобнин, Grafana Labs
 
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественно
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественноИлья Аблеев – Zabbix в Badoo: реагируем быстро и качественно
Илья Аблеев – Zabbix в Badoo: реагируем быстро и качественно
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, Badoo
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, Erlyvideo
 
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»  Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
Паша Мурзаков: Как 200 строк на Go помогли нам освободить 15 серверов»
 
Как мы готовим MySQL
 Как мы готовим MySQL  Как мы готовим MySQL
Как мы готовим MySQL
 
Архитектура хранения и отдачи фотографий в Badoo
Архитектура хранения и отдачи фотографий в Badoo Архитектура хранения и отдачи фотографий в Badoo
Архитектура хранения и отдачи фотографий в Badoo
 
5 способов деплоя PHP-кода в условиях хайлоада
5 способов деплоя PHP-кода в условиях хайлоада5 способов деплоя PHP-кода в условиях хайлоада
5 способов деплоя PHP-кода в условиях хайлоада
 
ChromeDriver Jailbreak
ChromeDriver JailbreakChromeDriver Jailbreak
ChromeDriver Jailbreak
 
Git хуки на страже качества кода
Git хуки на страже качества кодаGit хуки на страже качества кода
Git хуки на страже качества кода
 

Как мы делаем модули PHP в Badoo – Антон Довгаль

  • 1. Антон Довгаль 20 июля 2017 Модули PHP в Badoo
  • 2. ● Свой первый модуль написал в 16 лет 2004 году - PECL/memcache ● Когда-то давно написал PECL/rar, PECL/sphinx, PECL/memtrack и ещё какой-то трэш, по пути исправив сотни багов в PHP ● Успел 3 года поработать в Zend (в основном над Zend Server), в процессе переписал заново PECL/oci8 ● 10 лет в Badoo: поддержка/доработка PHP, разработка сервисов на C, недорого Про меня
  • 3. ● Крупнейший сервис знакомств в мире - 350 млн пользователей ● ~3 млн строк кода на PHP + ~1.5 млн строк тестов ● ~1000 серверов с PHP-FPM (разработан в Badoo, добавлен в PHP в 2010 году) ● ~600 серверов MySQL ● >200 инженеров ● 2 + 0.5 + 0.5 (=3?) датацентра ● 2 офиса разработки - Москва и Лондон Про Badoo
  • 4. Модули PHP они же - экстеншены
  • 5. ● Как работает PHP с модулями? ● Что представляют из себя модули PHP? ● Как и на чём их пишут? ● Зачем их (иногда) нужно писать? ● Как они работают? ● Как начать писать свой модуль PHP ● Пара примеров из жизни У меня был план
  • 6. Архитектура PHP в двух словах
  • 7. ● Пишутся на C/C++ ● Статические модули - встроены в PHP, нельзя выгрузить ● Динамические - обычный .so/.dll, можно загрузить dl() ● Могут использовать сторонние библиотеки на C/C++ Модули PHP
  • 8. ● встроенные (standard, date, pcre, SPL, Reflection) ● собираемые по умолчанию (ctype, dom, hash, json etc.) ● поставляемые в дистрибуции ● модули из PECL - pecl.php.net ● сторонние модули - Github & Co. Виды модулей PHP
  • 10. ● обычные модули ○ имплементируют функции, классы, методы ● Zend extension ○ имплементируют функции, классы, методы ○ вмешиваются в работу ядра (opcache, XDebug) Типы модулей PHP
  • 11. ● blitz - движок шаблонов на C ● geoi - используется для гео-поиска ● gpbs - общий интерфейс к нашим сервисам на C/C++/Go ● handlersocketi - интерфейс к HS ● imatch - сравнение изображений, поиск дубликатов ● leptonica - работа с изображениями: ресайз, поворот, искажения для капчи ● memtrack - следит за использованием памяти в PHP, ищет прожорливые функции ● pinba - клиент для нашего сервиса статистики на базе MySQL Нестандартные модули PHP в Badoo
  • 12. ● Нужен интерфейс к библиотеке на C/C++ (mysql, oci8) ● Есть задача, которая не решается на PHP (gpbs) ● Есть узкое место в коде, которое можно оптимизировать на C (blitz) ● Нужно добавить функционал в сам PHP (xdebug) ● Хочется посмотреть “что у ней внутре” Причины написания своего модуля
  • 14. > git clone https://github.com/php/php-src > cd php-src/ext > ./ext_skel ./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]] [--skel=dir] [--full-xml] [--no-help] --extname=module module is the name of your extension --proto=file file contains prototypes of functions to create --stubs=file generate only function stubs in file --xml generate xml documentation to be added to phpdoc-svn --skel=dir path to the skeleton directory --full-xml generate xml documentation for a self-contained extension (not yet implemented) --no-help don't try to be nice and create comments in the code and helper functions to test if the module compiled Пишем модуль PHP
  • 15. > ./ext_skel --extname=example Creating directory example Creating basic files: config.m4 config.w32 .gitignore example.c php_example.h CREDITS EXPERIMENTAL tests/001.phpt example.php [done]. Пишем модуль PHP
  • 16. config.m4 - опции configure и проверки библиотек, хидеров и пр. config.w32 - используется для сборки под Windows CREDITS - информация об авторах EXPERIMENTAL - файл-метка, показывающий статус модуля .gitignore - игнорируем мусор от сборки php_example.h - заголовок модуля example.c - исходник модуля example.php - небольшой скрипт для демонстрации работы tests/ - ??? какие тесты ??? Пишем модуль PHP
  • 17. config.m4: PHP_ARG_ENABLE(example, whether to enable example support, [ --enable-example Enable example support]) if test "$PHP_EXAMPLE" != "no"; then PHP_NEW_EXTENSION(example, example.c, $ext_shared) fi Пишем модуль PHP
  • 18. ● Функции-обработчики: ○ MINIT - при загрузке/старт PHP ○ MSHUTDOWN - при выгрузке/окончание работы PHP ○ MINFO - вывод в phpinfo() ○ RINIT - начало запроса, на каждый запрос ○ RSHUTDOWN - конец запроса, на каждый запрос ● Функции, методы классов ● Список функций модуля - zend_function_entry[] ● Структура модуля - zend_module_entry Структура модуля PHP
  • 19. php_example.h: #ifndef PHP_EXAMPLE_H #define PHP_EXAMPLE_H extern zend_module_entry example_module_entry; #define phpext_example_ptr &example_module_entry #define PHP_EXAMPLE_VERSION "0.1.0" #endif /* PHP_EXAMPLE_H */ Пишем модуль PHP
  • 20. example.c: #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_example.h" … Пишем модуль PHP
  • 21. example.c: … /* {{{ proto string confirm_example_compiled(string arg) Return a string to confirm that the module is compiled in */ PHP_FUNCTION(confirm_example_compiled) { char *arg = NULL; size_t arg_len, len; zend_string *strg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) { return; } strg = strpprintf(0, "Congratulations! You have successfully modified ext/%s/config.m4. Module %s is now compiled into PHP.", "example", arg); RETURN_STR(strg); } /* }}} */ … Пишем модуль PHP
  • 22. БЕЗ ПАНИКИ! всё это можно потом найти тут: github.com/tony2001/example
  • 23. example.c: … /* {{{ proto string confirm_example_compiled(string arg) Return a string to confirm that the module is compiled in */ /* }}} */ … Пишем модуль PHP
  • 25. #define PHP_FUNCTION(name) ZEND_FUNCTION(name) #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) #define ZEND_FN(name) zif_##name #define ZEND_NAMED_FUNCTION(name) name(INTERNAL_FUNCTION_PARAMETERS) #define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value PHP_FUNCTION(name) => zif_name(zend_execute_data *execute_data, zval *return_value) PHP + макросы = ❤
  • 26. #define RETURN_STR(s) { RETVAL_STR(s); return; } #define RETVAL_STR(s) ZVAL_STR(return_value, s) #define ZVAL_STR(z, s) do { zval *__z = (z); zend_string *__s = (s); Z_STR_P(__z) = __s; /* interned strings support */ Z_TYPE_INFO_P(__z) = ZSTR_IS_INTERNED(__s) ? IS_INTERNED_STRING_EX : IS_STRING_EX; } while (0) PHP + макросы = ❤
  • 27. typedef union _zend_value { zend_long lval; /* long value */ double dval; /* double value */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; <---------- :) void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } zend_value; Переменные в PHP. ZVAL
  • 29. example.c: … char *arg = NULL; size_t arg_len, len; zend_string *strg; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) { return; } … Пишем модуль PHP
  • 30. example.c: … strg = strpprintf(0, "Congratulations! You have successfully modified ext/%s/config.m4. Module %s is now compiled into PHP.", "example", arg); RETURN_STR(strg); } /* }}} */ … Пишем модуль PHP
  • 32. example.c: … const zend_function_entry example_functions[] = { PHP_FE(confirm_example_compiled, NULL) PHP_FE_END }; zend_module_entry example_module_entry = { STANDARD_MODULE_HEADER, "example", example_functions, NULL, //MINIT NULL, //MSHUTDOWN NULL, //RINIT NULL, //RSHUTDOWN PHP_MINFO(example), PHP_EXAMPLE_VERSION, STANDARD_MODULE_PROPERTIES }; Пишем модуль PHP
  • 33. Нам понадобится phpize и заголовки PHP. Обычно они есть в пакетах: ● php7-devel ● или php-devel ● или php-dev Пишем Собираем модуль PHP
  • 34. > phpize Configuring for: PHP Api Version: 20160303 Zend Module Api No: 20160303 Zend Extension Api No: 320160303 > ./configure --with-php-config=/path/to/php/php-config configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu checking for grep that handles long lines and -e... /usr/bin/grep … … > make install Installing shared extensions: /path/to/php/lib64/extensions/debug-non-zts-20160303/ Пишем Собираем модуль PHP
  • 35. <?php dl('example.so'); echo confirm_example_compiled(“example”); ?> Используем модуль PHP Congratulations! You have successfully modified ext/example/config.m4. Module “example” is now compiled into PHP.
  • 37. Пример из жизни #1 совсем простой
  • 38. Код для “шифрования” ID пользователя:     function map_canonical($n, $d = true)     { $seed = 3358638055; $map1 = array(31, 27, 23, 19, 15, 11, 7, 3, 28, 24, 20, 16, 12, 8, 4, 0, 29, 25, 21, 17, 13, 9, 5, 1, 30, 26, 22, 18, 14, 10, 6, 2); $map2 = array(15, 23, 31, 7, 14, 22, 30, 6, 13, 21, 29, 5, 12, 20, 28, 4, 11, 19, 27, 3, 10, 18, 26, 2, 9, 17, 25, 1, 8, 16, 24, 0);         $m = 0;         $n = $d ? $n : ($n ^ $seed);         foreach ($d ? $map1 : $map2 as $i => $l) {             $k = $n & (1 << $i);             if ($k) $m |= 1 << $l;         }         return $d ? $m ^ $seed : $m;     } Пример #1. Оригинал на PHP
  • 39. Вызовем 100 млн раз: # time php5.3 /tmp/original.php real 9m9.008s user 9m8.904s sys 0m0.028s ~180 тысяч вызовов в секунду Пример #1. Оригинал на PHP
  • 40. static PHP_FUNCTION(bi_map_encode) /* {{{ */ { long n; unsigned int result = 0; unsigned int number; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) { return; } number = (unsigned int)n; #define K(i) (number & (1 << i)) #define ITER(i, n) result += (n > i) ? (K(i) << (n - i)) : (K(i) >> (i - n)); ITER(0, 31); ITER(1, 27); ITER(2, 23); ITER(3, 19); … Пример #1. Жалкая пародия на C
  • 41. Вызовем 100 млн раз: # time php5.3 /tmp/copy.php real 0m9.427s user 0m9.417s sys 0m0.008s ~11 млн вызовов в секунду т.е. в 60 раз быстрее Пример #1. Жалкая пародия на C
  • 42. 5.3 PHP - ~550 секунд Модуль - ~9 секунд Мини-бенчмарк PHP 5.3 vs PHP 7.1 7.1 PHP - ~100 секунды Модуль - ~4 секунды
  • 44. Пример из жизни #2 чуть посложнее
  • 45.
  • 46. <?php $connect = memcache_connect(“service.host”, 3113); $result = memcache_laccess_update($connect, $anketa_id, $user_id, $mode, $command, $partner_id); C: модуль - snprintf(buf, sizeof(buf), "laccess_update v17 %u %u %c %c %u %s %u", aid, user_id, mode, command, partner_id, ip, country_id); сервис - sscanf(buf, "%u %ld %ld %c %f %f %c %*s %*s %ld %*s %*s %ld %*s %*s %*s %*s %ld"....); >_< Пример #2. Текстовый протокол
  • 47. Минусы: ○ приходится постоянно менять модуль PHP вместе с API сервисов ○ неэкономно расходуется сеть ○ сложный разбор аргументов методов Плюсы: ○ человеко-читабельность протокола Пример #2. Текстовый протокол
  • 48.
  • 49. ● Google Protobuf: формат сериализации, бинарная альтернатива XML, JSON и пр. ● Google Protocol Buffers Service - RPC на базе GPB ● Формат данных задаётся proto-файлом ● Из proto можно генерировать код на C, C++, PHP, Go, Java, Python и прочих языках ● gRPC - официальный RPC от Google 2015 года, но у нас всё работает c 2011 года Пример #2. GPBS
  • 50. Пример #2. GPBS package badoo.cityd2; message city { required uint32 id = 1; required string name = 2; required uint32 lang_id = 3; required uint32 user_cnt = 4; optional float lat = 5; optional float lon = 6; } message request_find_city { required string name = 1; optional uint32 limit = 2; repeated uint32 lang_ids = 3; } message response_cities { repeated city cities = 1; }
  • 51. - с помощью protobuf-c генерируем из proto-файла код на C и дескриптор (описывает все структуры в proto a-la reflection) - собираем код в .so, добавляя дескриптор - подгружаем .so в PHP (dlopen, dlsym) - используем для кодирования/декодирования пакетов Protobuf в модуле Пример #2. GPBS
  • 52. <?php $module = gpbs_import(“cityd.so”); $connect = gpbs_connect(“cityd.host”, 1331, $module); $call_result = gpbs_call(“find_city”, array(“name” => ”mos”)); //добавляем новый аргумент $call_result = gpbs_call(“find_city”, array(“name” => ”mos”, “country_id” => 1)); Пример #2. GPBS
  • 53. Разница между GPB и JSON: <?php //грузим .so, создаём объект модуля со всеми методами из дескриптора $so = gpbs_import(“cityd.so"); //сериализуем запрос в Protobuf $j = gpbs_serialize($so->request_find_city, array("name" => "mos", "limit"=>10, "lang_ids"=>array(1,2,3))); var_dump($j); // string(13). Тот же самый запрос в JSON - 44 байта! Пример #2. GPBS
  • 54. Плюсы: ● все сервисы унифицированы, используют общую базу кода ● бинарный протокол - меньше потребление сети ● при изменениях в API сервиса нужно пересобрать .so из proto-файла, в остальном меняется только PHP-код клиентской части Пример #2. RPC на Google Protobufs Минусы: ● бинарный протокол приходится разбирать Wireshark
  • 55. Плюсы: ● все сервисы унифицированы, используют общую базу кода ● бинарный протокол - меньше потребление сети ● при изменениях в API сервиса нужно пересобрать .so из proto-файла, в остальном меняется только PHP-код клиентской части Пример #2. RPC на Google Protobufs Ещё плюсы: ● можно генерить JSON!
  • 56.
  • 57. PHP: ● PHP at the Core: A Hacker's Guide php.net/manual/en/internals2.php ● Extending and Embedding PHP, Sara Golemon 2006 (местами устарела). ● Читайте исходники PHP и других модулей! Google Protobuf: ● github.com/google/protobuf ● github.com/grpc/grpc Badoo: ● techblog.badoo.com ● habrahabr.ru/company/badoo Полезные ссылки