performance pb with big datatable
gonzalad Nov 19, 2009 6:30 AMHello,
I have perfomance problems when showing a 500 rows table in ajax mode.
The performance problem appears on the browser (I think it's due when RF tries to include the ajax response in the DOM or when it parses the XML response).
Rendering all the 500 lines (339 ko) takes :
* 2 s on the server.
* 4s on FF and 5.5 s on IE6
Appserver and browser are running on the same host.
You can see a screen capture of my page : http://www.flickr.com/photos/44793303@N04/4116400761/sizes/o/.
When I ask for 20 rows, table is displayed quite instantaneous (200 ms).
I know 339 ko is a lot of data.
Should I exclude ajax usage (replace a4j:commandButton with h:commandButton) in this particular case ?
If yes, and in order to know this in the future, what's the best practice for a reasonable maximum ajax payload (50 ko, 100ko, 1Mo ?).
Thanks very very much for your input !
More details
Using Page Speed Activity Tab (Google Page Speed plugin for FF), javascript executions takes between 1 and 2 seconds.
See http://www.flickr.com/photos/44793303@N04/4117274650/sizes/o/.
For more info about Page Speed Activity usage, see http://code.google.com/intl/fr/speed/page-speed/docs/using.html#activities
When using a4j:log, I see (I'm posting only the interesting part here) :
debug[12:10:19,407]: Have Event [object Object] with properties: target: [object HTMLInputElement], srcElement: undefined, type: click debug[12:10:19,412]: QueryString: AJAXREQUEST=sR&sF=sF&sF%3Astatut=Tous&sF%3Anom=&sF%3Abadge=&sF%3Aj_id73=500&javax.faces.ViewState=j_id7&sF%3AdoFiltrer=sF%3AdoFiltrer& debug[12:10:21,503]: Response with content-type: text/xml;charset=UTF-8 debug[12:10:21,505]: Full response content: ..blabla... debug[12:10:21,529]: call getElementById for id= rF debug[12:10:22,503]: Replace content of node by replaceChild() debug[12:10:22,820]: search for elements by name 'script' in element form debug[12:10:22,843]: No focus information in response
And an extract of my page code :
<a4j:region id="sR"> <h:form id="sF"> <a4j:commandButton id="doFiltrer" action="#{rechercherBeneficiaireAction.search}" reRender="rF,msg" limitToList="true" status="status2" value="#{messages['direction.beneficiaire.button.filtrer']}"/> </h:form> </a4j:region> <h:form id="rF"> <rich:panel header="#{messages['titre.page.direction.liste.recherche.beneficiaire.titre']}" rendered="#{rechercherBeneficiaireAction.resultListNotEmpty}"> <a4j:outputPanel id="bDt" rendered="#{rechercherBeneficiaireAction.resultListNotEmpty}"> <table cellspacing="0" cellpadding="0" border="0" width="100%" class="rich-table"> <colgroup span="9" /> <thead> blabla (just some th info) </thead> <a4j:repeat var="utilisateur" value="#{rechercherBeneficiaireAction.resultList}" rowKeyVar="i"> <tr class="#{i%2==0?'rich-table-cell-pair':'rich-table-cell-impair'}"> <td class="rich-table-cell rich-table-cell-checkbox"> <input type="checkbox" name="sel"/> </td> <td class="rich-table-cell"> <img src="#{rechercherBeneficiaireAction.getStatutImgUrl(utilisateur)}"/> </td> <td class="rich-table-cell"> <h:outputText value="#{utilisateur.personnePhysique.membre.departementClient.libelle}"/> </td> <td class="rich-table-cell"> <a href="#{detailProfilUrl}&id=#{utilisateur.personnePhysique.membre.id}">#{utilisateur.login}</a> </td> <td class="rich-table-cell"> <h:outputText value="#{el:abbreviate(utilisateur.personnePhysique.nom,19)} #{el:abbreviate(utilisateur.personnePhysique.prenom,19)}" title="${utilisateur.personnePhysique.nomPrenom}"/> </td> <td class="rich-table-cell"> <h:outputText value="#{utilisateur.personnePhysique.membre.getBeneficiaireParProduitSouscrit(produitSouscritAction.instance).datePremiereCommande}"> <s:convertDateTime pattern="#{messages['datePattern.libelle']}"/> </h:outputText> </td> <td class="rich-table-cell"> <h:outputText value="#{utilisateur.personnePhysique.membre.getBeneficiaireParProduitSouscrit(produitSouscritAction.instance).recapCommandeBeneficiaire.nbTitres}" /> </td> <td class="rich-table-cell"> <h:outputText value="#{utilisateur.personnePhysique.membre.getBeneficiaireParProduitSouscrit(produitSouscritAction.instance).parametrageDotation.maxDemande}"/> </td> <td class="rich-table-cell"> <s:fragment rendered="#{utilisateur.codeAction ne 'AT'}"> <s:fragment rendered="#{!utilisateur.actif}"><a title="#{messages['bouton.activer']}" onclick="act(#{utilisateur.id})" href="#">#{messages['bouton.action.activer']}</a></s:fragment> <s:fragment rendered="#{utilisateur.actif}"><a title="#{messages['bouton.desactiver']}" onclick="des(#{utilisateur.id})" href="#">#{messages['bouton.action.desactiver']}</a></s:fragment> </s:fragment> <s:fragment rendered="#{utilisateur.codeAction eq 'AT'}"><a title="#{messages['bouton.valider']}" onclick="val(#{utilisateur.id})" href="#">#{messages['bouton.action.valider']}</a> <a title="#{messages['bouton.refuser']}" onclick="ref(#{utilisateur.id})" href="#">#{messages['bouton.action.refuser']}</a></s:fragment> </td> </tr> </a4j:repeat> </table> </a4j:outputPanel> </rich:panel> </h:form>