问题
I was told to optimize a web application. To do so I use JProfiler.
I noticed a large part of the response time is spent in the presentation layer. Especially, when the code builds the HTML code.
Drilling down this bottle neck, I saw that the code deals a lot with OGNL classes/methods (nearly 50% of the calls).
I tuned the JSP code (see below for details) by removing some unnecessary OGNL statements. I managed to gain 200ms. However the code still spend more than 2000ms on average in this bottle neck. The overall response time is around 3000ms.
The OGNL documentation says this:
As of OGNL 2.5.0 the OgnlContext object can automatically tracks evaluations of expressions. (...) you can access the last evaluation through the lastEvaluation property of OgnlContext.
Since I use Struts 2.3.15.1 (OGNL v3.0.6) how can I access this property or call the getLastEvaluation
of OgnlContext
either from JSP file or Action class ?
JSP file
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix ="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<title><s:text name="domain.domain0.title"/></title>
<script type="text/javascript" src="<s:url value='/js/domain/domain0.js'/>"></script>
<script type="text/javascript" src="<s:url value='/js/core/html.js'/>"></script>
</head>
<body>
<div style="width:100%;color:green;font-weight: bold;text-align:center">
<s:text name="domain.domain0.information"/>
</div>
<div class="content selectFen">
<s:set var="noAnchor">false</s:set>
<s:iterator value="artefactList" status="numRow">
<s:if test="court == nomenclatureCritere && #noAnchor!=true">
<s:set var="noAnchor">true</s:set>
<a id="NomencAnchor" href="#NomencAnchor" style="visibility:hidden;"></a>
</s:if>
<s:set var="isOpen" value="nomenclatureCritere.startsWith(court) || ligProd != '80'"/>
<div class="parcoursNomenc">
<table onmouseover='this.style.backgroundColor="gainsboro"' onmouseout='this.style.backgroundColor=""' style="width: 100%;font-weight:bolder">
<tbody>
<tr>
<s:url var="childNomenUrl" action="ajaxPopupNomenChild" escapeAmp="false">
<s:param name="dateCritere" value="dateCritere"/>
<s:param name="sidNomenclaturePere" value="sidArtNomenc"/>
</s:url>
<s:if test="#isOpen">
<s:if test="#numRow.last">
<td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open_last"> </td>
</s:if>
<s:else>
<td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open"> </td>
</s:else>
</s:if>
<s:else>
<s:if test="#numRow.last">
<td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed_last"> </td>
</s:if>
<s:else>
<td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed"> </td>
</s:else>
</s:else>
<td style="vertical-align: top; width: 8.5em; padding-top: 5px;">
<s:text name="domain.domain0.label"/> <s:property value="court"/>
</td>
<td class="description">
<s:property value="description"/>
</td>
</tr>
</tbody>
</table>
<div id="divParcours<s:property value="sidArtNomenc"/>" class="<s:if test="numRow.last">subtree_last</s:if><s:else>subtree</s:else>" >
<s:if test="#isOpen">
<s:action name="popupNomenExist" executeResult="true">
<s:param name="dateCritere" value="dateCritere"/>
<s:param name="nomenclatureCritere" value="nomenclatureCritere"/>
</s:action>
<s:action name="ajaxPopupNomenChild" executeResult="true">
<s:param name="dateCritere" value="dateCritere"/>
<s:param name="sidNomenclaturePere" value="sidArtNomenc"/>
</s:action>
</s:if>
</div>
</div>
</s:iterator>
</div>
</body>
</html>
回答1:
You can access OgnlContext like
OgnlContext context = (OgnlContext) ActionContext.getContext().getValueStack().getContext();
context.setTraceEvaluations(true);
Evaluation evaluation = context.getLastEvaluation();
How to trace evaluations is described in the document you linked in the section for Trace Evaluations
You can also set system property ognl.traceEvaluations
before the context is instantiated to turn on this feature.
回答2:
Looking at your JSP code, it's evident that the culprits are the <s:action>
tags:
You call two actions on each iteration... that basing on the number of rows you are iterating, may become a serious problem.
I would try refactoring that section; a big part of the bottleneck is in the mechanism to interpret the tag, call the action, pass through the Interceptor Stack, and so on.
If you can generate the same output minimizing the calls to actions, the bottleneck would decrease significantly.
P.S: a very minimal optimization is to change the order of the boolean and string comparison in your s:if, to exploit the short circuit (boolean comparison is faster):
<s:if test="#noAnchor!=true && court == nomenclatureCritere">
EDIT
It works better without
s:action
however the page need them and I don't know how to replace them
To be more clear, an Action should
- perform one (or few) logical action;
- never be used as an helper class.
When you call popupNomenExist
, your only requirements is to call the server, do something, and receive the result to inject it in the JSP.
There are several ways to receive that result, and calling an Action is probably the worst (in terms of performances, because of the reasons listed above).
You can take the code from the execute()
method of your popupNomenExist
Action, and :
- place it in a method of YOUR current action, like described in RomanC linked answer;
- place it in a static method of an helper class;
- precalculate it in your current action, and expose the results as List of Strings;
- and so on...
In addition, we can't argue what is exactly being performed inside your popupNomenExist's execute()
method, but I guess there are chance that it could be refactored to prevent executing some part of logic that is common to each iteration, grouping them and executing before the iteration as a sort of cache.
来源:https://stackoverflow.com/questions/24078472/how-to-access-ognl-tracing-evaluations-in-struts-2