Sixteen things you can do to make SMF go faster.

Started by Vekseid, February 16, 2009, 05:40:49 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Vekseid

I posted this on SMF's forums... but anyone running SMF may benefit from this, so here you go : )




The following are sixteen improvements that you should be able to make to SMF regardless of your host, though only the first set will be possible anywhere. If the second set is not possible (outside of say, using Postgres over MySQL, in which case you probably don't need the second set), then I seriously suggest finding a new host. Hosts should provide you with shell access, access to crontab, php5 and InnoDB. An inability to do these things securely does not speak well of confidence in them.

Not all of these ideas are mine, but I did tweak some of them. I give credit to other places in the form of a link - I wanted everything in one place for people to easily reference, as opposed to being forced to check several lists - some of which are quite old. I believe this covers the overwhelming majority of what you would want to do without significantly altering the schema (TinyText needs to die a slow, horrible death), smf's code (as does the @ operator), or your server configuration. A lot can be done in these areas, but the first two are probably best dealt with by pressuring the SMF team directly, while the last deserves a far more comprehensive discussion.

If anyone has additional comments or optimizations, feel free to mention them. If appropriate I will edit them in here.




Basic Improvements

Just about anyone can make use of these optimizations, regardless of how much control you have over your server. The first few options here can have an extremely dramatic effect on your server's performance, I've sorted them roughly in order of potential impact.

1: Move your uploaded avatars directory. In the administration panel, go to Attachments and Avatars, and then go to Avatar Settings.

For Upload avatars to... select: Specific directory...
For Upload directory: put in the raw, publicly accessible server directory you want them added to ie /var/www/yoursite/docs/forums/avs

So assuming /docs was your webroot, you would put /forums/avs for your upload URL. Don't do what I did and make it a subdirectory of your main avatars directory, SMF still handles it like an attachment directory for some reason so if someone uploads a .png avatar, someone else decides to use it and the first person replaces it with a .jpg avatar, the first will be deleted.

The benefit of this borders on the ridiculous. Every single avatar load is  another php call, which loads a session, the user's settings and permissions, the board and its theme. In addition, two additional calls to the database are made to load the avatar itself, and to increment the view counter. So not only are you reducing the processor load on your server, but you are also reducing your database load. If five different avatars are displayed on a page, that's five additional php calls and dozens of database queries getting made.

After you do this access index.php?action=manageattachments;sa=moveAvatars to use the hidden feature to move your avatars over.

2: Disable hostname lookups. This is located in Features and Options -> Layout and Options or Server Settings -> General in RC1 and on. If you leave hostname lookups on, every single page access carries with it a reverse DNS query. If your host's RDNS is having issues or goes down, you are going to hear about the lag from your members.

3: Enable gzip compression. This is located in Server Settings -> Feature Configuration. This has the greatest benefit when combined with #1, particularly for dialup users. Your webserver configuration may render this irrelevant, however.

4: Tune topics, members, and posts per page. In Posts and Topics -> Topic Settings. Setting this low can have a detrimental affect on your forum's raw activity, however, at least it did on mine. If people click more, they make more requests, after all, and get more frustrated. I use fifty topics per page and twenty-five posts per page, which seems to be close to ideal. Disabling participation icons will also reduce load a slight bit, but some may find this annoying.

5: If you are going to enable search, and are not or cannot use Sphinx, use a Large Custom Index. SMF's custom index works by taking a hash of every available word, and then building an index of which words point to which messages. 'Small' means this is a 16 bit hash, 'Moderate' is 24 and 'Large' is a 32 bit hash. 'Large' is thus only two bytes larger per record than small is, plus an additional number of records based on the average number of unique words per post you have - which is not going to be a significant increase. The speed improvement you get for the additional ~40% space usage is well worth it.

6: Don't use post moderation on an active forum. Where active is over a thousand posts a day or so. Apparently the query is rather slow, but it is not difficult to have a self policing forum.

7: Disable the recent posts feature on the board index. Let people click a link if they want to see more than the last post they have access to, compiling that list is expensive especially if you have a lot of groups set up. Also I find it rather ugly, myself.

8: Run the mark read for inactive users script periodically. The log_topics, log_boards, and log_mark_read tables are not the best designs, and for some unlucky folks end up dominating their database. Pruning them can help.

9: Do you really need that many boards? I tend to see this rather often and the answer is almost always no. Too many boards actually reduces your forum's activity, for one, but in the case of optimization here, each and every board takes up resources on the relatively common index load, as well as space for the log_boards and log_mark_read tables, with an amount that grows for each new member you gain.

10: Do you really need the calendar? When enabled, SMF looks for an event on each and every thread load - there are ways to make it more efficient but in general it's not an often-used feature.

11: Ben has a post about disabling features according to server load here. Don't enable this on a shared server or VPS unless you know what you are doing or at least have some guidance, but this can be pretty dramatic. My members use 'show unread posts' or 'show unread replies' roughly thirty thousand times per day. During high loads, even if they're caused by someone else, those sorts of requests are not helping.

12: Consider using database-driven sessions and offloading all attachments to Mediawiki. There is an awesome MediaWiki extension here though some minor tweaks are needed for 1.13 - see the talk page. Combine with hotlinking protection and you can have a slightly more efficient file handling system. It is likely more difficult for your members to use, however.




Intermediate Improvements

These steps are going to require some support from your host, or for you to actually be the host, as in running off of a VPS or dedicated hosting solution. The total improvement in speed can be extremely dramatic, however - you can easily cut your forum's response time in half. These will be possible with any and every vps/dedicated host, of course, and pretty much any shared host you ought to be doing business with.

1: Converting Tables to InnoDB and MEMORY Download and run status.php from the checklist post here. Click on "Show more information" and look for the have_innodb: setting. Does it say YES? Good. If it says no, and you are on a shared host, and after all of the above you are still having issues, it's time to get a VPS or at least a better host.

First, clear out your error logs from smf's error page, and make a backup of your database.

You may also want to wipe out the read message indicators if you don't want your forum to be unresponsive for too long when you do some of this:


DELETE FROM smf_log_boards;
DELETE FROM smf_log_topics;
DELETE FROM smf_log_mark_read;


If you don't do this these three are going to take their sweet sweet time.


ALTER TABLE smf_attachments ENGINE=InnoDB;
ALTER TABLE smf_collapsed_categories ENGINE=InnoDB;
ALTER TABLE smf_log_actions ENGINE=InnoDB;
ALTER TABLE smf_log_boards ENGINE=InnoDB;
ALTER TABLE smf_log_errors ENGINE=InnoDB;
ALTER TABLE smf_log_karma ENGINE=InnoDB;
ALTER TABLE smf_log_mark_read ENGINE=InnoDB;
ALTER TABLE smf_log_online ENGINE=InnoDB;
ALTER TABLE smf_log_topics ENGINE=InnoDB;
ALTER TABLE smf_members ENGINE=InnoDB;
ALTER TABLE smf_sessions ENGINE=InnoDB;
ALTER TABLE smf_settings ENGINE=InnoDB;
ALTER TABLE smf_topics ENGINE=InnoDB;
ALTER TABLE smf_log_activity ENGINE=InnoDB;


The following command will only work for SMF 1.1. SMF 2.0 commands are next.

You will also want flood control to be memory/heap:

DROP TABLE smf_log_floodcontrol;
CREATE TABLE smf_log_floodcontrol (
  ip char(16) NOT NULL,
  logTime int(10) unsigned NOT NULL default '0',
  PRIMARY KEY (ip),
  KEY logTime (logTime)
) ENGINE=HEAP;


For SMF 2.0 the create statements for this is a bit different:


CREATE TABLE `smf_log_floodcontrol` (
  `ip` char(16) NOT NULL default '',
  `log_time` int(10) unsigned NOT NULL default '0',
  `log_type` varchar(8) NOT NULL default 'post',
  PRIMARY KEY  (`ip`,`log_type`)
) ENGINE=HEAP;


Finally, on a forum with a lot of personal messages this is going to take awhile. So warn people, etc. etc.


ALTER TABLE smf_pm_recipients ENGINE=InnoDB;


SMF 2.0 has a few additional tables that you may wish to convert to InnoDB:


ALTER TABLE smf_pm_rules ENGINE=InnoDB;
ALTER TABLE smf_log_spider_stats ENGINE=InnoDB;


Unless you have installed mods, this should be a fairly complete list as of SMF 1.1 and 2.0 (I think >_>). Your mileage will vary regarding the amount of benefit this will provide - I switched my own forum after ~1M posts and response roughly doubled.

Some suggest converting -all- tables except floodcontrol to InnoDB. For most tables this is perfectly reasonable, but for smf_personal_messages and smf_messages, as well as similar "Post and forget" tables like a Shoutbox, this can actually be counterproductive to performance, particularly with a good-sized key_buffer and concurrent_insert = 2 in your my.cnf config. A warning, however, is that smf_boards currently depends on MyISAM's ordering in order to display boards properly - if you convert it to InnoDB you will want to make adjustments to the key and/or SMF accordingly.

2: Run PHP 5. If your host does not at least give you the option, get a new host.

3: If possible, keep SMF in its own database. If you do something like I do and have SMF, Drupal, MediaWiki, and other sites all on the same physical server, it's a good idea to give each such application and even every -instance- of each such application its own database. The primary purpose of this is not quite speed, but rather organization and faster backups.

4: Backup scripts make the world go round. You will need shell access for this, and I am making the possibly erroneous assumption that your server uses bash. There are several steps involved here:

A: Disable SMF's table optimization. This is in Server Settings -> Feature Configuration, set Optimize tables every how many days to 0 to disable it.

B: Make two subdirectories from your home directory. Call one 'backups' and the other 'scripts', without the quotes. chmod o-rx the both of them.

C: We're going to want to let your members know that your forum is getting backed up, because once you get into the million post range this is going to bring it down for awhile. Make a file in the scripts directory called Settings.lock.php - obviously, you're going to want to customize this appropriately.


$maintenance = 2;
$mtitle = 'Backup in progress';
$mmessage = 'We are in the midst of the nightly optimization and backup script. This currently takes a few minutes. Thank you for your patience. : )';

$mbname = 'Your Forum Name';
$language = 'english';
$boardurl = 'http://yourdomain.com/forums';
$webmaster_email = 'webmaster@yourdomain.com';
$cookiename = 'CookieName';

$boarddir = '/var/www/forums/docs/forums';
$sourcedir = '/var/www/forums/docs/forums/Sources';


D: Let's make a script in your scripts directory. Call it backup.smf and be sure to chmod 700 it. You are certainly going to have to edit the directories, database names, and password accordingly. Use whereis mysqlcheck/mysqldump/nice/bzip2 to make sure the directories calling them are accurate. You may also wish to remove --auto-repair from the mysqlcheck line, though fortunately, as you will note, you have already made a backup immediately beforehand in case something goes wrong. : )


#!/bin/bash
cp /var/www/webdir/docs/forums/Settings.php /home/userdir/scripts/Settings.orig.php
cp /home/userdir/scripts/Settings.lock.php /var/www/webdir/docs/forums/Settings.php
/usr/bin/nice /usr/bin/mysqldump -q -u dbusername -p"dbpassword" --ignore-table=smf_forums.smf_log_search_words smf_forums > /home/userdir/backups/smf_forums.`date +%a`.sql
/usr/bin/nice /usr/bin/mysqlcheck -ao -–auto-repair -u dbusername -p"dbpassword" --databases smf_forums
/bin/chmod o-r /home/userdir/backups/smf_forums.`date +%a`.sql
cp /home/userdir/scripts/Settings.orig.php /var/www/webdir/docs/forums/Settings.php
/usr/bin/nice /bin/bzip2 -f9 /home/userdir/backups/smf_forums.`date +%a`.sql


Line by line, this script:
1: Calls the interpreter
2: Makes a backup of our Settings.php file
3: Copies the locked Settings.php file over our forum Settings.php, shutting down the forum
4: Calls nice (this is optional, I use it because it's not the only aspect of the site) to make a backup via mysqldump. If you are not using a custom search index (Sphinx or search is just disabled) then you can omit the ignored table. The `date %a` in the filename returns the three-letter weekday. Omit if you just want one backup. `date +%b-%d` would let you keep a year's worth of backups (god why...) etc. The weekly log rotation seems to be a good compromise between space and having more than one backup to try and recover from IMO.
5: Optimizes our database and checks it for errors, again using nice.
6: I'm paranoid, even though I run my VPS on my own, don't want any random chance of someone breaking into an account and reading it.
7: Since we've got our database backed up, we can freely restore our original Settings.php before we compress the file.
8: nice is less optional here. Now that we're up and running again, compress the ginormous backup we just made. Do not pipe mysqldump to bzip2. You will end up taking your forum down for far longer than it needs to be unless you have a tiny forum.

E: run crontab -e and add this line:
35  4  *   *   *     /home/userdir/scripts/backup.smf

Change the directory and time as needed. This runs the backup at 4:35 AM my time, each morning, which is when my forums have the least amount of activity.

F: I use a WinSCP script to synchronize these with my machine at 5 AM each morning. You can set something up similar for your own machine or operating system.

edie

Brilliant post Vekseid. Since following your tips my forums site speed has gone from loading at 2.6 seconds to just under 1 second. I've even had a few people tell me how great it is that the site is loading much faster.

I also agree with number 6 that on an active forum it's better to have users self police spam and use the report posts function. Thanks for taking the time to write an awesome post.