Каждый слот имеет список тэгов, которыми он помечен, вместе с версиями этих тэгов. При инвалидации тэга его версия изменяется, поэтому библиотека при извлечении очередного слота понимает, что он «протух». Ну а для ускорения операции используется «групповой фетч» в memcached, который поддерживается в новых версиях PHP (т.е. за один запрос к memcached получаются сразу все тэги некоторого слота).
На тот момент, когда я ее проверял (несколько месяцев назад) она сегфолтилась, а иногда висла и начинала бесконечно отжирать память. Возможно, сейчас ее уже починили. Кстати, в дистрибутиве Dklab_Cache есть Dklab_Cache_Backend_MemcachedTag, который именно для memcached-tags предназначен (адаптер для Zend_Cache_Backend).
Если глянуть в исходники библиотеки, то видно, что краевых условий и нюансов там действительно много. Например, NULL в array и hstore выглядит как NULL, в ROWTYPE — просто как пропуск значения между двух запятых. Кавычки квотятся по-разному: в array и hstore — слэшем, в ROWTYPE — удвоением. Соответствующие особенности и с квотингом слэшей и пустых строк, а также непустых строк (где-то их нужно заключать в кавычки, где-то нет).
Соответственно, данная библиотека полезна тем, кому нужно проверенное и покрытое тестами продакшен-решение, устойчивое к инъекциям и виду входных/выходных данных. Те, кто использует типы неактивно, вполне могут обходиться самодельными функциями.
А насчет синтаксиса Propel (и вообще ORM) — то на первый взгляд и правда кажется, что он очень громоздкий. Но на практике эта громоздкость, что удивительно, почти совсем не мешает. А вот много проблем с тем, что Propel (и другие ORM) способствуют неконтролируемому росту кол-ва разновидностей («планов») SQL-запросов, и оптимизировать такой код впоследствии становится очень сложным. SQL оказывается ровным слоем размазанным по всему приложению. Впрочем, та же проблема и с ручной генерацией SQL через тот же DbSimple или PDO. Локализовывать нужно SQL, ох локализовывать…
Ну там в библиотеке как бы не одна строка, а три:
— отслеживание фильтра, какие ошибки преобразовывать в исключения, а какие — нет;
— идеома «выделение ресурса есть инициализация», в результате чего преобразователь нотисов в исключение автоматом отключается при выходе из области видимости текущего блока;
— иерархия «серьезностей» ошибок.
Подозреваю, что ненависть эта связана с WSDL-схемами. Они, как тут выше правильно заметили, «подходят для энтерпрайза». Попробуйте без них, в большинстве случаев жизнь становится сильно легче. Без WSDL PHP-шный SOAP превращается в простой и приятный инструмент, да и с точки зрения ресурсов все достаточно хорошо (по сравнению с обычными издержками на выполнение PHP-кода накладные расходы на SOAP-кодирование и декодирование блекнут).
Хм. Будет знать {some/node}, но не поймет <xsl:value-of select=«some/node» />? Или узнает {if something}, но не додумается до <xsl:choose><xsl:when test=«something»>? Конечно, я понимаю, что новички разные бывают, но чтоб такое не понять, нужно очень сильно постараться…
Про 95% — мне кажется, это сильное преувеличение. Чтобы использовать XSLT в качестве веб-шаблонизатора, нужно как минимум еще применять xsl:template, xsl:call-template (или apply-templates, но это реже) и xsl:import. Без них никакого шаблонизатора не сделать, а чтобы их применять, нужно очень хорошо себе представлять, как работает xslt.
Да, но в этом случае мы теряем в производительности: придется результат XSLT-преобразования прогонять через еще одно XSLT-преобразование для замены локализованных вставок. Кроме того, для улучшения производительности иногда имеет смысл автоматически «вкомпилить» строковые значения в исходный XSLT еще до преобразования, т.е. заменить {#hello} на «Привет». Тогда не будет тратиться время на вызов функции вида h:const(). Такую замену можно сделать при помощи препроцессор Dklab_DOMDocument, на котором и написан, собственно, ShortXSLT.
Вы совершенно правы, это правда был бы бред. Именно поэтому это не «XSLT-процессор, написанный на PHP», а «система для поддержки упрощенного синтаксиса XSLT для встроенных в PHP-классов XSLTProcessor и DOMDocument». Поправил в посте, чтобы не было недопониманий.
Странно, что в статье большинство пунктов — именно что экономия на спичках. А вот такие важные вещи, как:
— сокращайте число итераций во внутренних циклах: встроенная функция типа array_xxx() и т.д. лучше, чем цикл на 1 тыс. итераций,
— если массивы передаются в параметрах или копируются, после чего меняются, старайтесь сохранять их маленькими
— старайтесь не писать много PHP-кода, принцип KISS
даже не упоминаются. Например, экономия «конкатенация вместо интерполяции» тут меркнет на фоне любого вызова str_replace или preg_replace, которые, конечно же, есть почти в каждом мало-мальски сложном проекте.
Ну не совсем соглашусь. Для МАЛЕНЬКИХ веб-задач, действительно, выбор CGI Perl или PHP — вопрос предпочтения, и они похожи. А вот когда дело доходит до проектов с большим объемом кода и высокими нагрузками, то выбор встает не совсем между Perl и PHP, а скорее между mod_perl и PHP (или между FastCGI Perl и PHP). Названия похожи, а вот методики разработки и архитектура очень сильно различны.
Да, для тех, кто захочет копать. Ключевые слова: SWASH, SWASHGET, encoding.pm, utf8.pm, open.pm. (Кстати, мне никогда не нравилось называть «use utf8» и другие похожие штуки вроде «use strict» прагмой, потому что все «прагмы» на самом деле — обыкновенные модули на Perl. Как правило, они подменяют разные «плохо документированные» переменные типа $^W, которые влияют на результаты компиляции.)
Расскажу интересную историю. Правда, детали я уже успел подзабыть, так что где-то могу ошибиться. Если кто-то поправит, а еще лучше, подкрепит примерами из исходников Perl, буду признателен.
Где-то полгода назад мне пришлось разбираться, как на низком уровне работает поддержка UTF8 в Perl (включая изучение исходников и т.д.). И выяснилась одна очень интересная деталь: по сути, вся встроенная «ядровая» поддержка ограничивается этим самым флагом is_utf8 с минимальной его интерпретацией. Все остальное сделано на Perl-коде. Например, для полноценной работы с Unicode Perl так или иначе подключает encoding.pm, а также 500-килобайтные файлы из lib/Unicode (а возможно, из lib/unicore — я сейчас уже не вспомню). Причем делается это довольно интересно: в Perl-коде можно повесить недокументированный «callback» на ряд операций с unicode-данными, и этот callback будет вызываться из Си-кода ядра Perl. При этом модули типа encoding.pm подсовывают в роли данного callback-а… код на Perl, работающий с огромными файлами в lib/Unicode. Т.е. из ядра Perl вызывается Perl-код, а ядро ничего про Unicode не знает (оно знает про флаг is_utf8, но интерпретирует его только как подсказку для вызова хуков; с тем же успехом он мог называться is_blablabla). Так что с этой точки зрения в Perl по-настоящему встроенной поддержки Unicode как не было, так и нет.
Все это я обнаружил, пытаясь минимизировать объем Perl-кода, который должен поставляться вместе с perl.exe для работы с Unicode. Я просто начал постепенно удалять файлы и смотреть, что происходит. По зависимостям потянулись описанные выше явления.
Почему они не использовали стандартный и проверенный iconv для поддержки Unicode, а сделали обработку через хуки, для меня так и осталось загадкой.
В итоге, как это ни печатльно, по совокупности причин пришлось отказаться от «встроенной» поддержки Unicode совсем (т.к. без файлов в lib/Unicode флаг is_utf8 бесполезен), вместо этого полагаясь на старый механизм и выполняя перекодировки вручную, где это необходимо (вопрос объема и скорости загрузки был критичен). Также я пришел к выводу, что поддержка Unicode в Perl — весьма костыльная, или уж — во всяком случае — по своей чистоте сильно проигрывает таковой в Javascript и Python. Она примерно такая же костыльная, как в PHP5, а может, даже и хуже (потому что в PHP есть какой-никакой встроенный mbstring).
Соответственно, данная библиотека полезна тем, кому нужно проверенное и покрытое тестами продакшен-решение, устойчивое к инъекциям и виду входных/выходных данных. Те, кто использует типы неактивно, вполне могут обходиться самодельными функциями.
А насчет синтаксиса Propel (и вообще ORM) — то на первый взгляд и правда кажется, что он очень громоздкий. Но на практике эта громоздкость, что удивительно, почти совсем не мешает. А вот много проблем с тем, что Propel (и другие ORM) способствуют неконтролируемому росту кол-ва разновидностей («планов») SQL-запросов, и оптимизировать такой код впоследствии становится очень сложным. SQL оказывается ровным слоем размазанным по всему приложению. Впрочем, та же проблема и с ручной генерацией SQL через тот же DbSimple или PDO. Локализовывать нужно SQL, ох локализовывать…
— отслеживание фильтра, какие ошибки преобразовывать в исключения, а какие — нет;
— идеома «выделение ресурса есть инициализация», в результате чего преобразователь нотисов в исключение автоматом отключается при выходе из области видимости текущего блока;
— иерархия «серьезностей» ошибок.
Про 95% — мне кажется, это сильное преувеличение. Чтобы использовать XSLT в качестве веб-шаблонизатора, нужно как минимум еще применять xsl:template, xsl:call-template (или apply-templates, но это реже) и xsl:import. Без них никакого шаблонизатора не сделать, а чтобы их применять, нужно очень хорошо себе представлять, как работает xslt.
Также (ИМХО) «мега-темплейты» не имеют отношения к конструкциям if-else и foreach, а имеют отношение, главным образом, к неопытности XSLT-писателя.
— сокращайте число итераций во внутренних циклах: встроенная функция типа array_xxx() и т.д. лучше, чем цикл на 1 тыс. итераций,
— если массивы передаются в параметрах или копируются, после чего меняются, старайтесь сохранять их маленькими
— старайтесь не писать много PHP-кода, принцип KISS
даже не упоминаются. Например, экономия «конкатенация вместо интерполяции» тут меркнет на фоне любого вызова str_replace или preg_replace, которые, конечно же, есть почти в каждом мало-мальски сложном проекте.
Где-то полгода назад мне пришлось разбираться, как на низком уровне работает поддержка UTF8 в Perl (включая изучение исходников и т.д.). И выяснилась одна очень интересная деталь: по сути, вся встроенная «ядровая» поддержка ограничивается этим самым флагом is_utf8 с минимальной его интерпретацией. Все остальное сделано на Perl-коде. Например, для полноценной работы с Unicode Perl так или иначе подключает encoding.pm, а также 500-килобайтные файлы из lib/Unicode (а возможно, из lib/unicore — я сейчас уже не вспомню). Причем делается это довольно интересно: в Perl-коде можно повесить недокументированный «callback» на ряд операций с unicode-данными, и этот callback будет вызываться из Си-кода ядра Perl. При этом модули типа encoding.pm подсовывают в роли данного callback-а… код на Perl, работающий с огромными файлами в lib/Unicode. Т.е. из ядра Perl вызывается Perl-код, а ядро ничего про Unicode не знает (оно знает про флаг is_utf8, но интерпретирует его только как подсказку для вызова хуков; с тем же успехом он мог называться is_blablabla). Так что с этой точки зрения в Perl по-настоящему встроенной поддержки Unicode как не было, так и нет.
Все это я обнаружил, пытаясь минимизировать объем Perl-кода, который должен поставляться вместе с perl.exe для работы с Unicode. Я просто начал постепенно удалять файлы и смотреть, что происходит. По зависимостям потянулись описанные выше явления.
Почему они не использовали стандартный и проверенный iconv для поддержки Unicode, а сделали обработку через хуки, для меня так и осталось загадкой.
В итоге, как это ни печатльно, по совокупности причин пришлось отказаться от «встроенной» поддержки Unicode совсем (т.к. без файлов в lib/Unicode флаг is_utf8 бесполезен), вместо этого полагаясь на старый механизм и выполняя перекодировки вручную, где это необходимо (вопрос объема и скорости загрузки был критичен). Также я пришел к выводу, что поддержка Unicode в Perl — весьма костыльная, или уж — во всяком случае — по своей чистоте сильно проигрывает таковой в Javascript и Python. Она примерно такая же костыльная, как в PHP5, а может, даже и хуже (потому что в PHP есть какой-никакой встроенный mbstring).