Jump to content

PageSpeed Web Server Module


Recommended Posts

I said I would post this a few days ago, I guess having a dedicated discussion topic on Google Pagespeed configurations could be interesting.

I am running Nginx, so I am using the ngx_pagespeed module. However, other than the configuration syntax, the Apache and Nginx versions are pretty much the same.

This is the configuration I have for IP.Board,

    # Pagespeed configuration
    pagespeed On;
    pagespeed FileCachePath "/run/shm/ngx_pagespeed/";
    pagespeed FileCacheSizeKb 1048576;
    pagespeed FileCacheCleanIntervalMs 3600000;
    pagespeed CreateSharedMemoryMetadataCache "/run/shm/ngx_pagespeed/" 65536;
    pagespeed RewriteLevel PassThrough;
    pagespeed EnableFilters combine_css,combine_javascript,collapse_whitespace,extend_cache,insert_dns_prefetch,remove_comments,rewrite_css,rewrite_style_attributes_with_url,rewrite_javascript,convert_to_webp_lossless,convert_jpeg_to_progressive,insert_image_dimensions,lazyload_images,defer_javascript,convert_meta_tags;
 
    pagespeed LoadFromFile "https://example.org/public/"
                           "/srv/http/example.org/root/public/";
    pagespeed LoadFromFile "https://example.org/cache/"
                           "/srv/http/example.org/root/cache/";
    pagespeed LoadFromFile "https://example.org/uploads/"
                           "/media/storage/http/example.org/uploads/";
    pagespeed LoadFromFile "https://example.org/screenshots/"
                           "/srv/http/example.org/root/screenshots/";
 
    pagespeed Disallow     "https://example.org/admin/*";
    pagespeed Disallow     "https://example.org/*do=quote*";
    pagespeed Disallow     "https://example.org/page/index.html";
 
    location ~ ".pagespeed.([a-z].)?[a-z]{2}.[^.]{10}.[^.]+" { add_header "" ""; }
    location ~ "^/ngx_pagespeed_static/" { }
    location ~ "^/ngx_pagespeed_beacon$" { }
    location /ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
    location /ngx_pagespeed_global_statistics { allow 127.0.0.1; deny all; }
    location /ngx_pagespeed_message { allow 127.0.0.1; deny all; }
    location /pagespeed_console { allow 127.0.0.1; deny all; }

General Configuration

Let's take a look at these first three directives to start;

    pagespeed FileCachePath "/run/shm/ngx_pagespeed/";
    pagespeed FileCacheSizeKb 1048576;
    pagespeed FileCacheCleanIntervalMs 3600000;

Notice I have pagespeed storing its cache on a tmpfs partition here, mounted with the following settings,

# <file system>  <mount point>  <type>  <options>                       <dump>  <pass>
  tmpfs          /run/shm       tmpfs   rw,noexec,nodev,nosuid,size=2G  0       0

This means all of the optimized files generated by Pagespeed are stored and accessed in memory for maximum performance. This is optimal and highly recommended if you can spare the memory. How much memory you dedicate to Pagespeed is dependent on how large your website is and how much free memory you have to spare. I have plenty of memory on my server, so I can be a bit liberal, but my website is also fairly large and hosts a lot of static resources, including images.

I'm also not actually dedicating all of that 2GB to Pagespeed, I have Pagespeed set to clear out its oldest files after reaching 1GB in size every hour. This means that it may go over 1GB in that hour time frame, but it shouldn't actually come anywhere near the 2GB of memory dedicated to it. This just ensures Pagespeed won't run run out of storage space while running. If this makes you feel like you'd be wasting a gigabyte of RAM in this situation, you're not. The memory not in use here is still free to be used for disk caching and the sort, but you should always keep careful control over your servers available memory pool. Avoid ever allowing an even potential situation where your server could actually run out of memory. This could easily crash your entire server, and is a common case scenario for people who wildly misconfigure Apache and/or MySQL.

(If you're tl;dr'ing my off-topic lectures, I don't blame you, sorry for being a bit too wordy!)

Next, take a look at this setting.

    pagespeed CreateSharedMemoryMetadataCache "/run/shm/ngx_pagespeed/" 65536;

This setting is well documented, but I actually overlooked it initially. This dedicates 64MB of memory entirely to storing metadata cache. This is far better compared to allowing Pagespeed to write all of this data to your filesystem and should absolutely be used. As above, how much memory you should actually dedicate here is dependent on how large your website is. If you want learn how to fine tune this setting, refer to the documentation.

Filters

    pagespeed RewriteLevel PassThrough;
    pagespeed EnableFilters combine_css,combine_javascript,collapse_whitespace,extend_cache,insert_dns_prefetch,remove_comments,rewrite_css,rewrite_style_attributes_with_url,rewrite_javascript,convert_to_webp_lossless,convert_jpeg_to_progressive,insert_image_dimensions,lazyload_images,defer_javascript,convert_meta_tags;

The first setting here disables the default filters so you can configure only the ones you explicitly want.

These are the filters I've decided to use after a bit of testing, from highest to lowest priority.

High Priority

  • defer_javascript - This is one of the best filters available, but also one of the most dangerous. It can completely break your website if not configured properly, but it gets rid of the multiple render blocking issues that IP.Board natively has. Ever notice how there's always a "flash" when browsing your forum in Chrome, for example? This is why, and this is something that is especially annoying (and somewhat blinding to your visitors) when you're using a dark template. For more information on deferring javascript, see this page.

    Keep in mind again, this filter is considered high risk. You may have to go through some of your templates (especially if you're using custom scripts) and add the "pagespeed_no_defer" attribute to them to prevent breakage.
  • combine_css - This filter lets you combine CSS resources without having to rely on PHP. I recommend you enable this, and disable Minify CSS and JS in your IP.Board settings, so you're not left relying on PHP to serve static resources.
  • combine_javascript - This filter lets you combine Javascript resources without having to rely on PHP. I recommend you enable this, and disable Minify CSS and JS in your IP.Board settings, so you're not left relying on PHP to serve static resources.
  • extend_cache - This is an easy way to enable extended browser caching on static resources. If any files on your server change, the unique hash identifier in the URL will change with it, so you never have to worry about your visitors being stuck with old resources when enabling browser caching. Though IP.Board automatically does this for most resources by implementing its own anti-cache query strings, it's still good to enable as a lazy yet efficient way to ensure all your static resources have proper cache headers set.
  • rewrite_css - This filter parses linked and inline CSS, rewrites the images found and minifies the CSS. Minification can drastically reduce the byte count in common CSS by stripping all comments and most whitespace and shortening color names. It also enables other filters (such as image filters) to apply to resources included in your websites stylesheets. Overall a great filter, but is considered moderate risk. I have personally had no problems with it.
  • rewrite_javascript - This filter minifies JavaScript code, using an algorithm similar to that in Douglas Crockford's popular JSMin program. Minification can drastically reduce the byte count in common JavaScript code. This filter can be used to avoid the extra step of minifying Java code by hand when constructing and maintaining a site.
  • lazyload_images - This is a particularly nice filter for forums. Why? Forums often have a lot of images. Avatars and post attachments, for example. This filter lets you "lazily load" those images, meaning, your visitors won't actually have to download and render the images until they're in the clients "viewport" (or basically until they scroll down). If you decide to use this filter, it is strongly recommended you consider enabling the insert_image_dimensions filter as well.
  • convert_to_webp_lossless - This is the only image filter I am going to highly recommend using, purely because of how impressed I am by it. WebP was initially only focused on improving lossy image compression (which I am hesitant to suggest re-compressing already lossy images). WebP now also offers improved lossless image compression as a new alternative to PNG. How good is WebP's lossless compression compared to PNG you may ask? See for yourself. It is pretty impressive.

    The caveat with this is that WebP is only supported in some browsers, which is also why Pagespeed is so perfect for making use of it. Pagespeed automatically detects if the browser supports WebP. If they do, they're served with the optimized resources. If not, they get the original image. Extremely easy. No overhead or requirements for the developer. This is honestly the only time I would bother making use of WebP, because otherwise, it's simply not worth the hassle of programming your web application to detect for WebP support and generate two versions of the same images to serve.

Medium Priority

  • insert_image_dimensions - This flag inserts width= and height= attributes into <img> tags that lack them and sets them to the image's width and height. Good to use with lazyload_images, but is medium risk. I have noticed this filter may cause avatars on profile pages to become stretched. To fix this, you need to manually edit the profileModern template and replace the following line,
    <img class="ipsUserPhoto" id='profile_photo' src='{$member['pp_main_photo']}' alt="{parse expression="sprintf($this->lang->words['users_photo'],$member['members_display_name'])"}" />
    with,
    <img class="ipsUserPhoto" id='profile_photo' src='{$member['pp_main_photo']}' alt="{parse expression="sprintf($this->lang->words['users_photo'],$member['members_display_name'])"}" pagespeed_no_transform />
  • convert_jpeg_to_progressive - This is the second and last image filter I currently recommend using. This page offers a good sample showing baseline vs. progressive images. This filter will only apply to images over 10KB in size by default.
  • rewrite_style_attributes_with_url - The "Rewrite Style Attributes" filter rewrites the CSS inside elements' style attributes as performed by rewrite_css, which includes CSS minification, image rewriting, image recompression, and cache extension. This filter is especially useful with IP.Gallery, where all large album preview images make use of CSS backgrounds and will otherwise miss out on pagespeed optimizations.

Low Priority

  • collapse_whitespace - Low risk, low reward. Pretty self-explanatory. This strips all the unnecessary whitespace from HTML output. IP.Board can output quite a decent bit of whitespace. Right click any page here and click "View Page Source" to see what I mean. Stripping all of this white space sounds like a great way to reduce the size of your web pages, but the reality is, with gzip compression enabled it won't really matter and the difference is completely negligible. But if you want to get the feeling that "wow, this is really doing something!" the next time you view your pages source, this is a great filter to use! No more excessive whitespace bloat, everything is nice and compact, you can lay your OCD to rest now.
  • convert_meta_tags - The 'Convert Meta Tags' filter adds a response header that matches each meta tag with an http-equiv attribute. For example, <meta http-eqiv="Content-Language" content="fr"> would be converted to Content-Language: fr in the response headers. Certain http-equiv meta tags, specifically those that specify content-type, require a browser to reparse the html document if they do not match the headers. By ensuring that the headers match the meta tags, these reparsing delays are avoided.
  • insert_dns_prefetch - DNS resolution time varies from <1ms for locally cached results, to hundreds of milliseconds due to the cascading nature of DNS. This can contribute significantly towards total page load time. This filter reduces DNS lookup time by providing hints to the browser at the beginning of the HTML, which allows the browser to pre-resolve DNS for resources on the page
  • remove_comments - This strips HTML comments from output. Another one of those low-risk filters that saves an extra few bytes at little cost.

LoadFromFile


By default PageSpeed loads sub-resources via an HTTP fetch. It's much better to allow PageSpeed to load files directly from the disk, and it's required to do this if you run your forum under HTTPS.

    pagespeed LoadFromFile "https://example.org/public/"
                           "/srv/http/example.org/root/public/";
    pagespeed LoadFromFile "https://example.org/cache/"
                           "/srv/http/example.org/root/cache/";
    pagespeed LoadFromFile "https://example.org/uploads/"
                           "/media/storage/http/example.org/uploads/";
    pagespeed LoadFromFile "https://example.org/screenshots/"
                           "/srv/http/example.org/root/screenshots/";

Replace "https://example.org" with your forums base URL and replace the paths below each URL with the associated location paths on your fourm.

Disallow

There are some pages and resources you'll want to disallow PageSpeed access to.

    pagespeed Disallow     "https://example.org/admin/*";
    pagespeed Disallow     "https://example.org/*do=quote*";
    pagespeed Disallow     "https://example.org/page/index.html";

First is your admin directory. If you use a renamed admin directory, change this setting appropriately. PageSpeed does not seem to cause anything in the AdminCP to break or glitch, but there's really no reason you need it to run on pages here. It's best to just leave it off.

Second is required if you want to use the defer_javascript filter. When quoting a post on IP.Board, the editor makes an ajax call to a page that returns HTML output. If you do not stop PageSpeed from applying filters to this page, your users will have a bunch of gibberish Javascript code plastered into the editor every time they try and quote a post. This issue took me a decent while to track down. Quite annoying, but very easy to fix.

Lastly, I disable the filter for my IP.Content homepage. This is because deferring javascript makes things a bit glitchy with the gallery slideshow, and trying to work around it with pagespeed_no_defer attributes is a headache. If you don't use the gallery slider on your IP.Content homepage, you can probably safely remove this line.



Again, this is just the configuration I've tuned so far and the configuration I used on my production forums. Don't expect it to be a perfect configuration for your forum or server. To learn more about PageSpeed and to learn how to fine tune things specifically to your liking, the web server module is very well documented, just dive in and start learning.

Please feel free to offer feedback on my configuration here, as well as offer your own tips and suggestions, or just post your general experience with using the PageSpeed module on your forums.
Link to comment
Share on other sites

  • Replies 90
  • Created
  • Last Reply

Is this something you would be willing to be hired to do?

Sure, if you'd like me to set this up for you, just send me a private message and we can work out the details.

have you tried this with php 5.5?

I have not yet had a chance.

I had issue with combine_css when a dcn was used for css.

Really? Maybe it has something to do with minifying the resources? Because that's the only time PHP should come into play, I would think. (That's also why I recommended disabling minification if you use the filter, since you don't need to rely on PHP anymore)

do you have any performance stats?

some comparision with other types of caching?

I don't have any side-by-side comparisons right now, but I can definitely try and generate some.

This is one of my development forums that runs using SPDY and PageSpeed though,

http://community.invisionpower.com/topic/395989-getting-ipboard-to-load-in-1-second/?p=2457262

Link to comment
Share on other sites

It depends. I love experimenting with new technologies and don't mind investing my time into projects that may not have any guaranteed results, just for the sake of learning if anything. Whether or not playing with PageSpeed will be worth your time depends partially on how much experience you have with server administration in general (as this requires installing and configuring third party modules in Apache, or manually compiling third party modules into Nginx) and how much time you're willing to invest. The goal of this thread is to help give people a good starting point and minimize some of the headaches, but depending on your specific configuration and what filters you want to use here, it can still require some manual labor on your part to ensure everything is configured optimally for your specific IP.Board installation.

I also use Google SPDY on my forums and believe it definitely helps, at least with browsers that support it. (Basically, not IE).

Using Google SPDY requires you configure your forum to run entirely under HTTPS. That's probably the most complicated aspect of it, but configuring IP.Board to run under HTTPS itself isn't too complicated. You mostly just need to get a signed SSL certificate and tweak a few settings in IP.Board.

Link to comment
Share on other sites

actually was wondering about spdy with mixed content too, the forums are full ssl but of course I cannot items from other sites.

have you seen any issues with this?

You mean users linking to images on third party HTTP sites in their posts, right?

If so, no. I posted about that in your other thread :P

This is an example page with mixed inactive content. It should load fine for you, yes?

Mixed active content is the only thing that should cause problems, and that's something you shouldn't have to worry about. Active content is basically Javascript and iframes (which is why you have to tweak the media code for YouTube embeds when using HTTPS)

Link to comment
Share on other sites

It probably was. You just have to make sure if you use any third party services such as AdSense or Google Analytics, that it loads the script from a HTTPS source.

I believe Analytics at least checks if you're connecting over HTTP or HTTPS and makes the appropriate request. I think I had to manually modify AdSense's script URL though.

But in general, you should have no problems.

Link to comment
Share on other sites

I ended up getting this running myself (after much banging my head on the wall with the Cpanel add-in). I shaved 6 seconds off my total load time. Right now, I have an unusually large Time to First Byte that I have to resolve and my OpenX Ads are very slow to load... but all the rest of the board loading stuff is now much faster.

Link to comment
Share on other sites

I ended up getting this running myself (after much banging my head on the wall with the Cpanel add-in). I shaved 6 seconds off my total load time. Right now, I have an unusually large Time to First Byte that I have to resolve and my OpenX Ads are very slow to load... but all the rest of the board loading stuff is now much faster.

The large TTFB could be the result of some filters causing lag. Did you set PageSpeed up to run on a tmpfs partition, or are you just using a your hard drive partition for the PageSpeed cache?

You should be able to pull up the PageSpeed Console and see if any filters are causing problems anyways.

You might not be able to do anything about the OpenX ads. Some ad services are just really crappy with load times.

Link to comment
Share on other sites

I had a large TTFB before the adding the pagespeed module. My hard drives are actually raid 10 SSD drives, so while I could run the cache to ram, I probably won't see much of a speed increase there. As such, I'd rather leave the ram for the MySQL and Apache servers.

My solution for the OpenX ads will likely be to replace them. I've been unhappy with them for a while for other reasons.

How do I pull up the pagespeed console?

Edit: Found it.

Link to comment
Share on other sites

You're probably right, I would still say you should still definitely make use of the Shared Memory Metadata Cache at least though, simply because of how inefficient storing all of that data to disk is, and generally 64MB of memory should be more than enough to allocate for a moderate to large sized forum.

Can you run this on your server?

curl -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} n" http://inserturl.here


Run that on a few pages. Your board index and a few random forums and topic pages specifically. See what the TTFB is when making requests directly on your server. If this is high, that means there's lag in the backend that's slowing your forum down. If it's not, that generally means it's a network related issue.

Link to comment
Share on other sites

I think the Nginx variation of PageSpeed automatically gzip compresses output regardless of your web server configuration, but I'm not 100% sure on that.

You can easily test if your website/static resources are being loaded with gzip here though,

http://www.whatsmyip.org/http-compression-test/

If it's not already, you most definitely should enable it.

If you have gzip compression enabled in Nginx, you can safely disable gzip compression in IP.Board's settings also. Output from upstream (PHP-FPM) should also be gzip compressed by Nginx.

Link to comment
Share on other sites

I did the test on your dev site and in shows compression is enbled.

Do You have gzip enabled in nginx?

Yes, and I just tested to see if PageSpeed automatically applied gzip compression, and it does not. At least not for standard HTML output, it may automatically compress its cached static resources (since those are probably handled by the module itself and not by nginx), but it doesn't replace gzip compression in Nginx.

So you should ensure you have it enabled in your Nginx configuration.

I also do make use of gzip static on my forums, but the benefit is probably highly negligible at best unless you're dealing with absurdly massive amounts of traffic, as the overhead of standard gzip compression is very low.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.

  • Upcoming Events

    No upcoming events found
×
×
  • Create New...