Просмотр JSF при перестройке каждого запроса ajax

У меня проблема с производительностью с моими айсхасами JSF/RichFaces/Facelets и из того, что я могу сказать, потому что все дерево компонентов перестраивается при каждом запросе ajax. Это происходит, даже если я использую ajaxSingle = true, разделы обтекания в области a4j: объявить единый раздел для рендеринга или вообще ничего. Наша страница - динамическая страница со множеством вложенных уровней. Страница может содержать около 800-900 полей (inputText, богатые календари, selectOneMenus и т.д.). Начальное время загрузки - проблема, но я понимаю эту проблему, ее много полей. Как только у нас есть это начальное время сборки/рендеринга, хотя мы разработали все другие действия как ajax и только reRender, что нужно. Из журналов отладки facelets я вижу такие сообщения при любом вызове ajax:

2011-08-24 22:19:03,054 DEBUG [facelets.viewhandler] (http-0.0.0.0-8080-2) Took
24445ms to build view: /oconsole/appfile.xhtml
2011-08-24 22:19:09,377 DEBUG [facelets.viewhandler] (http-0.0.0.0-8080-2) Took
6323ms to render view: /oconsole/appfile.xhtml

Я не уверен, что что-то, что мы делаем, вызывает перестройку всего дерева компонентов, или личинки определяют эту потребность по какой-то причине (устаревший кеш?). Вот наш стек: JBoss 5.1 JSF 1.2 RichFaces. 3.3.3.Final Лицеи 1.1.15 Шов 2.1.2

Я попытался добавить некоторые параметры контекста, чтобы увидеть, помогут ли они, но они ничего не сделали: facelets.BUILD_BEFORE_RESTORE = false facelets.REFRESH_PERIOD = -1 или 5 (как в 5 минут)

Можно ли вообще сказать, правильно ли кэшируются наши представления? Мы не рассматриваем метод экономии состояния, поэтому я считаю, что он по умолчанию относится к стороне сервера. Все наши запросы происходят в длинных цепочках. Я не был уверен, что это играет роль, поскольку я думал, что взгляды кэшируются на уровне сеанса? Любая помощь будет принята с благодарностью, спасибо.

Обновление после дополнительной отладки:

AjaxViewHandler (который имеет переменную-член в FaceletsViewHandler) имеет параметр developmentMode = true. Я не уверен, что это приводит к тому, что facelets не кэширует какие-либо представления, поэтому любые изменения будут обновляться во время циклов разработки...?? Его было очень сложно найти любую информацию о кешетах/JSF-кешировании взглядов и о поведении и управлении этим. Кроме того, когда я добавляю конфигурационный параметр:

<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>

Это не получилось! В отладчике я все еще вижу истинный набор. Поскольку у нас есть много подзаголовков, я также пробовал com.sun.faces.numberOfLogicalViews и com.sun.faces.numberOfViewsInSession до 1000 от 15 (по умолчанию), и это не повлияло.

Я также попытался сэкономить при сохранении состояния на стороне клиента. Запуск идей.... надеюсь, что кто-то может помочь....

Кажется, Seam 2.1 автоматически инициализирует RichFaces, и я не уверен, что с этим что-то связано.....

Ответ 1

Как и при любой проблеме с производительностью, профилировщик очень поможет в определении узких мест. (Да, вы знаете, что это фаза restore_view, но не там, где на этапе restore_view).

Тем не менее, фаза восстановления восстанавливает весь вид, а не только части, которые будут обрабатываться или визуализироваться. Цитирование Документация Richlaces taglib:

: Id ['s] (в формате вызова UIComponent.findComponent()) компонентов, обработанных на этапах 2-5 в случае AjaxRequest, вызванных этим компонентом. Может быть единым идентификатором, разделенным запятыми списком идентификаторов или выражением EL с помощью массива или коллекции

RESTORE_VIEW - это этап 1. Также:

reRender: Id ['s] (в формате вызова UIComponent.findComponent()) компонентов, отображаемых в случае AjaxRequest, вызванных этим компонентом. Может быть единым идентификатором, разделенным запятыми списком идентификаторов или выражением EL с помощью массива или коллекции

Кроме того, я не уверен, что UIComponent.findComponent() реализован с использованием более подходящей структуры данных, чем дерево компонентов. (Поиск чего-то в дереве компонентов сводится к линейному поиску...).

Я наблюдал подобные эффекты с JSF 2.0 (Mojarra). Мой вывод состоял в том, что мнения не должны содержать более нескольких десятков UIComponents, независимо от того, будут ли они визуализированы. (По-другому, AJAX непригоден для навигации по страницам.) Мы делаем вывод, что мелкие представления не включают в себя только компоненты, которые в настоящее время видны в представлении, и переключают представления, если необходимо отобразить много новых компонентов. То есть вместо одного представления с 10 вкладками с 30 компонентами каждый, у нас будет 10 видов, каждый из которых содержит только содержимое одной вкладки. Недостатком такого подхода является то, что компоненты переключаются при переключении вкладок, в результате чего теряется какое-либо состояние, не содержащееся в резервной копии beans.

Я не утверждаю, что это хорошее решение. Увы, это был лучший, который я нашел, когда смотрел на это пару недель назад. Я был бы счастлив, если бы мне показали лучшую.

Edit Когда я говорю восстановление, я имею в виду ViewHandler.restoreView(), который вызвал и для первоначального запроса на получение, и для обратной передачи. Неверно сказать, что restoreView будет просто повторно использовать существующее представление как есть. Например, спецификация JSF 2.0 в разделе 7.6.2.7:]

Метод restoreView() должен выполнять следующие обязанности:

Все реализации должны:

  • Если идентификатор viewId не может быть идентифицирован, верните null.
  • Вызвать метод restoreView() связанного StateManager, передав экземпляр FacesContext для текущий запрос и рассчитанный viewId, и верните возвращенный UIViewRoot, который может быть null.

и в разделе 7.7.2:

Реализации JSF поддерживают два основных механизма сохранения состояния на основе значения javax.faces.STATE_SAVING_METHOD параметр инициализации (см. раздел 11.1.3 "Конфигурация приложения Параметры" ). Возможные значения этого параметра дают общую индикацию используемого подхода, позволяя Реализации JSF для новаций по техническим деталям:

  • клиент - [...]
  • server - причина сохранения сохраненного состояния на сервере между запросами. Реализации, которые хотят включить их сохраненное состояние для отказа от другого экземпляра контейнера должно помнить об этом при реализации своего сервера стратегия сохранения состояния. Реализация по умолчанию Сериализует представление как в режиме клиента, так и на сервере. в сервер, это сериализованное представление сохраняется в сеансе, а уникальный ключ для извлечения представления отправляется вниз клиент. Сохраняя сериализованное представление в сеансе, переход на другой ресурс может произойти с использованием обычных механизмов, предоставляемых контейнер.

Иными словами, поддержка AJAX, добавленная в JSF (как добавленная RichFaces 3 к JSF 1.2, так и встроенная в JSF 2.0), направлена ​​на снижение потребления полосы пропускания сети, а не на стороне сервера.

Ответ 2

Из моего анализа проблема вызвана реализацией facelets. Основываясь на отладчике следующие строки класса FaceletViewHandler, вызывает перестройку дерева для каждого запроса (даже AJAX) (buildBeforeRestore - false, поэтому вызывается метод buildView):

        // build view - but not if we're in "buildBeforeRestore"
        // land and we've already got a populated view. Note
        // that this optimizations breaks if there a "c:if" in
        // the page that toggles as a result of request processing -
        // should that be handled? Or
        // is this optimization simply so minor that it should just
        // be trimmed altogether?
        if (!this.buildBeforeRestore
                || viewToRender.getChildren().isEmpty()) {
            this.buildView(context, viewToRender);
        }

Итак, я решил решить проблему восстановления дерева по каждому запросу, чтобы углубиться в реализацию facelets и выполнить повторную реализацию... Я предпочел бы реструктурировать представление и свести к минимуму количество компонентов, поэтому время дерева сборки низкое.