web-dev-qa-db-fra.com

Amélioration de la performance JSF

Je travaille sur une application Web utilisant JSF 2.2 + Primefaces ... le projet se développe rapidement et le premier test de performance était très médiocre (en raison de ma connaissance insuffisante de JSF LifeCylce en combinaison avec des exigences non fonctionnelles - c'est-à-dire un site entièrement ajax), nous pourrions améliorer un peu, mais les résultats restent, ne sont pas comme prévu. (Nous avons un temps de 300 ~ 1500 ms en fonction de l’action, l’idée est d’avoir une performance d’environ 500 ms). Principalement la phase vue de la restauration et la réponse de rendu sont les consommateurs de temps (le temps passé n'a aucune valeur). Pour certaines actions, Invoke Aplication prend également du temps (en raison d'appels de base de données).

Après avoir lu de nombreux articles sur le Web, il y avait beaucoup de trucs géniaux à prendre en compte (beaucoup, bien sûr, de stackoverflow) tels que:

  • Améliorer les requêtes de base de données

nous en avons quelques-unes complexes qui sont traitées avec deux requêtes Hibernate Criterias, nous avons donc du travail ici. (peut-être utiliser des requêtes SQL pur, et sur des requêtes complexes, utiliser des sous-requêtes?)

  • Jamais définir la logique métier sur les accesseurs de Bean

Je l'ai!

  • Définir les portées appropriées pour les haricots et y stocker rien de plus que le matériel nécessaire

Nous avons un site ajax complet, donc View Scoped est presque identique à Session Scoped, nous utilisons les SessionBeans comme une sorte de "cache" pour stocker des données clés que nous ne voulons pas obtenir de la base de données à chaque fois + définir la logique d'entreprise ici.

  • Choisir la bonne méthode d’économie d’état de JSF - Client Vs Server

Pour cela, je dois faire des recherches supplémentaires, vérifier les possibilités avec leurs avantages et leurs inconvénients, puis tester les performances de chacun.

Jusqu'ici très clairement, maintenant quelques conseils supplémentaires sur lesquels j'ai des doutes.

  • Utilisez autant que possible Vanilla HTML et, de préférence, utilisez les balises h: plutôt que p:

Le HTML simple est clair et a du sens, maintenant entre h: et p: combien est-il digne? Par exemple.

<p:commandButton value="Value" 
             styleClass="class" 
             actionListener="#{myBean.doStuff()}"
             ajax="true" process="@form" update="@form" 
             onsuccess="jsFunction()" />

contre

<h:commandButton value="Value" 
             styleClass="class" 
             actionListener="#{myBean.doStuff()}" >
       <f:ajax execute="@form" render="@form" event="onclick" />
</h:commandButton>

ou

<ui:fragment... vs <p:fragment...

ou

<p:outputLabel value="#{myBean.value}" rendered="#{myBean.shouldRender}" />

contre

<ui:fragment rendered="#{myBean.shouldRender}">
    <label>#{myBean.value}</label>
</ui:fragment>

J'utilise un mélange de Primefaces avec des balises Jsf et du HTML pur ici et là depuis un moment (principalement PF en raison des fonctionnalités de leurs composants). Maintenant, le HTML simple sera toujours plus rapide, mais entre JSF et un autre Framework? Si j'y vais, cela changera beaucoup de temps et je ne voudrais pas que le résultat soit de savoir que cela ne fait pas une différence significative.

  • Tags Facelets personnalisés vs Composants Composites

Je pense que voici la clé. Vous avez encore des doutes sur leurs différences, sur la mise en œuvre des deux,CCsont assez simples et souples à utiliser, mais ont le désavantage d'être complètement inclus dans le ViewTree et de générer à nouveau JSF pour chaque requête (si je ne me trompe pas), tandis que balises personnalisées semble un peu plus complexe à utiliser (pas tant que ça) mais présente l’avantage que seul ce qui est rendu est inclus dans le ViewTree et rien de plus, RESTORE VIEW prend moins de temps. Nous avons plusieurs composants composites et aucune étiquette Facelets, nous aurons donc beaucoup de travail à faire. Je n'ai toujours pas trouvé de bon article expliquant les différences qui existent entre eux, quand il faut en utiliser un et quand l'autre (j'ai lu que pour les entrées, les messages utilisent TAGS et pour les choses plus complexes CC). Si l’idée est de préférer les tags vs CC, ce qui serait le cas sur lequel je n’aurais aucune option plutôt que d’utiliser CC? Est-il possible d’utiliser des balises personnalisées dans CC pour les rendre plus légères à JSF pour les traiter?

Je suis sur le point de commencer à modifier le projet de trou afin d'obtenir une meilleure performance qui me prendra plusieurs jours, l'idée est d'obtenir de meilleurs résultats cette fois-ci; donc chaque conseil, suggestion et suggestion est la bienvenue! Merci pour votre temps les gars!

12
Rodrigo Martinez

RenderResponse prend 98% de votre temps car ... c'est principalement ce que fait JSF. Je serais inquiet si JSF consacrait 50% du temps de traitement d'une demande à d'autres tâches que la réponse! Vous devez creuser plus profondément. Considérez cet exemple. 

Supposons que vous ayez une page qui affiche un tableau. Vous utilisez le composant p: dataTable PrimeFaces, comme ceci:

<h:html>
   <h:body>
       <p:dataTable value="#{myBean.data}">
       </p:dataTable>
   </h:body>
</h:html>

Et vous avez ce @ManagedBean:

@ManagedBean(name="myBean")
public class MyBean {

    public List<MyObject> getData() { 
        return // fetch list from database;
    }
}

À chaque appel de getData(), il y a un accès à la base de données, et cette heure s'ajoute à l'heure globale de la phase de rendu. De plus, le rendu de p: dataTable peut nécessiter de nombreux appels pour getData. 

Encore une fois, vous devez approfondir votre application et déterminer exactement où, pendant la phase de rendu, vous passez du temps. D'après mon expérience, les implémentations naïves de @ManagedBeans ont beaucoup de code d'interrogation de base de données dans les mêmes getters référencés dans xhtmls, comme dans mon exemple précédent. JSF (ou un composant tel que p: dataTable de PrimeFaces) peut invoquer ces accesseurs plusieurs fois lors du rendu d'un seul xhtml. Une stratégie courante consiste à extraire les données une seule fois, en utilisant l'événement preRenderView, comme ceci:

Dans votre xhtml:

<h:html>
   <f:metadata>
       <f:event type="preRenderView" listener="#{myBean.fetchDAta}"/>
   </f:metadata>
   <h:body>
       <p:dataTable value="#{myBean.data}">
       </p:dataTable>
   </h:body>
</h:html>

Dans votre haricot managé:

@ManagedBean(name="myBean")
public class MyBean {
    private List<MyObject> data;

    public void fetchData() {
         data = // fetch data from database.
    }

    public List<MyObject> getData() { 
        return data; 
    }
 }
1
Martín Straus

Il y a plusieurs choses que vous pouvez faire pour améliorer les performances de vos écrans.

  1. Filtre GZIP réduira considérablement le temps de chargement initial. Il compresse le contenu de la page lors du transfert vers le navigateur client. Reportez-vous à https://stackoverflow.com/a/35567295/5076414
  2. Vous pouvez également implémenter un cacheFilter pour amener les performances de Vos écrans au pair avec une interface utilisateur basée sur JavaScript. Cela mettra en cache le contenu statique de votre écran, tel que des icônes, des images, des feuilles de style, des javascripts, etc. Vous pouvez contrôler ce qu'il faut mettre en cache et ce qu'il faut exclure. Reportez-vous à https://stackoverflow.com/a/35567540/5076414
  3. Pour les composants de l'interface utilisateur côté client, vous pouvez utiliser Primefaces , qui est une interface utilisateur basée sur JQuery . 

Comment vérifier si mon écran utilise gzip et cache

Pour voir si votre contenu utilise déjà gzip et le cache, dans votre Google Chrome Navigateur -> cliquez avec le bouton droit sur votre écran -> inspecter -> cliquez sur l'onglet réseau -> actualisez votre écran. Cliquez sur. sur les images, les icônes, les feuilles de style et voyez si vous voyez ce qui suit dans response header

Cache-Control:max-age=2592000 si le statut de l'élément est 304 (provenant du cache)

Content-Encoding:gzip si le statut de l'élément est 200

1
Sacky San

J'ai rencontré le même problème il y a six mois. La plupart du temps passé dans RestoreView et RenderResponse phase. Si votre problème est identique, alors Vous ne pouvez pas faire grand chose:

  1. Utilisez partialSubmit="true" autant que possible
  2. Réduire le nombre de composants
  3. Ne pas utiliser beaucoup de composants composites

Dans mon cas particulier, j'avais beaucoup de HTML dynamique sans contrôles d'entrée et J'ai utilisé un composant composite comme modèle pour le rendu conditionnel. Pour augmenter les performances, j’ai utilisé freemarker pour générer du HTML dynamique.

PS Mon avis est de ne pas utiliser JSF si nous avons des pages complexes comportant de nombreux composants. Je pense que Tapestry est plus optimisé pour cela. Comme JSF, il ne recrée pas de composants à chaque requête.

1
Sergiy Uvarov