问题是 - 你如何衡量页面加载的时间,你使用的技术,你可以提供哪些推荐,以及你有什么积极和消极的经验.
麻烦的是,即使是jsf中的轻页也可能需要10秒才能加载.这些页面不需要任何评估,渲染资源等.显而易见的答案 - 它在渲染队列中......好吧,但可能是其他的东西?
似乎需要从请求开始测量时间,包括渲染,评估,数据传输时间,客户端渲染时间等.
您是否有任何良好的工作方式,工具链,工具,可以在JSF中查看页面的完整生命周期时间?
使用Glassfish-3,JSF-2.机器有64个CPU.
这是我刚刚制作和测试的一个简单的自定义解决方案.它提供了一些执行和渲染时间的统计信息.当然,所有信息仅来自服务器端处理.
结果示例:
Date ID request URL Phase Execution time
2013-05-16 21:10:29.781 34 http://localhost:8080/web/page.jspx RESTORE_VIEW 1 15
2013-05-16 21:10:29.796 34 http://localhost:8080/web/page.jspx RENDER_RESPONSE 6 4438
2013-05-16 21:10:39.437 35 http://localhost:8080/web/page.jspx RESTORE_VIEW 1 16
2013-05-16 21:10:39.453 35 http://localhost:8080/web/page.jspx RENDER_RESPONSE 6 3937
Run Code Online (Sandbox Code Playgroud)
实施非常紧张.首先,你要在里面配置一个PhaseListenerfaces-config.xml
<lifecycle>
<phase-listener>com.spectotechnologies.jsf.phaselisteners.PhaseProcessesAnalyserListener</phase-listener>
</lifecycle>
Run Code Online (Sandbox Code Playgroud)
这是帮助程序类,它保存有关每个处理的信息:
package com.spectotechnologies.website.common.helper;
import java.util.Date;
import javax.faces.event.PhaseId;
/**
*
* @author Alexandre Lavoie
*/
public class PhaseProcess
{
private int m_nIDRequest;
private String m_sURL;
private Date m_oStart;
private Date m_oEnd;
private PhaseId m_oPhase;
public void setIdRequest(int p_nIDRequest)
{
m_nIDRequest = p_nIDRequest;
}
public int getIdRequest()
{
return m_nIDRequest;
}
public void setUrl(String p_sURL)
{
m_sURL = p_sURL;
}
public String getUrl()
{
return m_sURL;
}
public void setStart(Date p_oStart)
{
m_oStart = p_oStart;
}
public Date getStart()
{
return m_oStart;
}
public void setEnd(Date p_oEnd)
{
m_oEnd = p_oEnd;
}
public Date getEnd()
{
return m_oEnd;
}
public void setPhase(PhaseId p_oPhase)
{
m_oPhase = p_oPhase;
}
public PhaseId getPhase()
{
return m_oPhase;
}
public long getExecutionTime()
{
long lExecutionTime = -1;
if(getEnd() != null)
{
lExecutionTime = getEnd().getTime() - getStart().getTime();
}
return lExecutionTime;
}
}
Run Code Online (Sandbox Code Playgroud)
这是具有业务逻辑的类,请注意,目前统计数据只会增长并且永远不会被删除,因此可能是一个很好的更新,例如仅保留最后一小时:
package com.spectotechnologies.website.common.helper;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
/**
*
* @author Alexandre Lavoie
*/
public class PhaseProcesses
{
private List<PhaseProcess> m_lItems = new ArrayList();
private int m_nNextIDRequest = 0;
public static PhaseProcesses getInstance()
{
FacesContext oFaces = FacesContext.getCurrentInstance();
PhaseProcesses oPhaseProcesses = (PhaseProcesses)oFaces.getExternalContext().getSessionMap().get("sessionPhaseProcesses");
if(oPhaseProcesses == null)
{
oPhaseProcesses = new PhaseProcesses();
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("sessionPhaseProcesses",oPhaseProcesses);
}
return oPhaseProcesses;
}
public void set(int p_nIDRequest, String p_sURL, PhaseId p_oPhase, int p_nType)
{
PhaseProcess oPhaseProcess;
// Phase start
switch(p_nType)
{
case 0:
// start
oPhaseProcess = new PhaseProcess();
oPhaseProcess.setIdRequest(p_nIDRequest);
oPhaseProcess.setUrl(p_sURL);
oPhaseProcess.setPhase(p_oPhase);
oPhaseProcess.setStart(new Date());
if(m_lItems.size() > 250)
{
m_lItems.remove(0);
}
m_lItems.add(oPhaseProcess);
break;
case 1:
// end
for(int nPhase = m_lItems.size() - 1;nPhase >= 0;nPhase--)
{
if(m_lItems.get(nPhase).getIdRequest() == p_nIDRequest && m_lItems.get(nPhase).getPhase() == p_oPhase)
{
m_lItems.get(nPhase).setEnd(new Date());
break;
}
}
break;
}
}
public List<PhaseProcess> getList()
{
return m_lItems;
}
public Integer getNextIDRequest()
{
return m_nNextIDRequest++;
}
}
Run Code Online (Sandbox Code Playgroud)
这是着名的PhaseListener,其中跟踪信息:
package com.spectotechnologies.jsf.phaselisteners;
import com.spectotechnologies.website.common.helper.PhaseProcesses;
import java.net.URLEncoder;
import java.util.Enumeration;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Alexandre Lavoie
*/
public class PhaseProcessesAnalyserListener implements PhaseListener
{
@Override
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
@Override
public void beforePhase(PhaseEvent p_oEvent)
{
PhaseProcesses.getInstance().set(getIDRequest(),getURL(),p_oEvent.getPhaseId(),0);
}
@Override
public void afterPhase(PhaseEvent p_oEvent)
{
PhaseProcesses.getInstance().set(getIDRequest(),getURL(),p_oEvent.getPhaseId(),1);
}
private Integer getIDRequest()
{
Integer iIDRequest = (Integer)FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("idrequest");
if(iIDRequest == null)
{
iIDRequest = PhaseProcesses.getInstance().getNextIDRequest();
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("idrequest",iIDRequest);
}
return iIDRequest;
}
private String getURL()
{
Enumeration<String> lParameters;
String sParameter;
StringBuilder sbURL = new StringBuilder();
Object oRequest = FacesContext.getCurrentInstance().getExternalContext().getRequest();
try
{
if(oRequest instanceof HttpServletRequest)
{
sbURL.append(((HttpServletRequest)oRequest).getRequestURL().toString());
lParameters = ((HttpServletRequest)oRequest).getParameterNames();
if(lParameters.hasMoreElements())
{
if(!sbURL.toString().contains("?"))
{
sbURL.append("?");
}
else
{
sbURL.append("&");
}
}
while(lParameters.hasMoreElements())
{
sParameter = lParameters.nextElement();
sbURL.append(sParameter);
sbURL.append("=");
sbURL.append(URLEncoder.encode(((HttpServletRequest)oRequest).getParameter(sParameter),"UTF-8"));
if(lParameters.hasMoreElements())
{
sbURL.append("&");
}
}
}
}
catch(Exception e)
{
// Do nothing
}
return sbURL.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,这是我创建的用于显示统计信息的简单页面.一个很好的改进可能是在页面处理上添加平均值,也就是每个idrequest处理时间.
Bean代码:
package com.spectotechnologies.website.common.beans;
import com.spectotechnologies.website.common.helper.PhaseProcess;
import com.spectotechnologies.website.common.helper.PhaseProcesses;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
/**
*
* @author Alexandre Lavoie
*/
@ManagedBean
@RequestScoped
public class PagesStatisticsActions
{
public List<PhaseProcess> getList()
{
return PhaseProcesses.getInstance().getList();
}
}
Run Code Online (Sandbox Code Playgroud)
查看代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="application/xhtml+xml">
<h:head>
<meta http-equiv="Content-Type" content="application/xhtml+xml;charset=UTF-8" />
</h:head>
<h:body>
<h:dataTable value="#{pagesStatisticsActions.list}" var="item">
<h:column>
<f:facet name="header">
Date
</f:facet>
<h:outputText value="#{item.start}">
<f:convertDateTime timeZone="America/Montreal" pattern="yyyy-MM-dd HH:mm:ss.SSS" />
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
ID request
</f:facet>
#{item.idRequest}
</h:column>
<h:column>
<f:facet name="header">
URL
</f:facet>
#{item.url}
</h:column>
<h:column>
<f:facet name="header">
Phase
</f:facet>
#{item.phase}
</h:column>
<h:column>
<f:facet name="header">
Execution time (ms)
</f:facet>
#{item.executionTime}
</h:column>
</h:dataTable>
</h:body>
</f:view>
</html>
Run Code Online (Sandbox Code Playgroud)
更新1:
| 归档时间: |
|
| 查看次数: |
2427 次 |
| 最近记录: |