Showing posts with label Wordpress. Show all posts
Showing posts with label Wordpress. Show all posts

Thursday, August 18, 2011

Why is Wordpress Slow?

I love WordPress, so it breaks my heart when our nice shiny WordPress pages take 9 seconds to load.  Here are the results of some investigations.  I don't do WP professionally, but WP is really easy to tinker with, so I'll blog this to avoid forgetting it.

The X-Plane blog uses WP Super Cache and a pile of social networking plugins.  Here's what I found for speed.

When we miss the cache, page load is really slow.  You can tell whether you missed the cache and why it's slow by looking at the last few lines of the page; WP super cache will list the time the cached page was last built, the render time in seconds, and it'll tell you if it's gzipping.  We see dynamic content times from 2 to 9 seconds!

Disabling Tweet This brought the time down to less than a second.  I don't know what Tweet This is doing (probably blocking on IO with Twitter on the server side while the page renders) but our first action will be to explore whether another plugin is faster.

So the number one issue is that when we miss the cache, run time costs are killing us.

When we hit the cache, Safari's timeline view of resources tells us what is causing the page to be slow to load.  We can see a few things:
  • One plugin is putting its java script link at the end of the page, so we lose parallelism in loading.
  • Some plugins are going to external sites with much higher latency than our server.
  • We're "scattering" a bit to get our JS - consolidation might be a good idea, but in practice we don't have enough JS to care, plus the browser will cache.
We have some slow-loading stragglers from social media live content, but they don't block page load, so I guess we can live with that for now.

Finally the third and weirdest finding: if you have local browser cookies, WP Super Cache dutifully caches the customized version of the page you see with the forms filled out.  This means that you get your own private cache site.

This is a bit terrifying first because we could have a really huge build-up of files in the cache. But it's also bad news for cache hits.  When the site changes (e.g. a comment is posted) the first user to view the page eats the cache miss.  But if you have cookies, you always miss the cache since you have your own private cache.

In our case this is really bad: it means that users who have commented before (and thus have comment-name cookie in place) will always miss the cache once for every new article they see plus every comment posted.  Which is to say, the site will virtually always be "slow" (which in our case is "really slow" due to slow plugins).

I discovered this by putting WP Super Cache in debug mode, setting my IP as the debug URL and setting the debug level to 5.  Then when I first loaded a page in FireFox, I saw a whole pile of cache output due to cookies - when I viewed the cache meta data on the server, my own commenting name and email were clearly visible.

Fixing Wordpress Auto-Update Issues

There are a ton of posts from people having trouble auto-updating WordPress. 

This is the post that has the solution to the underlying problem.  I will try to explain why it works, since I totally misunderstood this the first time and without understanding it, it's hard to fix.

When WordPress auto-updates your blog, it doesn't do so as the "apache" user that usually runs httpd.  Instead it uses your ftp login to place files into the local file system as "you".

This is very clever because it means that you don't have to give apache cart blanche over your site, protecting you from web daemons run amock (or whatever it is that web developers worry about).

So the first key point is that you need to allow httpd to make FTP calls out to servers.  That's where
/usr/sbin/setsebool -P httpd_can_network_connect=1
comes in.  This gives httpd permission to make outgoing network connections so that it can call up your server via FTP as you. 

Without this you get the "Failed to connect to FTP server XXX" error (because httpd isn't allowed to make the outgoing connection - what's tricky here is that it is the client side of FTP that's failing, not your FTP server).

The second key point is that if you have multiple users administrating WP, things aren't going to go well.  The ownership of plugins will be 644 with the only person who has write permissions being you.  If another site admin tries to update, you get an error saying that WP couldn't remove the old version of the plugin.

I don't have a great solution for this yet.  I'll update this post when we fix the problem.

Tuesday, February 15, 2011

Permalink Shortcode

This must exist somewhere in WordPress or as part of a plugin, so if you know what plugin I should have used, feel free to heap on the abuse in the comments section. Anyway...

I wanted a way to create a link to a WP page from inside a post or page that wouldn't need modification when the target page's parent was changed. WordPress's permalink scheme uses a hierarchy of parent/child/grandchild/ to identify pages, and this can change as a page is reparented. If the parenting scheme is meant to represent a navigational hieararchy, you could have dead links.

I ended up with this function, loosely based on snippets I found on the web:
function permalink_func( $atts, $content=null ) {
extract( shortcode_atts( array(
'p' => '1',
), $atts ) );
if ($content == null)
$content = get_the_title($p);
$link = get_permalink($p);

return "$content";
}
add_shortcode( 'prm', 'permalink_func' );

(It lives in functions.php inside a php block.)

The short code is used like this: [prm p=1] or [prm p=6]link title[/prm]. If the short code is used with no closing tag, the article's title is used to label the link. The parameter (p=17) is the ID of the page, and can be seen by mousing over the page or post in the admin interface. The URL generated by the shortcode matches the current permalink scheme.

Once again, I am amazed by how easy it is to get things done with WordPress. It doesn't seem right...

Thursday, February 10, 2011

Random Wordpress Notes

We're converting our website to WordPress (which I continue to be impressed by, but that'll be another post). One or two random notes.

If you put your news feed 'on a page' the page template is ignored - index.php is still used. I am sure this is by design, but I discovered it while creating a custom template. The page contents appear to be ignored too.

If you have an existing site and you want to merge in WordPress, you can do this:
  • Host your news feed on a specific page, rather than letting it default to 'home'.
  • Change the WordPress URL base (not install base) to your site.
  • Put a mod_rewrite rule into your site root to rewrite missing files to /wp/index.php (or wherever WP is installed).
  • If you want to replace an existing HTML page with a WP page you can use a rewrite rule from the old name to something like /wp/index.php?page_id=20 (or whatever page ID you want).
This is similar to the normal 'changing base' rules for WP, except that you don't need to create a second index.php in your root folder - your old site's home page stays in place.
RewriteEngine On
RewriteRule news.html /wp/index.php?page_id=5 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
mod_rewrite is pretty cryptic. Basically what this says is:
  1. If the user asks for news.html, go to WordPress article 5.
  2. If the user asks for a missing file, let WordPress sort it out.