APC+mysql cache (not just query but keycache too) is a must, but memcached is pointless unless you have a multi-server website (on a single server APC shared memory is way faster than memcached).
All logged out users should be served a completely cached static page that bypasses PHP entirely, it's way faster than even an opcode cache and way less load.
WP-Super-Cache can serve static pages to logged out users and makes this rather easy to setup. It's practically a must for wordpress.
I've did some experiments - and yes APC is a little bit faster (1-5ms per page rendering) when used as key-value store in comparision to memcached via unix socket. However I had always problems with cache fragmentation and a resulting slowdown. If you use Apache mod_fcgid the PHP processes are beeing shot down and started at random and APC is is not shared acress them. With nginx and PHP-FPM is is not so true anymore. I've had the impression memcached is more solid.
For static caching I use nginx with fastcgi_cache. This makes WP-Supercache obsolete. I bybass the cache for requests containing certain cookies, so that logged in users always receive fresh pages.
Another big Wordpress performance sink is locales. If you have a blog in a non-english language consider using a language-caching plugin. Wordpress uses a PHP gettext implementation that is quite slow. 20% speedup if you cache the generated locales.
But it's a shame to spend days or months on tuning Wordpress, what is essentially just a blog engine.
I don't know how the caching plugin in WP works, however the most difficult part of caching is always cache invalidation, which is the reason why Memcache is better than an in-memory cache, even for a single server, because then you have the flexibility of invalidating cache entries from a background process that does not run on that server.
It's also great to have the flexibility of adding more servers in case of a huge spike, even if you are running on only one server. Like on Heroku, where you can just increase the number of dynos in realtime. Doing that without a central cache that every server can access can break your MySQL because each new server will have a cold cache.
If you want a smart cache invalidation system for NGINX please have a look at this plugin http://bit.ly/nginxmanager
Pages are cached on NGINX for not logged in user, and when a new content is published all and only the pages that contains that content are deleted from the cached and regenerated at the next request.
All logged out users should be served a completely cached static page that bypasses PHP entirely, it's way faster than even an opcode cache and way less load.
WP-Super-Cache can serve static pages to logged out users and makes this rather easy to setup. It's practically a must for wordpress.