Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance in JavaEE 6 Applications (Glassfish v3) - Logging, DI, Database-Operations, EJBs, Managed Beans

The important technologies i use are: Glassfish v3, JSF 2.0, JPA 2.0, EclipseLink 2.0.2, log4j 1.2.16, commons-logging 1.1.1.

My problem is that some parts of the application are pretty slow. I analysed this with the netbeans 6.8 Profiling capabilities.

I. Logging - i use log4j and apache commons logging to generate logs in a logging file and in the console. The logs also appear in glassfish's server log. I use loggers as follows:

    private static Log logger = LogFactory.getLog(X.class);
    ...
    if (logger.isDebugEnabled()) {
        ...
        logger.debug("Log...");
    }

The Problem is that sometimes such short statements take much time (about 800 ms). When i switch to java.util.logging its not that bad but also very slow (200 ms band). What's the problem? I need some logging... UPDATE - The problem with the slow logging was solved after switching from Netbeans 6.8 to Netbeans 6.9.1. - Netbeans 6.8 possibly is very slow when logs are printed to its console?! So it had nothing to do with Log4J or commons logging..

II. DB Operation: The first time i call the find Method of the following EJB it takes 2,4 s! Additional calls last only some ms. So why takes the first operation that long? Is this (only because of) the connection establishment or has it something to do with the Dependency Injections of the XFacade and when are these Injections performed?:

@Stateless
@PermitAll
public class XFacade {
    @PersistenceContext(unitName = "de.x.persistenceUnit")
    private EntityManager em;
    // Other DI's
    ...

    public List<News> find(int maxResults) {
      return em.createQuery(
      "SELECT n FROM News n ORDER BY n.published DESC").setMaxResults(maxResults).getResultList() 
    }
}

III. Dependency Injection, JNDI Lookup: Is there a difference beetween DI like (@EJB ...) and InitialContext lookups concerncing performance? Is there a difference (performance view) between injecting local, remote and no-interface EJB's?

IV. Managed Beans - I use many Session Scoped Beans, because the ViewScope seems to be very buggy and Request Scoped is not always practically. Is there an alternative? - because these Beans are not slow but the server side memory is stressed during a whole session. And when a user logs out it takes some time!

V. EJBs - I don't use MDB only Session Beans and Singleton Beans. Often they inject other Beans with the @EJB Annotation. One Singleton Bean use @Schedule Annotations to start repeatedly operations. A interesting thing i found is that since EJB 3.1 you can use the @Asynchronous Annotation to make Session Bean Method's asynchronous. What should i generally consider when implementing EJBs concerning performance?

Maybe someone could give me some general and/or specific tips to increase the performance of javaee applications, especially concerning the above issues. Thanks!

like image 484
Michael W. Avatar asked Aug 20 '10 06:08

Michael W.


2 Answers

To start with, you should bench your application in a real environment using load testing tools, you can't really make valid conclusions from the behavior you observe in your IDE. On top of that don't forget that profiling actually alters performances.

I. Logging (...) The problem with the slow logging was solved after switching from Netbeans 6.8 to Netbeans 6.9.1

That's the first proof you can't use trust the behavior inside your IDE.

II. DB Operation: The first time i call the find Method of the following EJB it takes 2,4 s! Additional calls last only some ms. So why takes the first operation that long?

Maybe because some GlassFish services are (lazy) loaded, maybe because the stateless session beans (SLSB) have to be instantiated, maybe because the EntityManagerFactory has to be created. What did the profiling say? Why do you see when activating app server logging? And what's the problem since subsequent calls are ok?

III. Dependency Injection, JNDI Lookup: Is there a difference beetween DI like (@EJB ...) and InitialContext lookups concerncing performance?

JNDI lookups are expensive and it was a de facto practice to use some caching in the good old service locator. I thus don't expect the performances to be worst when using DI (I actually expect the container to be good at it). And honestly, it has never been a concern for me.

When you work on performance optimization, the typical workflow is 1) detect a slow operation 2) find the bottleneck 2) work on it 3) if the operation is still not fast enough, go back to 2). To my experience, the bottleneck is 90% of the time in the DAL. If your bottleneck is DI, you have no performance problem IMO. In other words, I think you're worrying too much and you're very close to "premature optimization".

IV. Managed Beans - I use many Session Scoped Beans, because the ViewScope seems to be very buggy and Request Scoped is not always practically. Is there an alternative? - because these Beans are not slow but the server side memory is stressed during a whole session. And when a user logs out it takes some time!

I don't see any question :) So I don't have anything to say. Update (answering a comment): Using a conversation scope might be indeed less expensive. But as always, measure.

V. EJBs - I don't use MDB only Session Beans and Singleton Beans. Often they inject other Beans with the @EJB Annotation. One Singleton Bean use @Schedule Annotations to start repeatedly operations. A interesting thing i found is that since EJB 3.1 you can use the @Asynchronous Annotation to make Session Bean Method's asynchronous. What should i generally consider when implementing EJBs concerning performance?

SLSBs (and MDBs) perform very well in general. But here are some points to keep in mind when using SLSBs:

  • Prefer Local over Remote interfaces if your clients and EJBs are collocated to avoid the overhead of remote calls.
  • Use Stateful Session Beans (SFSB) only if necessary (they are harder to use, managing state has a performance cost and they don't scale very well by nature).
  • Avoid chaining EJBs too much (especially if they are remote), prefer coarse grained methods over multiple fine-grained methods invocation.
  • Tune the SLSB pool (so that you have just enough beans to serve your concurrent clients, but not too much to avoid wasting resources).
  • Use transactions appropriately (e.g. use NOT_SUPPORTED for read only methods).

I would also suggest to not use something unless you really need the feature and there is a real problem to solve (e.g. @Asynchronous).

Maybe someone could give me some general and/or specific tips to increase the performance of javaee applications, especially concerning the above issues. Thanks!

Focus on your data access code, I'm pretty sure this represents 80% of the execution time of most business flows.

And as I already hinted, are you sure that you actually have a performance problem? I'm not convinced. But if you really are, measure performances outside your IDE.

like image 111
Pascal Thivent Avatar answered Sep 23 '22 02:09

Pascal Thivent


I agreed with Pascal Thivent, in that "premature optimization" is bad. Design your code well, and then worry about performance.

Also, you can optimize for performance or memory-conservation. Pick which one is causing you headaches in the morning, and optimize for that.

I actually really like NetBeans' profiler; it's one of the best free ones, IMHO.

I would recommend:

  1. Profiling for Performance but limiting the scope to either either just your own packages (e.g., de.x) or excluding Java core classes. This is so your application isn't bogged down with profiling and giving you misleading performance numbers. Basically, try to get the "Overhead" as low as possible, as indicated by the bar at the bottom.

alt text

  1. Browse around your web app for a while see what is taking up most of your CPU time. Also take note of the fact that some objects are lazily-loaded so the first time you access pieces of code it may be slow. Also, you're using a JIT-compiler, so code may be slow the first (or second...) time you run it, but it will get faster as you use that piece of code more often. In short, use the web app for a while. You can "record" a web session using Selenium and "play" it back. This will allow you to get better performance metrics and see where your application really is slow instead of measuring "warm up time."

  2. If there is a specific piece of code or class that is causing you trouble, use profiling points to see exactly what is causing that piece of code to be slow.

If you have a specific piece of code that's causing you problems, feel free to post about that.

like image 42
The Alchemist Avatar answered Sep 22 '22 02:09

The Alchemist