Posts tagged memcache
The subject of Expression Engine Snippets versus EE Embeds was recently brought back to my mind by Jean St-Amand on Twitter yesterday. It has been some time since I’ve thought about the matter, so this got me thinking a bit more about EE performance. First, some background on how we got sideways and how we solved it. Then some zen learnings at the end.
At the office, we are now on the 3rd major version of our core web product. The second version of that product was our first EE project as a team, and my first EE project ever. I am fortunate to have come in with EE 2.1.0, and I was hooked right away. It was one of the more complex systems my partner in crime has built on EE, containing over 7,000 entries at the time we did the initial build (now well over 10,000 entries). We used every trick in the book to build this thing out, and by every trick I mean every WRONG way. Related entries for every entry, categories by NAME as part of our URL structure, and my LORD did we have some embeds. Our home page must have embedded 4 levels deep at a minimum. Some of those embeds went out and performed relationship lookups to then perform a 5th level of embeds.
Looking back at the pingdom records, page response time had pass the 5.7 second mark. 5.7 seconds. There are cars that could go 0-60 mph in that time. TWICE. AB testing from a good solid cable broadband connection showed a number closer to 11 seconds. ELEVEN. Once we factored in a normal user internet connection our response time almost doubled. I was embarrassed. The smallest site (by unique visitors) I had worked on in quite some time and it was performing this poorly? We started upgrading hosting. Then migrating. Then out came Varnish. I’m not saying that Varnish is a bad tool, but by this point I knew I was just hiding the root cause. By this point I had learned enough about EE to understand the error of my ways. Vint Cerf gave me the look of a disappointed grandparent.
I bring up Varnish for a reason. It’s good. Use it. Or Memcached. Or both. I don’t care how clean your architecture is, how fast your server. Even small amounts of traffic will clog things up on smaller VPS hosting or low-end dedicated stuff. Varnish keeps traffic from even getting into your AMP stack. Memcached can help keep things out of PHP and MySQL. Learn them. Use them. IronCache makes playing with Memcached simple, I highly recommend it. The Grist Labs team is awesome.
In the recent past we had enough time to both redesign and refactor this core site. Combining over a year of EE learnings along with a better understanding of our product and customer combined powers to generate a much better product. Everything was turned into snippets. As a rule we avoided any embeds. Ditto for any type of relationship field. We found some exceptions to the embed rule, but held firm to the relationships issue. Embeds became a tool ONLY for exposing integral data and not just for making our code “look clean”. We worked hard to understand when and where an embed was needed and when other strategies solved the problem.
The numbers tell the story. The problem version had 56 embeds in our global includes template group. The new version has 14. These 14 are also infrequently used in our code. We plan on replacing a lot of these 14 with jQuery tricks in order to take the direct embed out of EE. That will make an interesting write-up of it’s own when finished.
AB testing from a normal user connection followed this line of performance:
- Version 2 - Bare System: 11 seconds
- Version 2 - Varnish: 0.8 seconds wow, Varnish is cool!
- Version 3 - Bare System: 1.2 seconds wow, Snippets are cooler than Varnish!
- Version 3 - Memcached: 0.6 seconds
Those are some telling numbers. As I said before, use either Varnish or Memcached. Use both if you need, they are NOT mutually exclusive. After refactoring into Version 3, our site performance almost caught up to Version 2 with Varnish. Note that our data structure changed in just one way: Removal of all relationships. We used two relationships on the site, but they were used on almost every single page. Worse, each relationship was usually used to feed an embed. Terrible combination there.
The Zen Learnings
Test early and test often. In the traditional software world (think C++ or Java) testing is done at nearly every stage. My best developers always turned out code that was performance tuned. You do this by testing performance on each component as well as testing performance on the integrated whole. This can be done and SHOULD be done with web development as well. I feel ignorant for not doing this the first go around. How to test? AB is the standard tool for simulating load. Combine this with server utilization numbers (I use sar 4 5) and you have a winning combination.
How do you run the test? AB makes it easy, and it should be a standard install on Linux systems as well as Mac OS X. You run it like this:
- ab -n 500 -c 20 http://www.mydomain.com/
Pretty straight forward so long as you know that:
- -n 500 means to snag the requested URL 500 times (-n, number, get it?)
- -c 20 means to run 20 gets at a time (-c is concurrency)
- http://www.mydomain.com/ is the target URL to get. I seem to need the trailing / on this to make AB happy.
When do you test? All the time. Continuously. Test each Snippet, embed and template individually then after integrating them. Create a template that just contains a single snippet with just enough supporting EE code to test what is inside of that snippet. Use preload:replace to test embeds. Test every time you think you are “done” with a feature. Test against your local dev machine. Test against production. Test, test test test and test some more.
There isn’t a magic bullet for knowing when your code is fast enough or clean enough. Indeed it is easy to assume it IS fast enough. Always challenge that assumption. It will make you think cleaner and clearer about what you are trying to do. It will force you to learn things you didn’t know existed. It will cause you to see the world from your end-users perspective. One last bit of zen advice I learned in my performance seeking adventures:
Not all fast websites are good, but all good websites are fast.
- Me, right now
• • •