SlideShare uma empresa Scribd logo
1 de 17
Расширяем PHP



доклад для тех, кто скучает по <?php asm mov ax,bx; ?>
Зачем понадобилось расширение?

Имеется собственный движок для разработки сайтов
и систем автоматизации бизнеса (PHP+MySQL+JS).
Движок используется с 2006 года.


Используется собственный шаблонизатор,
к которому мы очень привыкли.




 Вопрос «Почему не использовали [SMARTY|XSLT|…]» оставим за рамками доклада
Как выглядит шаблонизатор?

Пример шаблона:                                 Результат:
<ul>                                             <ul>
       {:list}                                          <li> первый пункт </li>
            <li> {!item} </li>                          <li> второй пункт </li>
       {:/list}                                  </ul>
</ul>

Подача данных в шаблон:

Array( “list” => Array (
                        Array ( “item” => ”первый пункт” ),
                        Array ( “item” => ”второй пункт” )));




 Вопрос о достоинствах и недостатках шаблонизатора оставим за рамками
 доклада
Как это обрабатывалось в PHP?

Примерно такой конструкцией:

$result = preg_replace(”/
        {([?~:])([a-zA-Z0-9_]*)(([<>!=]{1,2})
        ([a-zA-Z0-9_]*)){0,1}}(.*){1/2}
        /iseU”,
  ”ProcessBlock(‘$0′, ‘$1′, ‘$2′, ‘$4′, ‘$5′, ‘$6′, $vars_arr) ”,
  $result);




 Регулярное выражение с eval’ом
И что, это работало?

Да!
За пять лет на этом движке было создано
порядка двухсот проектов.

И все было бы хорошо, если бы на некоторых проектах
нас не стала подводить производительность парсера.
В определенных условиях он потребляет серьезное
количество ресурсов – памяти и процессора.




 Что же нам делать???
Что же нам делать?

Первой идеей было создание компилирующего
шаблонизатора. Шаблон должен трансформироваться
в HTML, перемешанный с простыми управляющими
конструкциями PHP (циклы, условия, вывод).
На вход такому скрипту-шаблону подаются данные,
скрипт выполняется, получаем HTML-страницу.

Не получилось – шаблонизатор является управляющим
(возможен вызов программных модулей и их методов
из шаблона), шаблоны могут каскадироваться.




 Скорее всего, задача решаема – но из наших программистов не решил ее никто.
Какие проблемы были
с компилирующим шаблонизатором?

Схема парсинга:

                           Шаблон
   Шаблон                                            Шаблон
                        программного
   страницы                                        интерфейса
                           модуля


    Тело                 Класс в PHP          Метод в классе в PHP
  страницы




 Скорее всего, задача решаема – но из наших программистов не решил ее никто.
А напишем расширение!

Вторая идея – написать на C++ расширение, которое будет
сливать шаблон с данными.
И это сработало!
На пути нам встретились три основные проблемы.




 На самом деле, их было значительно больше.
Первая проблема: как в недрах PHP представлены
ассоциативные массивы…

Данные, хранящиеся в ассоциативных массивах в PHP,
становятся в C++ объектами HashTable.
Работать с ними можно при помощи набора функций –
довольно неудобных (начать с названий – как вам нравится
zend_hash_internal_pointer_reset_ex?).
Работа с многоэтажными массивами превращается
в сложное занятие.

А у нас в движке данные как раз хранятся в многоэтажных
массивах. Каждый уровень вложенности (метод, цикл) –
это новый уровень вложенности массива.



 В принципе, можно нас обвинить в том, что мы сами себе придумали проблему.
Как решили?

За один проход разворачиваем всю иерархию
ассоциативных массивов в два обычных массива –
один с ключами, второй со значениями.
Ключи при этом собираем в одну строку.

$arr = Array ( “first” => 1,
                “second” => Array (
                             Array ( “number” => 2 )));

Keys = [ "first ", "second0number" ];
Values = [ "1",    "2" ];

Заодно преобразуем и ключи, и значения в строки.
  Поиск значения с любого «этажа» - чистое удовольствие!
Вторая проблема: как вызвать функцию,
 содержащуюся в PHP-скрипте, из расширения?
zval *function, *itemname, *retval;
zval **params[1];                     пусть itemname – параметр функции function
MAKE_STD_ZVAL ( function );
MAKE_STD_ZVAL ( itemname );
ZVAL_STRING ( function, “MyPHPFunction“, 1);
ZVAL_STRING ( itemname, “значение“, 1);
                                               нигде не определенный параметр
params[0] = &itemname;
if ( call_user_function_ex ( CG (function_table), NULL, function, &retval, 1, params, 0,
NULL TSRMLS_CC ) == FAILURE )                                           непонятный макрос
             zend_error (E_ERROR, “Function call failed“);
else {
          if ( Z_TYPE_P (retval) == IS_STRING ) {
                     … тут мы можем обработать возвращенное значение, используя
макросы
          Z_STRLEN_P ( retval ) и Z_STRVAL_P ( retval )



    Этот код работает только внутри функции, вызываемой из PHP:
    ZEND_FUNCTION(Func)
Как решили?

Документация тут не поможет… лезем в исходники PHP.

Оказывается, function_table – это параметр, передаваемый
в ZEND_FUNCTION.

За макросом TSRMLS_CC скрывается переменная tsrm_ls,
тоже являющаяся одним из стандартных параметров для
функций, объявленных при помощи ZEND_FUNCTION.

Остается передать эти параметры в нашу innerCPPFunction:

char *result = innerCPPFunction ( CG ( function_table ), tsrm_ls );
char *innerCPPFunction ( HashTable *function_table, void ***tsrm_ls )
{…}
  innerCPPFunction – это функция, куда мы захотели вынести вызов функции PHP
Передача выполнения между PHP и расширением

Схема парсинга:

                           Шаблон
   Шаблон                                            Шаблон
                        программного
   страницы                                        интерфейса
                           модуля


     Тело                Класс в PHP          Метод в классе в PHP
   страницы


PHP => extension => PHP => extenstion    => PHP => extension




 Скорее всего, задача решаема – но из наших программистов не решил ее никто.
Третья проблема: глобальные переменные

Глобальные переменные (например, общие массивы ключей
и значений), объявленные в расширении, сохраняют свои
значения между вызовами различных функций из PHP.

Приходится о них заботиться. Учитывая, что схема парсинга
выглядит так: сначала из PHP вызывается функция
расширения, которая сливает данные с шаблоном верхнего
уровня, а затем она вызывает функции из PHP, которые
инициализируют содержащиеся в странице программные
модули (и цикл повторяется). То есть, выполнение переходит
из PHP в расширение, затем обратно в PHP, затем снова
в расширение. При втором вызове как раз важно не забыть
о том, что глобальные переменные первым вызовом
уже проинициализированы.

 Ура, расширение работает!
Что выиграли в плане производительности?

Парсинг  при            помощи          регулярных        100%
выражений
Парсинг при помощи расширения PHP                         53%


XMLXSLT                                                  36%


«чистый»    PHP                 (компилирующий             3%
шаблонизатор)




 парсинг при помощи регулярных выражений принят за 100%
Выводы?
Конечно, «чистый» PHP побеждает с чудовищным отрывом.
Но проблема создания компилирующего шаблонизатора
для движка с управляющим синтаксисом шаблона все еще
ждет своего героя…

Поэтому в итоге было принято решение использовать
в новой версии нашего продукта шаблонизацию XSLT:
дополнительный плюс состоит в том, что этот язык является
стандартом, с которым некоторые разработчики уже
знакомы, а не собственным «эксклюзивным» решением.

А расширение PHP, реализующее парсер «старого»
синтаксиса, помогло нам улучшить производительность
ранее написанных программных систем, уже работающих
у наших клиентов.
 А еще теперь мы знаем, как сделать <?php asm mov ax,bx; ?>
Спасибо за внимание!
                     Вопросы?



Также можно обсудить в ЖЖ:

http://serge-index.livejournal.com

Mais conteúdo relacionado

Mais procurados

Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»
Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»
Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»SpbDotNet Community
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2Technopark
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6Technopark
 
Конструирование алгоритмов
Конструирование алгоритмовКонструирование алгоритмов
Конструирование алгоритмовAndrey Dolinin
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.Igor Shkulipa
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в javaUnguryan Vitaliy
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2Technopark
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФПAlexander Granin
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействиеUnguryan Vitaliy
 
C++ осень 2013 лекция 6
C++ осень 2013 лекция 6C++ осень 2013 лекция 6
C++ осень 2013 лекция 6Technopark
 
C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.Igor Shkulipa
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4Technopark
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняAlexander Granin
 
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.7bits
 

Mais procurados (19)

Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»
Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»
Роман Неволин «Функциональные трюки для вашего объектно-ориентированного кода»
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2
 
Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Java. Методы
Java. Методы Java. Методы
Java. Методы
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6
 
Конструирование алгоритмов
Конструирование алгоритмовКонструирование алгоритмов
Конструирование алгоритмов
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в java
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2
 
лек13 4
лек13 4лек13 4
лек13 4
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействие
 
Java: вчера, сегодня, завтра
Java: вчера, сегодня, завтраJava: вчера, сегодня, завтра
Java: вчера, сегодня, завтра
 
C++ осень 2013 лекция 6
C++ осень 2013 лекция 6C++ осень 2013 лекция 6
C++ осень 2013 лекция 6
 
C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодня
 
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
 

Semelhante a DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)

Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальBadoo Development
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptTimur Shemsedinov
 
Функциональное программирование для разработки распределённых, облачных и веб...
Функциональное программирование для разработки распределённых, облачных и веб...Функциональное программирование для разработки распределённых, облачных и веб...
Функциональное программирование для разработки распределённых, облачных и веб...Dmitri Soshnikov
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 
Сборник практических задании по Php
Сборник практических задании по PhpСборник практических задании по Php
Сборник практических задании по PhpRauan Ibraikhan
 
вспомогательные алгоритмы
вспомогательные алгоритмывспомогательные алгоритмы
вспомогательные алгоритмыЕлена Ключева
 
Microsoft Visual Studio 2010
Microsoft Visual Studio 2010Microsoft Visual Studio 2010
Microsoft Visual Studio 2010Alexander Babich
 
Отладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программОтладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программTatyanazaxarova
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Platonov Sergey
 
Систематизация экспрешнов в IE
Систематизация экспрешнов в IEСистематизация экспрешнов в IE
Систематизация экспрешнов в IERoman Komarov
 
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 27bits
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычностьStepan Tanasiychuk
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
 
Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Alexey Kachayev
 
Catalyst – MVC framework на Perl (RIT 2008)
Catalyst – MVC framework на Perl  (RIT 2008)Catalyst – MVC framework на Perl  (RIT 2008)
Catalyst – MVC framework на Perl (RIT 2008)Sergey Skvortsov
 

Semelhante a DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art) (20)

Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон Довгаль
 
пр 15.docx
пр 15.docxпр 15.docx
пр 15.docx
 
прак 15.docx
прак 15.docxпрак 15.docx
прак 15.docx
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScript
 
Java 9 - кратко о новом
Java 9 -  кратко о новомJava 9 -  кратко о новом
Java 9 - кратко о новом
 
Функциональное программирование для разработки распределённых, облачных и веб...
Функциональное программирование для разработки распределённых, облачных и веб...Функциональное программирование для разработки распределённых, облачных и веб...
Функциональное программирование для разработки распределённых, облачных и веб...
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
Сборник практических задании по Php
Сборник практических задании по PhpСборник практических задании по Php
Сборник практических задании по Php
 
вспомогательные алгоритмы
вспомогательные алгоритмывспомогательные алгоритмы
вспомогательные алгоритмы
 
Microsoft Visual Studio 2010
Microsoft Visual Studio 2010Microsoft Visual Studio 2010
Microsoft Visual Studio 2010
 
Отладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программОтладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программ
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
 
Систематизация экспрешнов в IE
Систематизация экспрешнов в IEСистематизация экспрешнов в IE
Систематизация экспрешнов в IE
 
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2
Спецкурс "Современные практики разработки ПО", 2013-2014 уч. год, занятие 2
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычность
 
Log+
Log+Log+
Log+
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
 
Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)
 
Catalyst – MVC framework на Perl (RIT 2008)
Catalyst – MVC framework на Perl  (RIT 2008)Catalyst – MVC framework на Perl  (RIT 2008)
Catalyst – MVC framework на Perl (RIT 2008)
 

Mais de it-people

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Coit-people
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghubit-people
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrainsit-people
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologiesit-people
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндексit-people
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...it-people
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalrit-people
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...it-people
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАНit-people
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банкit-people
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Coit-people
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНСit-people
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...it-people
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologiesit-people
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn Systemit-people
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologiesit-people
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндексit-people
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...it-people
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognicianit-people
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...it-people
 

Mais de it-people (20)

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
 

DUMP-2012 - Только хардкор! - "Расширяем PHP" Сергей Горшков (index.art)

  • 1. Расширяем PHP доклад для тех, кто скучает по <?php asm mov ax,bx; ?>
  • 2. Зачем понадобилось расширение? Имеется собственный движок для разработки сайтов и систем автоматизации бизнеса (PHP+MySQL+JS). Движок используется с 2006 года. Используется собственный шаблонизатор, к которому мы очень привыкли. Вопрос «Почему не использовали [SMARTY|XSLT|…]» оставим за рамками доклада
  • 3. Как выглядит шаблонизатор? Пример шаблона: Результат: <ul> <ul> {:list} <li> первый пункт </li> <li> {!item} </li> <li> второй пункт </li> {:/list} </ul> </ul> Подача данных в шаблон: Array( “list” => Array ( Array ( “item” => ”первый пункт” ), Array ( “item” => ”второй пункт” ))); Вопрос о достоинствах и недостатках шаблонизатора оставим за рамками доклада
  • 4. Как это обрабатывалось в PHP? Примерно такой конструкцией: $result = preg_replace(”/ {([?~:])([a-zA-Z0-9_]*)(([<>!=]{1,2}) ([a-zA-Z0-9_]*)){0,1}}(.*){1/2} /iseU”, ”ProcessBlock(‘$0′, ‘$1′, ‘$2′, ‘$4′, ‘$5′, ‘$6′, $vars_arr) ”, $result); Регулярное выражение с eval’ом
  • 5. И что, это работало? Да! За пять лет на этом движке было создано порядка двухсот проектов. И все было бы хорошо, если бы на некоторых проектах нас не стала подводить производительность парсера. В определенных условиях он потребляет серьезное количество ресурсов – памяти и процессора. Что же нам делать???
  • 6. Что же нам делать? Первой идеей было создание компилирующего шаблонизатора. Шаблон должен трансформироваться в HTML, перемешанный с простыми управляющими конструкциями PHP (циклы, условия, вывод). На вход такому скрипту-шаблону подаются данные, скрипт выполняется, получаем HTML-страницу. Не получилось – шаблонизатор является управляющим (возможен вызов программных модулей и их методов из шаблона), шаблоны могут каскадироваться. Скорее всего, задача решаема – но из наших программистов не решил ее никто.
  • 7. Какие проблемы были с компилирующим шаблонизатором? Схема парсинга: Шаблон Шаблон Шаблон программного страницы интерфейса модуля Тело Класс в PHP Метод в классе в PHP страницы Скорее всего, задача решаема – но из наших программистов не решил ее никто.
  • 8. А напишем расширение! Вторая идея – написать на C++ расширение, которое будет сливать шаблон с данными. И это сработало! На пути нам встретились три основные проблемы. На самом деле, их было значительно больше.
  • 9. Первая проблема: как в недрах PHP представлены ассоциативные массивы… Данные, хранящиеся в ассоциативных массивах в PHP, становятся в C++ объектами HashTable. Работать с ними можно при помощи набора функций – довольно неудобных (начать с названий – как вам нравится zend_hash_internal_pointer_reset_ex?). Работа с многоэтажными массивами превращается в сложное занятие. А у нас в движке данные как раз хранятся в многоэтажных массивах. Каждый уровень вложенности (метод, цикл) – это новый уровень вложенности массива. В принципе, можно нас обвинить в том, что мы сами себе придумали проблему.
  • 10. Как решили? За один проход разворачиваем всю иерархию ассоциативных массивов в два обычных массива – один с ключами, второй со значениями. Ключи при этом собираем в одну строку. $arr = Array ( “first” => 1, “second” => Array ( Array ( “number” => 2 ))); Keys = [ "first ", "second0number" ]; Values = [ "1", "2" ]; Заодно преобразуем и ключи, и значения в строки. Поиск значения с любого «этажа» - чистое удовольствие!
  • 11. Вторая проблема: как вызвать функцию, содержащуюся в PHP-скрипте, из расширения? zval *function, *itemname, *retval; zval **params[1]; пусть itemname – параметр функции function MAKE_STD_ZVAL ( function ); MAKE_STD_ZVAL ( itemname ); ZVAL_STRING ( function, “MyPHPFunction“, 1); ZVAL_STRING ( itemname, “значение“, 1); нигде не определенный параметр params[0] = &itemname; if ( call_user_function_ex ( CG (function_table), NULL, function, &retval, 1, params, 0, NULL TSRMLS_CC ) == FAILURE ) непонятный макрос zend_error (E_ERROR, “Function call failed“); else { if ( Z_TYPE_P (retval) == IS_STRING ) { … тут мы можем обработать возвращенное значение, используя макросы Z_STRLEN_P ( retval ) и Z_STRVAL_P ( retval ) Этот код работает только внутри функции, вызываемой из PHP: ZEND_FUNCTION(Func)
  • 12. Как решили? Документация тут не поможет… лезем в исходники PHP. Оказывается, function_table – это параметр, передаваемый в ZEND_FUNCTION. За макросом TSRMLS_CC скрывается переменная tsrm_ls, тоже являющаяся одним из стандартных параметров для функций, объявленных при помощи ZEND_FUNCTION. Остается передать эти параметры в нашу innerCPPFunction: char *result = innerCPPFunction ( CG ( function_table ), tsrm_ls ); char *innerCPPFunction ( HashTable *function_table, void ***tsrm_ls ) {…} innerCPPFunction – это функция, куда мы захотели вынести вызов функции PHP
  • 13. Передача выполнения между PHP и расширением Схема парсинга: Шаблон Шаблон Шаблон программного страницы интерфейса модуля Тело Класс в PHP Метод в классе в PHP страницы PHP => extension => PHP => extenstion => PHP => extension Скорее всего, задача решаема – но из наших программистов не решил ее никто.
  • 14. Третья проблема: глобальные переменные Глобальные переменные (например, общие массивы ключей и значений), объявленные в расширении, сохраняют свои значения между вызовами различных функций из PHP. Приходится о них заботиться. Учитывая, что схема парсинга выглядит так: сначала из PHP вызывается функция расширения, которая сливает данные с шаблоном верхнего уровня, а затем она вызывает функции из PHP, которые инициализируют содержащиеся в странице программные модули (и цикл повторяется). То есть, выполнение переходит из PHP в расширение, затем обратно в PHP, затем снова в расширение. При втором вызове как раз важно не забыть о том, что глобальные переменные первым вызовом уже проинициализированы. Ура, расширение работает!
  • 15. Что выиграли в плане производительности? Парсинг при помощи регулярных 100% выражений Парсинг при помощи расширения PHP 53% XMLXSLT 36% «чистый» PHP (компилирующий 3% шаблонизатор) парсинг при помощи регулярных выражений принят за 100%
  • 16. Выводы? Конечно, «чистый» PHP побеждает с чудовищным отрывом. Но проблема создания компилирующего шаблонизатора для движка с управляющим синтаксисом шаблона все еще ждет своего героя… Поэтому в итоге было принято решение использовать в новой версии нашего продукта шаблонизацию XSLT: дополнительный плюс состоит в том, что этот язык является стандартом, с которым некоторые разработчики уже знакомы, а не собственным «эксклюзивным» решением. А расширение PHP, реализующее парсер «старого» синтаксиса, помогло нам улучшить производительность ранее написанных программных систем, уже работающих у наших клиентов. А еще теперь мы знаем, как сделать <?php asm mov ax,bx; ?>
  • 17. Спасибо за внимание! Вопросы? Также можно обсудить в ЖЖ: http://serge-index.livejournal.com