Recently, a customer reported that the performance of the web application we are building, an AngularJS front end using REST services from a Java back end, is unsatisfactory. I had a fun time finding out what the problem was, understanding what was causing it and thinking up solutions. I’d like to share the experience with you.
What is the problem?
“Bad performance” can mean many things. Actual response times are only part of the story; an application that shows feedback while gathering a response can make you wait longer before it is perceived as slow. When users know their bandwith is limited, for instance on a mobile device on a slower network, they anticipate a slower site. But of course, it is always possible that the services on which your site relies are just too slow.
So, first order of business: ask the reporter what he means. What action did he perform, and how long did it take? How long did he expect it to take? It turned out there were several problem areas, not all of which were actually related to performance. I will describe two of these areas in more detail:
- loading of the AngularJS application
- loading of list views
Loading of the AngularJS application
Our AngularJS application has to perform several tasks before it can render the first view. This takes time, and during this time the end user is staring at a blank page.
Finding out what happens
To figure out what tasks are executed and which of these can most easily be sped up I opened a fresh Chrome window, trashed all the caches, opened the network panel and loaded the main page:
This is interesting. There is a flurry of activity at the start, followed by 300 ms of silence, after which a lot more is loaded. What does it mean?
- Initialization of the AngularJS application
- Retrieving the translations file
The initialization of the AngularJS application is not an easy one to speed up, so I’ll concentrate on the other two parts.
The contents of the translations file were all used. However, since this is a plain text file, it was a prime candidate for zipped transfer. AngularJS handles zipped files out of the box, so the only thing we needed to do was add an @org.apache.cxf.annotations.GZIP annotation to the Apache CXF resource in the back end, which reduced the download time from several hundred milliseconds to ~10 ms.
List views are always tricky, especially if there is no limit to the number of elements that may show up in the list, as was the case in some of our services. However, that turned out to not even be the biggest problem.
When opening a page with a list, the application would show a spinner to indicate that the contents of the list were still being retrieved. The spinner would be removed, and the list shown, when the variable containing the list data was present on the scope: