JSF view получает перестроение при каждом запросе ajax - PullRequest
11 голосов
/ 25 августа 2011

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

Я не уверен, что что-то, что мы делаем, вызывает перестройку всего дерева компонентов, или Facelets определяет эту потребностьпо какой-то причине (устаревший кеш?).Вот наш стек: JBoss 5.1 JSF 1.2 RichFaces.3.3.3.Final Facelets 1.1.15 Seam 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, и я не уверен, что это как-то связано с этим .....

Ответы [ 2 ]

5 голосов
/ 25 августа 2011

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

При этом фаза восстановления действительно восстанавливает весь вид, а не только части, которые будут обработаны или обработаны.Цитирование документации RichFaces taglib :

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

RESTORE_VIEW - фаза 1. Также:

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

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

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

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

Редактировать Когда я говорю восстановление, я имею в виду 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 внедрять инновации в технических деталях:

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

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

1 голос
/ 26 августа 2011

Из моего анализа проблема вызвана реализацией фейлетов.На основе отладчика следующие строки класса FaceletViewHandler вызывают перестройку дерева для каждого (даже AJAX) запроса (buildBeforeRestore ложно, поэтому вызывается метод 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's 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 и выполнить повторную реализацию ... Я бы предпочел реструктурировать представление и минимизировать количество компонентов, поэтому время сборки дерева невелико.

...