In the first part of my blog I covered the data side of the tuning process on my homegrown PHP application Spelix: database issues, caching on both the server and the client.
By just applying these insights I could bring Spelix to a stage where the number of users could be increased by more than 150%, and user experience could be improved to make existing users eager to work with the system. By having more users contributing and delivering input, Spelix became more and more a platform for the caving community to meet and share their work. However, I did not stop my mission there. There was more to be done.
In this part, I will concentrate more on technical topics: network traffic, code caching and session handling.
Step #4: Reduce Network Traffic
When we check the timeline in detail we even get to see the actual impact of having that many requests. Too many simultaneous web requests can’t be processed in parallel as browsers have a maximum number of connections per domain to download resources. The more resources on a single domain, the more resources get queued up and need to wait. Typical numbers for parallel connections are 6-10, depending on your browser.
Tip: Consider these numbers to split or merge your resource files. You will benefit from the advantage of parallel data transfer without the overhead of too many requests.
The network dashboard shows requests per physical browser network connection, and all these are sent to spelix.at. Note that your browser limits the number of simultaneous http connections to a single domain!
By merging these files into fewer container files you can avoid a lot of network redirections, as every single file creates a request to the webserver. Be sure to define the content of your container files properly, don’t pack everything into one file!
Tips & Tricks:
- Pack your icons into sprites! One container image file for your small icon files creates only one server request compared to one request per icon! In your CSS simply define the section of the sprite that contains your icon.
- Get some more tips and tricks by checking out Best Practices on Network Requests and Roundtrips!
- Avoid physical network requests by setting up proper caching, as described in the next step!
Step #5: Leverage Browser / CDN cache
On top of the unnecessary network traffic, the files from our example are not even cached, as shown in the browser network section:
Data can be cached in your browser or even throughout the CDN (content delivery network) between the server and the browser in a proxy server. Be sure to set reasonable HTTP headers to cache your data properly. In PHP you could do this by using the header() function:
These examples store your HTTP response in the cache and keep it valid for 1 day.
Alternatively you could use Apache’s mod_expires module to set the expires-header without having your code changed. Add following lines to your httpd.conf to enable and configure the module:
Conditional and Non-Conditional Caching
If you are using the ETag field in your response headers, the ETag value is stored in your browser cache together with the document. In a new request the browser sends that value back to the server to detect changes of the resource. If the document is unchanged, the server sends a 304 Not Modified in the response header and an empty body. The browser then uses the cached document. This is known as conditional caching.
As long as your resource in the cache is not expired, the browser won’t send a request to the server (unless you press reload) and fetch the document from the cache. This is what we know as unconditional caching.
HTML5 Application Cache
Another technique of caching has been introduced with HTML5: Application cache. In a cache-manifest file you define the documents to be stored in the browser. These documents can be used then for complete offline browsing. In your main document just refer the manifest file:
If you want more tips and tricks check out Best Practices for Browser Caching
Step #5: Optimize Session Handling
In a good application design, your browser content is divided into structure, layout, business logic and data. Data is commonly fetched from the server using AJAX calls, and most likely these requests are performed in parallel, interacting with the same HTTP session.
In Spelix we have such logic in the start page, which shows a map and loads further data via AJAX. But we found that these requests are rather slow, and all of them take almost the same time.
Starting your session in PHP with session_start() reads your data from the file system into the $_SESSION variable and locks the file for further usage. A parallel process in the same session can’t access the file unless the locking process has released the lock. This can slow down your entire application when a slow process delays other processes in execution, and this is what happened in Spelix. In an AJAX call that just requests data it’s generally not required to modify the data in $_SESSION. Make sure to release the lock right after dealing with your session data by
- lock and release session files (important when handling parallel requests in a session by multiple AJAX calls)
- using data cache for session data (memcache)
Now It’s Your Turn
It’s easy to trace your application and identify the hotspots that might cause bad performance measures. Download our free trial of Dynatrace or the free Dynatrace Ajax edition to start monitoring your performance and share with use your experiences in our forum on our community!