JSF性能改进

时间:2015-01-22 18:32:48

标签: performance jsf jsf-2 primefaces

我正在使用JSF 2.2 + Primefaces开发WebApp ...项目正在快速增长,并且第一次性能测试非常差(由于我对JSF LifeCylce在非功能性需求方面的了解不足 - 即完全ajax网站),然后我们可以改善一点,但结果仍然,不如预期。 (根据动作,我们有300~1500毫秒的时间,想法是性能大约500毫秒,给予或采取)。主要是还原视图阶段和渲染响应是消费者(在其他情况下花费的时间毫无价值)的时间。对于某些操作,调用应用程序也需要时间(由于DB调用)。

在网上阅读了很多文章之后,有很多很棒的提示需要考虑(很多当然来自stackoverflow),例如:

  
      
  • 改善数据库查询
  •   

我们有一些复杂的,用两个Hibernate Criterias查询完成,所以我们在这里工作。 (也许使用纯SQL查询,复杂的查询使用子查询?)

  
      
  • 永远不要在Bean的getters上定义业务逻辑
  •   

知道了!

  
      
  • 将适当的范围设置为bean并在其上存储只不过是必要的东西
  •   

我们有一个完整的ajax站点,因此View Scoped几乎就像Session Scoped一样,我们使用SessionBeans作为一种' Cache'存储我们不希望每次都从DB获取的关键数据+在此处定义业务逻辑。

  
      
  • 选择正确的JSF状态保存方法 - 客户端服务器
  •   

为此我需要进行更多的研究,检查各种可能性的优缺点,然后测试每一种的可能性。

到目前为止非常清楚,现在有些额外的提示,我有些疑惑。

  
      
  • 尽可能使用vanilla HTML,最好使用h:tags而不是p:tags
  •   

简单的HTML是清楚的,有意义的,现在在h:和p之间:它值多少钱?例如。

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

VS

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

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

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

VS

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

我一直在混合使用Primefaces和Jsf标签以及一些简单的HTML现在。(主要是由于它们的组件的功能)我现在认为纯HTML总是如此更快,但在JSF和另一个框架之间?如果我这样做,改变它将花费大量时间,我不会喜欢知道它根本没有产生相关差异的结果。

  
      
  • 自定义Facelets标记与复合组件
  •   

我认为这是关键。对于它们的差异仍有一些疑问,对于它们的实现, CC 使用起来非常简单和灵活,但缺点是它们完全包含在ViewTree和JSF为每个请求重新生成(如果我没有弄错的话,虽然自定义标签使用起来似乎有点复杂(不是那么多),但其优点是只有ViewTree中包含的内容才会被包含在内更多,使RESTORE VIEW更省时。我们有几个复合组件,没有Facelets标签,所以这里要做很多工作。我仍然没有找到一篇很好的文章来解释它们之间的差异,当一个应该被使用时,另一个(已经读过输入,消息使用TAGS和更复杂的东西CC)。如果想要更喜欢标签与CC,那么我将没有选择而不是使用CC?在CC中使用自定义标签是否可以使它们更轻松地用于处理它们?

我即将进入修改洞穴项目的旅程,以获得更好的表现,这将花费我几天的时间,想法是这次获得更好的结果;所以每个提示,建议和建议都非常欢迎!谢谢你的时间!

6 个答案:

答案 0 :(得分:1)

半年前我遇到了同样的问题。大多数时间花在 RestoreView RenderResponse 阶段。如果你的问题是一样的话 你无能为力:

  1. 尽可能使用partialSubmit="true"
  2. 减少组件数量
  3. 不要大量使用复合材料组件
  4. 在我的特定情况下,我有很多没有输入控件的动态HTML 我使用复合组件作为条件渲染的模板。 为了提高性能,我使用freemarker生成动态html。

    PS。如果我们有包含许多组件的复杂页面,我的意见是不使用JSF。我认为Tapestry对此更为优化。它不像JSF那样在每个请求上重新创建组件。

答案 1 :(得分:1)

您可以采取一些措施来提高屏幕效果

  1. GZIP过滤器会显着缩短初始加载时间。它在转移到客户端浏览器时压缩页面内容。请参阅https://stackoverflow.com/a/35567295/5076414
  2. 您还可以实施 cacheFilter 来提高性能 您的屏幕与基于JavaScript的UI相同。这将缓存屏幕的静态内容,如图标,图像,样式表,javascripts等。您可以控制要缓存的内容和要排除的内容。请参阅https://stackoverflow.com/a/35567540/5076414
  3. 对于客户端UI组件,您可以使用 Primefaces ,即JQuery 基于UI。
  4. 如何验证我的屏幕是否正在使用gzip和缓存

    要查看您的内容是否已经使用gzip和缓存,请执行 Google Chrome 浏览器 - &gt;右键点击你的屏幕 - &gt;检查 - &gt;点击网络标签 - &gt;刷新你的屏幕。 点击图片,图标,样式表,看看您是否在响应标题

    中看到了以下内容

    Cache-Control:max-age=2592000如果元素的状态是304(来自缓存)

    Content-Encoding:gzip如果元素的状态为200

答案 2 :(得分:1)

RenderResponse需要98%的时间,因为......这就是JSF主要做的事情。如果JSF将请求的处理时间的50%用于执行除了呈现响应之外的其他事情,我会担心!你需要深入挖掘。考虑这个例子。

假设您有一个显示表格的页面。您可以使用p:dataTable PrimeFaces组件,如下所示:

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

你有@ManagedBean

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

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

每次调用getData()时,都会有数据库访问权限,并且该时间会增加呈现阶段的全局时间。而且,p:dataTable的渲染可能需要多次调用getData。

同样,您需要深入了解应用程序,并在呈现阶段确切地检测到花费的时间。根据我的经验,@ManagedBean的朴素实现在xhtml中引用的相同getter中有很多数据库查询代码,就像我之前的例子一样。 JSF(或像PrimeFaces的p:dataTable这样的组件)可能会在渲染单个xhtml时多次调用这些getter。常见的策略是使用preRenderView事件仅获取一次数据,如下所示:

在你的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>

在托管bean中:

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

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

    public List<MyObject> getData() { 
        return data; 
    }
 }

答案 3 :(得分:-1)

我不确定“p”和“h”之间是否存在很大差异,因为它们都会在结尾处呈现为html。我看到你使用了很多进程属性。您可以通过仅发送表单的某些部分来定位此属性中的特定ID以提高性能。提高性能的另一个想法是使用primefaces“cache”。 http://www.primefaces.org/showcase/ui/misc/cache.xhtml表示您希望非常频繁地呈现的非动态内容(请查看文档)。我猜“缓存”会尝试从缓存中获取树视图而不是重建它。

答案 4 :(得分:-2)

我读了一篇关于JSF加速性能的有趣文章。在恢复视图阶段,JSF重构组件树,包括将数据绑定到数据表,从而导致从数据库中不必要地提取数据。本文着眼于避免额外工作来获取数据的一种方法。

我在这里报告可能的解决方案,以及完整的文章供参考。

该问题的解决方案是首次跳过获取数据。它不是必需的,甚至没有使用它甚至不是正确的数据(不用担心,我稍后会解释)。在FacesContext对象中有一个名为getRenderResponse()的方法,如果已经调用了渲染响应方法并且我们处于渲染阶段,则该方法返回true。在我们渲染页面之前,我们并不真正需要我们的数据,因此只有在此方法返回true时才加载它。

例如:

//generates the list of data, think of this as an expensive DB operation
private List<Integer> generateData()  {
if (!FacesContext.getCurrentInstance().getRenderResponse()) {
    return null;
}
System.out.println("Generating Data starting from "+pageNumber);
...
...
...
}

因此,即使在回发中我们也只能获得每页请求一次数据获取,因为我们不需要在渲染响应中真正需要加载数据,如果您查看时间,我们的页面加载速度是原来的两倍我们只获取了一半的数据。

所以你去,你可以通过只在你真正需要的时候加载数据来提高你的JSF页面的速度,我想这是一种懒惰的加载数据。

Double the speed of (some of) your JSF pages (and dodge bugs too)

我希望它对其他人有用。

答案 5 :(得分:-2)

如果你想用其他框架制作jsf应用程序你的应用程序对用户来说性能很差。因为Jsf应用程序变成了等待渲染阶段太多的6阶段。因此,您可以将微服务用于后端,并使用javascript作为前端。结果您可以在性能和体系结构方面做出如此好的应用。你可以看看java ee应用程序的spring boot微服务