<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:cc="http://creativecommons.org/ns#" >

<channel>
	<title>/etc</title>
	<atom:link href="http://blogs.ubc.ca/scottmcmillan/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.ubc.ca/scottmcmillan</link>
	<description></description>
	<lastBuildDate>Mon, 19 Dec 2011 19:16:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<cc:license >Creative Commons Attribution-NoDerivatives CC BY-ND</cc:license><dc:rights  >Creative Commons Attribution-NoDerivatives CC BY-ND</dc:rights>		<item>
		<title>September 2009 &#8211; 2010 traffic comparison.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/10/01/september-2009-2010-traffic-comparison/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/10/01/september-2009-2010-traffic-comparison/#comments</comments>
		<pubDate>Fri, 01 Oct 2010 17:06:21 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[web analytics]]></category>
		<category><![CDATA[Wiki]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=1033</guid>
		<description><![CDATA[September is always the busy time on campus so one thing that is cool to do is look back to last years traffic and see how things are fairing, are things going up or down are things scaling etc. Well &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/10/01/september-2009-2010-traffic-comparison/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>September is always the busy time on campus so one thing that is cool to do is look back to last years traffic and see how things are fairing, are things going up or down are things scaling etc.  Well things are still going up, way up which is very cool. No longer brochure traffic! WordPress is more popular than ever on this campus.</p>
<p>The WordPress CMS service which has been growing rapidly and has seen a huge spike in traffic thanks to some  50+ campus sites coming on board (and one very popular site <a href="http://elearning.ubc.ca">http://elearning.ubc.ca</a>). Last year during the month of September the service had  (79,821)  page views fast forward a year and the service averaged (2,009,301) page views 25x increase! </p>
<p><strong>WordPress CMS Service page views Sept  2009 &#8211; 2010</strong><br />
<a href="http://blogs.ubc.ca/scottmcmillan/files/2010/10/cms_page-_views.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/10/cms_page-_views.png" alt="WordPress CMS - Page View Traffic" title="cms_page-_views" width="540" height="294" class="aligncenter size-full wp-image-1034" /></a></p>
<p>UBC Blogs which has moved out of the &#8220;pilot&#8221; mode is also increasing not as rapidly as the CMS service which is kind of a surprise we though it would be the opposite&#8230;  In September 2009 UBC Blogs saw (158,654) page views in September 2010 (434,203) more than double. </p>
<p><strong>UBC Blogs page views September 2009 &#8211; 2010</strong><br />
<a href="http://blogs.ubc.ca/scottmcmillan/files/2010/10/blogs_page_views.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/10/blogs_page_views.png" alt="" title="blogs_page_views" width="533" height="292" class="aligncenter size-full wp-image-1036" /></a></p>
<p>Even wiki.ubc.ca has seen a double in traffic as well. Thanks to quite a few courses taking a stab at developing their course in the wide open wiki. </p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/10/wiki_page_views.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/10/wiki_page_views.png" alt="" title="wiki_page_views" width="520" height="286" class="aligncenter size-full wp-image-1044" /></a></p>
<p>Exciting times. </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/10/01/september-2009-2010-traffic-comparison/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Zuckerberg says the web must not die.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/09/23/zuckerberg-says-the-web-must-not-die/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/09/23/zuckerberg-says-the-web-must-not-die/#comments</comments>
		<pubDate>Thu, 23 Sep 2010 14:44:08 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=1024</guid>
		<description><![CDATA[Yay! We still have jobs for awhile&#8230; Zuck mentions the importance of HTML5 in this RWW article Why the Web is not going to die That standard is HTML5, which Facebook plans to push very hard. If HTML5 can deliever &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/09/23/zuckerberg-says-the-web-must-not-die/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Yay! We still have jobs for awhile&#8230; Zuck mentions the importance of HTML5 in this RWW <a href="http://www.readwriteweb.com/archives/facebook_founder_doesnt_want_the_web_to_die.php">article</a> </p>
<blockquote><p>Why the Web is not going to die<br />
That standard is HTML5, which Facebook plans to push very hard. If HTML5 can deliever a wide range of functions with a good user experience, then Facebook can develop one HTML5 version for every new product it launches and &#8220;that would be awesome,&#8221; Zuckerberg said. And HTML5 could combat the problem of unfair access raised by the great App Migration.</p>
<p>Already Facebook has launched a special mobile site for people in developing countries (and some developed ones). 0.facebook lets users access a speedy, data charge-free version of Facebook with a mobile browser from any basic phone even in parts of the world with poor infrastructure.</p>
<p>Until the devices that people use to access the internet are completely standardized, the Web will never die.</p></blockquote>
<p>While at Google i/O this was obvious Google is really pushing HTML5 and I heard a few comments like wouldn&#8217;t it be great if you only had to write your mobile app once&#8230; It will happen and Apple will not like it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/09/23/zuckerberg-says-the-web-must-not-die/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>I love UBC IT VMs also  Caching because you&#8217;re not Caching everything.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/09/13/i-love-ubc-it-vms-and-caching-because-your-not-caching-everything/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/09/13/i-love-ubc-it-vms-and-caching-because-your-not-caching-everything/#comments</comments>
		<pubDate>Mon, 13 Sep 2010 18:10:33 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=985</guid>
		<description><![CDATA[Students are definitely back on campus! The Sub is packed there are line ups for coffee at all the Starbucks and some of our web servers have increased traffic 10x fold! 10x fold? This is related to the CMS WordPress &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/09/13/i-love-ubc-it-vms-and-caching-because-your-not-caching-everything/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Students are definitely back on campus! The Sub is packed there are line ups for coffee at all the Starbucks and some of our web servers have increased traffic 10x fold!</p>
<p>10x fold? This is related to the CMS WordPress install we help maintain/develop with Public Affairs  one site on that service  is the reason for the traffic spike basically all logins/logouts  to the campus LMS is directed through that  site otherwise it would have been more or less business as usual for that service.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/09/sept_traffic_spike.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/09/sept_traffic_spike.png" alt="" title="sept_traffic_spike" width="468" height="121" class="aligncenter size-full wp-image-989" /></a></p>
<p>We did plan for this and load tested and we thought it could handle it but when we were hit with a huge flood of traffic because of a Vista outage we were crushed CPU was maxed out. *This is the reason why I love UBC IT VMs imagine being in this scenario with a locked in piece of hardware you would be hooped big time. We were able to contact UBC IT Infrastructure and they added a CPU literally on the fly! Do you know how cool that is? It&#8217;s very cool. Chris dropped the CPU in and the load came down the site was still sluggish but functional. VMs rock!</p>
<p>BUT&#8230; this was still very surprising to me to see it crumble on Tuesday. I have had a site hit by front page <a href="http://digg.com">Digg</a> and <a href="http://reddit.com">Reddit</a> traffic  which received considerably more traffic on a 7 dollar per month Webhost account back in 2006 and did not crash!  I was  simply using wp-cache 2 (before Super-Cache) a  Cutline theme and one plugin! No APC no Super-Cache no MySQL Query Cache! It held up on shared host with hundreds of other users. I was for lack of a better word PO&#8217;d at our fail whale. To remedy we looked at all our code we disabled all plugins that were not being used cleaned up some code, made some tweaks to PHP and it seemed to help. The following night during the next big spike (which had even more users) it responded OK but still not as fast as I would like it to be.</p>
<p>Why did this fail? We did load testing right?  I believe it is because our CLF theme/plugins are considerably more heavy than when we tested (there were a lot of code changes over the month). During the post crash testing we tested disabling and enabling  widgets and showed you can 2x the number of page requests your page can handle which is significant (I am not sure what widgets were enabled during the initial test the site was still being actively developed). Another culprit is Domain Mapping which is used on most of the websites on the service. Domain Mapping runs each time a page is hit even when the page is cached via Super-Cache (check this <a href="http://blogs.ubc.ca/scottmcmillan/files/2010/09/elearning_query_with_super_cache.txt">file</a> to see the query log of a hit to the cached page on elearning.ubc.ca) . Luckily we use MySQL Query cache so most of these would have been served from memory so it doesn&#8217;t change page requests/second by that much. But this really shows how much of a hog for resources WordPress can be if you let it and why you should do all the little things: </p>
<pre>
mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 11524    |
| Qcache_free_memory      | 36261544 |
| Qcache_hits             | 50840927 |
| Qcache_inserts          | 2040382  |
| Qcache_lowmem_prunes    | 113918   |
| Qcache_not_cached       | 1857166  |
| Qcache_queries_in_cache | 24673    |
| Qcache_total_blocks     | 64344    |
+-------------------------+----------+
8 rows in set (0.00 sec)
</pre>
<p>I hope we think more critically about features we add to higher traffic pages in the future and think more new school in web development. New school as in performance matters and little changes on the app level front end / back end code can help more than old school adding a whack of hardware (ironic because we are doing/did this&#8230; but I argue that is so we can do upgrades with less downtime not as much performance). </p>
<p>*I think FB, Google, Yahoo! really promote the new school style well I would say they started it. FB basically re-tooled PHP and contributed to APC this probably saves them tons of $cash by not adding  a boatload of new servers as well as make their users happy with faster response times. Yahoo! does a great job promoting <a href="http://developer.yahoo.com/performance/rules.html">front end</a> performance the same with Google&#8217;s <a href="http://code.google.com/speed/articles/">Let&#8217;s make the Web Faster</a>.  I like the way they think.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/09/13/i-love-ubc-it-vms-and-caching-because-your-not-caching-everything/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Makeover</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/08/30/database-makeover/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/08/30/database-makeover/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 23:05:41 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scaling]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=968</guid>
		<description><![CDATA[My brain is adjusting to being back to work after a computer less vacation so I will take this time to do a blog post on the database setup on UBC Blogs. Before a few weeks ago we had one &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/08/30/database-makeover/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My brain is adjusting to being back to work after a computer less vacation so I will take this time to do a blog post on the database setup on UBC Blogs.</p>
<p>Before a few weeks ago we had one server and things were ok&#8217;ish but we planned on adding the BP for September along with a shiny CWL login button so it meant a lot more users might jump on board&#8230; so we added a couple more  servers a database Master/Slave setup with a few more to come (another web and a cache).</p>
<p>But&#8230; before the Master/Slave we did database &#8220;partitioning&#8221;, what is this besides something that made me more than nervous for a fair amount? Well because WPMU creates around 8 database tables per blog overtime this will grow to a very large number of tables things start to get slow during backups (very slow actually would take 10-30 minutes  to do a backup, this is because it would have to lock up  a large number of tables 21k+) performance also begins to lag reportedly once you move past the 1000+ blog range, so we needed to move to a &#8220;Mulit-database&#8221; setup to be exact which basically involves blowing apart your database and enabling a Multi-DB plugin. *There are a few Multi-DB plugins: <a href="http://codex.wordpress.org/HyperDB">Hyper-DB</a> used by WordPress.com which is quite complicated and provides little to now help documentation or support. <a href="http://wordpress.org/extend/plugins/shardb/">SharDB</a> developed by Ron Rennick which is based on HyperDB and then there is Multi-DB which is developed by WPMU Premium Dev and used by <a href="http://edublogs.org/">Edublogs</a>&#8230; I decided to go with the Multi-DB *for now* first choice would have been SharDB because of the fact it&#8217;s based on HyperDB and it is a community plugin vs the &#8220;premium&#8221;  but there were issues once the database moved to it&#8217;s own server (connection/timeout errors) it worked beautifully on the same box but on it&#8217;s own a no go. Ron <a href="http://wpmututorials.com/plugins/shardb-3-0-1-update/#comment-10161">mentioned</a> this will be fixed in the future at which time I think we would switch.</p>
<p>Should be noted doing this step although nerve racking is relatively straight forward because of the great setup scripts that accompany both SharDB and Multi-DB and some great how to posts by <a href="http://bavatuesdays.com/wpmu-multi-db-tutorial/">Jim Groom</a> I was able to figure this out and test during a <a href="http://sakaiproject.org/">Sakai </a> presentation&#8230; implementation on the live took a fair amount of time approx 30 minutes (breaking 1 db into 256 dbs is slow). Once this was completed I have to say it felt faster (no empirical evidence) but doing things that were not so snappy prior like as an admin listing all users reported results much faster. I implemented the Master/Slave setup the following AM which is probably the coolest part because we have zero downtime with backups now and essentially a spare server&#8230; (if the master died we could flip to this quite easily). Here is how that was done *I am not a DBA like I said in the past so there maybe better ways but this seemed to work well so far*.</p>
<p>On the Master:<br />
the my.cnf contains these settings related to master slave:</p>
<pre>
# for master/slave
server-id=1
relay-log=/mnt/mysql_log/logs/mysql-relay-bin
relay-log-index=/mnt/mysql_log/logs/mysql-relay-bin.index
master-info-file=/mnt/mysql_log/logs/mysql-master.info
relay-log-info-file=/mnt/mysql_log/logs/mysql-relay-log.info

# Enable binary logging
log-bin=/mnt/mysql_log/binary_logs/blogsdb1-bin
#Expire the logs every three days
expire_logs_days=3
</pre>
<p>Create a slave user on the master:</p>
<pre>
mysql> GRANT REPLICATION SLAVE ON
 *.* to slave_user@'SLAVE_IP_ADDRESS'
 IDENTIFIED BY 'slave_pw';
</pre>
<p>Dump the master db and import into the slave.</p>
<p>On the Slave include this in your my.cnf:</p>
<pre>
# for master/slave
# changes made to do slave
server-id=2
relay-log=/mnt/mysql_log/logs/mysql-relay-bin
relay-log-index=/mnt/mysql_log/logs/mysql-relay-bin.index
master-info-file=/mnt/mysql_log/logs/mysql-master.info
relay-log-info-file=/mnt/mysql_log/logs/mysql-relay-log.info
</pre>
<pre>
mysql> CHANGE MASTER TO
MASTER_HOST='MASTER_IP_ADDRESS',
MASTER_USER='slave_user',
MASTER_PASSWORD='slave_pw';
</pre>
<p>Start the slave:</p>
<pre>
mysql> start slave;
</pre>
<p>Check the status of the slave:</p>
<pre>
mysql> show slave status\G
</pre>
<p>If things worked out you should see:</p>
<pre>
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
</pre>
<p>Try to run SHOW MASTER STATUS and SHOW SLAVE STATUS (quickly master first) you will see the Relay_Log_Pos will be the pretty much the same:</p>
<p>On master:</p>
<pre>
mysql> show master status\G ;
*************************** 1. row ***************************
File: blogsdb1-bin.000009
Position: 579567003
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
</pre>
<p>Exec_Master_Log_Pos should be close to the Position on master.</p>
<p>Now for backups just have your backup script run stop slave then dump and restart which gives no downtime for backups on production! Bloggers can post now at 3:00 am and not make passive aggressive tweets about blog DT.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/08/30/database-makeover/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Expire Headers! An easy way to speed up your website.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/06/22/expire-headers-an-easy-way-to-speed-up-your-website/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/06/22/expire-headers-an-easy-way-to-speed-up-your-website/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 22:14:39 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[performace]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=872</guid>
		<description><![CDATA[This is a another little tweak that can make your web pages faster and servers happier. Make sure you are using expires headers. I actually overlooked this one on our WordPress web servers, the tweak is a quick add if &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/06/22/expire-headers-an-easy-way-to-speed-up-your-website/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is a another little tweak that can make your web pages faster and servers happier. Make sure you are using expires headers. I actually overlooked this one on our WordPress web servers, the tweak is a quick add if you have  <a href="http://httpd.apache.org/docs/2.0/mod/mod_expires.html">mod_expires</a> installed  you can make things faster in seconds.</p>
<p>From the <a href="http://developer.yahoo.com/yslow/">YSlow</a> documentation:</p>
<blockquote><p>Web pages are becoming increasingly complex with more scripts, style sheets, images, and Flash on them. A first-time visit to a page may require several HTTP requests to load all the components. By using Expires headers these components become cacheable, which avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often associated with images, but they can and should be used on all page components including scripts, style sheets, and Flash.</p></blockquote>
<p>Tested with LEAP and with these 6 lines in your .htaccess (WP was having issues with the code reason why this is screened)</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/06/expires_headers.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/06/expires_headers.png" alt="" title="expires_headers" width="327" height="117" class="aligncenter size-full wp-image-884" /></a></p>
<p>The site went from a <a href="http://blogs.ubc.ca/scottmcmillan/files/2010/06/leap_before_headers.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/06/leap_before_headers.png" alt="" title="leap_before_expires_headers" width="278" height="42" class="aligncenter size-full wp-image-873" /></a></p>
<p>to a honor roll  A score in YSlow.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/06/leap_after_expire_headers_added.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/06/leap_after_expire_headers_added.png" alt="" title="leap_after_expire_headers_added" width="284" height="44" class="aligncenter size-full wp-image-875" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/06/22/expire-headers-an-easy-way-to-speed-up-your-website/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting the most out of MySQL</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/04/07/making-the-most-out-of-mysql/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/04/07/making-the-most-out-of-mysql/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 18:08:14 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=780</guid>
		<description><![CDATA[My Boss told me to focus on scaling&#8230; so I am writing a blog post on MySQL tuning/scaling. Right now we are I would say in phase one of our WordPress scaling process ie we have one server. Phase 2 &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/04/07/making-the-most-out-of-mysql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My Boss told me to focus on scaling&#8230; so I am writing a blog post on MySQL tuning/scaling. Right now we are I would say in phase one of our WordPress scaling process ie we have one server. Phase 2 would be two servers one web one db and partitioning the db. Phase 3 would be load balance two web and with two db servers one master one slave and add <a href="http://memcached.org/">Memcache</a>&#8230; after that well I doubt we would ever get there and even this would likely be overkill.</p>
<p>Phase one has involved minor scaling at the application / server level. We implemented PHP opcode caching with <a href="http://php.net/manual/en/book.apc.php">APC</a>, content caching using <a href="http://ocaoimh.ie/wp-super-cache/">Donncha O Caoimh&#8217;s</a> kick ass <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP-Super-Cache</a> and implemented some MySQL tuning techniques (what this post will be about). </p>
<p><strong>Our Server</strong></p>
<p>We have used a relatively modest server spec for the first two years 2 GB of RAM, 1 Intel(R) Xeon(R) CPU  E5440  @ 2.83GHz with a 48GB SAN mount. This has seemed to work fine for the most part with almost 2000 users to date (these 2000 users are rarely writing to the DB  95% reads the main reason why this has been working) and modest traffic according to Webalizer averaging around 1.8 million page view/month.  About a month ago  the IT VM gods granted us an extra 2GB of ram  bumping the total to 4GB which meant I could a little more MySQL tuning (you can&#8217;t really tune with  minimal  memory, with 2GB we were doing only query caching).  </p>
<p><strong>Warning</strong></p>
<p>*Before I start,  this tuning worked for the UBC Blogs setup  you should not implement this unless you take the time to understand MySQL and each of the settings your are changing and also keep an eye on your app after implementing (CPU usage, response time etc). I am by no means a MySQL DBA (I worked with real  whip smart DBA&#8217;s at the Bioinformatics Centre in the past I know what they are like and I frankly do not have the DB passion to memorize every error code, command,  and the skills to model  DB&#8217;s to handle multiple genomes  etc.(real DBA stuff) but I have been using maintaining  MySQL and building  web apps based of the LAMP stack  since 1999 (I am old) so I think I know enough to be get the work done (or enough to be dangerous) *.</p>
<p>So here are the tweaks that I found to work remember mileage may vary.</p>
<p><strong>Before</strong></p>
<p>Before you you begin tuning use some sort of  tuning script to give you an idea of what&#8217;s going on under the hood. I used the <a href="http://mysqltuner.pl/mysqltuner.pl">mysqltuner.pl</a> which is kind of old school so some of the recommends are not relevant but it gives you a good picture of what is going on. There are probably better ones out there but this has been in my toolbox for awhile.</p>
<p>Here is what it told me:<br />
<code><br />
-------- Performance Metrics -------------------------------------------------<br />
[--] Up for: 24d 17h 31m 13s (58M q [27.337 qps], 1M conn, TX: 2B, RX: 499M)<br />
[--] Reads / Writes: 93% / 7%<br />
[--] Total buffers: 59.0M global + 2.7M per thread (100 max threads)<br />
[OK] Maximum possible memory usage: 327.7M (16% of installed RAM)<br />
[OK] Slow queries: 0% (2K/58M)<br />
[!!] Highest connection usage: 100%  (101/100)<br />
[OK] Key buffer size / total MyISAM indexes: 8.0M/80.5M<br />
[OK] Key buffer hit rate: 95.6% (384M cached / 16M reads)<br />
[OK] Query cache efficiency: 54.1% (26M cached / 49M selects)<br />
[!!] Query cache prunes per day: 379131<br />
[OK] Sorts requiring temporary tables: 0% (1K temp sorts / 4M sorts)<br />
[!!] Temporary tables created on disk: 40% (3M on disk / 9M total)<br />
[!!] Thread cache is disabled<br />
[!!] Table cache hit rate: 0% (64 open / 3M opened)<br />
[OK] Open file limit used: 0% (128/24K)<br />
[OK] Table locks acquired immediately: 99% (30M immediate / 30M locks)<br />
</code><br />
<code><br />
-------- Recommendations -----------------------------------------------------<br />
General recommendations:<br />
    Add skip-innodb to MySQL configuration to disable InnoDB<br />
    Add skip-bdb to MySQL configuration to disable BDB<br />
    Run OPTIMIZE TABLE to defragment tables for better performance<br />
    Enable the slow query log to troubleshoot bad queries<br />
    Reduce or eliminate persistent connections to reduce connection usage<br />
    When making adjustments, make tmp_table_size/max_heap_table_size equal<br />
    Reduce your SELECT DISTINCT queries without LIMIT clauses<br />
    Set thread_cache_size to 4 as a starting value<br />
    Increase table_cache gradually to avoid file descriptor limits<br />
Variables to adjust:<br />
    max_connections (> 100)<br />
    wait_timeout (< 28800)<br />
    interactive_timeout (< 28800)<br />
    query_cache_size (> 25M)<br />
    tmp_table_size (> 32M)<br />
    max_heap_table_size (> 16M)<br />
    thread_cache_size (start at 4)<br />
    table_cache (> 64)</p>
<p></code></p>
<p>So some of the stuff is not useful as I said some is. I will go thought what I changed based on the recommends.</p>
<p><strong>Optimize Tables</strong></p>
<p>No brainer you have to do this every now and then. Pretty much the same as defragging your disk file system, it&#8217;s also important to do the same thing with MySQL data tables. If you don&#8217;t you may end up with slow or corrupted tables over time.</p>
<p>*I read on a blog post once someone wrote a php script to loop through all their databases and optimize the tables, that is a perfectly good waste of coffee drinkin&#8217; time! Let MySQL do the work for you!</p>
<p>run this command:<br />
<code><br />
mysqlcheck -u root -p --auto-repair --check --optimize --all-databases<br />
</code></p>
<p>*Note run this in off hours it does slow things down because it locks tables and if you have a large WPMU there will be a lot of MySQL tables to lock so it will take some time.</p>
<p><strong>Query Caching</strong></p>
<p>Like I said we were doing this in the past now with a little more RAM we could bump it up.<br />
* Too much here is not a good thing the max recommended  is 512MB .</p>
<p>From MySQL: &#8220;<a href="http://dev.mysql.com/tech-resources/articles/mysql-query-cache.html">A Practical Look at the MySQL Query Cache</a>&#8221; &#8211; </p>
<blockquote><p>
The MySQL query cache provides substantial benefits over other database engine caching strategies because not only is the overhead of hard parsing for identical queries avoided, but the sometimes very high overhead of recreating complex result sets from either disk or memory caches is averted as well, greatly lessening both physical and logical I/O. The end results are extremely fast response times for business applications (data warehouses, BI applications, Web applications, OLTP systems, etc.) where end user clients are repetitively executing the same MySQL queries.
</p></blockquote>
<p>I bumped up the query_cache_size up to 128M which has captured a lot of queries that would normally go to disk this is represented by the Qcache_hits 31758409 and is storing a fair amount of queries in memory as well with Qcache_queries_in_cache at 26371 .</p>
<p><code><br />
mysql> SHOW GLOBAL STATUS LIKE '%qcache%';<br />
+-------------------------+----------+<br />
| Variable_name           | Value    |<br />
+-------------------------+----------+<br />
| Qcache_free_blocks      | 9566     |<br />
| Qcache_free_memory      | 28278048 |<br />
| Qcache_hits             | 31758409 |<br />
| Qcache_inserts          | 10434728 |<br />
| Qcache_lowmem_prunes    | 3865108  |<br />
| Qcache_not_cached       | 2203713  |<br />
| Qcache_queries_in_cache | 26371    |<br />
| Qcache_total_blocks     | 68193    |<br />
+-------------------------+----------+<br />
8 rows in set (0.00 sec)</p>
<p></code></p>
<p><strong>Thread Cache Size</strong></p>
<p>This was at the default which was 0 which is bad because this affects the thread cache rate. </p>
<p>Thread_cache_size determines how many threads MySQL will hold open in memory to handle new connections. The hit rate should be as close to 100% as possible. You can calculate your hit ratio by dividing the &#8216;threads_created&#8217; status variable by the &#8216;connections&#8217; status variable:<br />
<code><br />
100 - ((Threads_created / Connections) * 100)<br />
</code><br />
For UBC Blogs the thread cache rate was:</p>
<p>100 &#8211; ((1629684  / 1629684  ) * 100) = 0% == very bad. This is because the thread_cache_size was set to the default 0. MySQL was basically holding 0 threads in cache so it was forced to create new threads all the time.</p>
<p>I set the thread_cache_size to 16 to see if it helps (* You should start at a low value and move up).</p>
<p>Checking after a ~ couple weeks of running<br />
<code><br />
mysql> SHOW GLOBAL STATUS LIKE 'Connections';<br />
+---------------+---------+<br />
| Variable_name | Value   |<br />
+---------------+---------+<br />
| Connections   | 1315861 |<br />
+---------------+---------+<br />
1 row in set (0.00 sec)<br />
</code></p>
<p><code><br />
mysql> SHOW GLOBAL STATUS LIKE 'Threads_created';<br />
+-----------------+-------+<br />
| Variable_name   | Value |<br />
+-----------------+-------+<br />
| Threads_created | 3057  |<br />
+-----------------+-------+<br />
1 row in set (0.00 sec)<br />
</code></p>
<p>Now doing the calculation again:</p>
<p>100 &#8211; ((3057 / 1315861  ) * 100 ) =  99.76% which is a huge improvement.</p>
<p><strong>Table cache</strong></p>
<p>Every time MySQL accesses a table, it places it in the cache. If the application accesses many tables like WordPress MU, it is faster to have more of these in the cache.  </p>
<p>We had it set to the default 64.<br />
<code><br />
mysql> SHOW GLOBAL STATUS LIKE 'Opened_tables';<br />
+---------------+---------+<br />
| Variable_name | Value   |<br />
+---------------+---------+<br />
| Opened_tables | 3948355 |<br />
+---------------+---------+<br />
1 row in set (0.00 sec)<br />
</code><br />
30 minutes later:<br />
<code><br />
mysql> SHOW GLOBAL STATUS LIKE 'Opened_tables';<br />
+---------------+---------+<br />
| Variable_name | Value   |<br />
+---------------+---------+<br />
| Opened_tables | 3955277 |<br />
+---------------+---------<br />
</code><br />
You can see the number go up and up. Increasing the table cache size will help a lot I doubled this to 128 to start will see how it works out.</p>
<p><strong>Key buffer size </strong></p>
<p>From <a href="http://dev.mysql.com/doc/refman/4.1/en/server-system-variables.html#sysvar_key_buffer_size">MySQL</a>:</p>
<blockquote><p>
You can increase the value to get better index handling for all reads and multiple writes; on a system whose primary function is to run MySQL using the MyISAM storage engine, 25% of the machine&#8217;s total memory is an acceptable value for this variable. However, you should be aware that, if you make the value too large (for example, more than 50% of the machine&#8217;s total memory), your system might start to page and become extremely slow.<br />
You can increase the value to get better index handling for all reads and multiple writes; on a system whose primary function is to run MySQL using the MyISAM storage engine, 25% of the machine&#8217;s total memory is an acceptable value for this variable. However, you should be aware that, if you make the value too large (for example, more than 50% of the machine&#8217;s total memory), your system might start to page and become extremely slow.</p>
<p>The Key_reads/Key_read_requests ratio should normally be less than 0.01. The Key_writes/Key_write_requests ratio is usually near 1 if you are using mostly updates and deletes, but might be much smaller if you tend to do updates that affect many rows at the same time or if you are using the DELAY_KEY_WRITE table option.
</p></blockquote>
<p>Here is what we were getting:<br />
<code><br />
mysql> SHOW STATUS LIKE 'Key_%';<br />
+------------------------+-----------+<br />
| Variable_name          | Value     |<br />
+------------------------+-----------+<br />
| Key_blocks_not_flushed | 0         |<br />
| Key_blocks_unused      | 6405      |<br />
| Key_blocks_used        | 3166      |<br />
| Key_read_requests      | 386078455 |<br />
| Key_reads              | 16844790  |<br />
| Key_write_requests     | 3127706   |<br />
| Key_writes             | 1148023   |<br />
+------------------------+-----------+<br />
7 rows in set (0.00 sec)<br />
</code><br />
key_read / key_reads_requests<br />
Ours is over 4.36 which is not so good.  </p>
<p>key_write  / key_writes_requests = 0.36 </p>
<p>The default key_buffer is  64Mb moved  this up to 128MB to start.</p>
<p>A  month  later checking:</p>
<p><code><br />
mysql> SHOW STATUS LIKE 'Key_%';<br />
+------------------------+-----------+<br />
| Variable_name          | Value     |<br />
+------------------------+-----------+<br />
| Key_blocks_not_flushed | 0         |<br />
| Key_blocks_unused      | 5994      |<br />
| Key_blocks_used        | 4059      |<br />
| Key_read_requests      | 311890660 |<br />
| Key_reads              | 15189451  |<br />
| Key_write_requests     | 3943721   |<br />
| Key_writes             | 1743544   |<br />
+------------------------+-----------+<br />
7 rows in set (0.00 sec)<br />
</code></p>
<p>key_read / key_reads_requests<br />
Ours is over 4.87  which is not  good  even after moving up to 128MB,   until we move to a dedicated MySQL server 128MB is the max we can set it at  to be on the safe side.  I think the fact this is off  maybe due to the fact that there is a huge number of tables in a WordPress MU install with a significant number of users.</p>
<p>key_write  / key_writes_requests = 0.44  up a bit.</p>
<p>That is it for now.</p>
<p><strong>Benchmarking</strong></p>
<p>Doing a Apache Bench web load test before and after with a search on the UBC Blogs homepage we get:</p>
<p>AB Testing a dynamic page **before** upgrade</p>
<p><code><br />
[scott@rab ~]$ ab -n 1000 -c 100 http://blogs.ubc.ca/?s=outage<br />
</code><br />
<code><br />
Concurrency Level:      100<br />
Time taken for tests:   4.350686 seconds<br />
Complete requests:      1000<br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      16953480 bytes<br />
HTML transferred:       16544000 bytes<br />
Requests per second:    229.85 [#/sec] (mean)<br />
Time per request:       435.069 [ms] (mean)<br />
Time per request:       4.351 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          3805.38 [Kbytes/sec] received<br />
</code></p>
<p>same page after adding the RAM and tuning</p>
<p><code><br />
[scott@rab ~]$ ab -n 1000 -c 100 http://blogs.ubc.ca/?s=outage<br />
</code><br />
<code><br />
Concurrency Level:      100<br />
Time taken for tests:   2.144289 seconds<br />
Complete requests:      1000<br />
Failed requests:        0<br />
Write errors:           0<br />
Total transferred:      16953000 bytes<br />
HTML transferred:       16544000 bytes<br />
Requests per second:    466.36 [#/sec] (mean)<br />
Time per request:       214.429 [ms] (mean)<br />
Time per request:       2.144 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          7720.51 [Kbytes/sec] received<br />
</code></p>
<p>You can see the Time per request was cut in half shows what some extra RAM and a little MySQL tuning can speed things up <img src='http://blogs.ubc.ca/scottmcmillan/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   mostly the RAM helped in this case&#8230;</p>
<p>Still more to do but on the right track.  MySQL and databases in general are not really out the box get up and go ready, you have to do some tuning to get the most  out of the install and tweak for your app, all part of the fun I guess&#8230; </p>
<p>I recommend skimming through:  &#8220;<a href=" http://www.amazon.ca/High-Performance-MySQL-Optimization-Replication/dp/0596101716">High Performance MySQL: Optimization, Backups, Replication, and More</a>&#8221;  contains some useful stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/04/07/making-the-most-out-of-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>400!</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/03/04/400/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/03/04/400/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 23:55:02 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=765</guid>
		<description><![CDATA[Hard to believe we passed 400+ commits to our blogs and sites SVN already. Great work Michael, Enej, Pan and to all the students Andre, Alex, Vince, Godfrey who contributed code you rock.]]></description>
			<content:encoded><![CDATA[<p>Hard to believe we passed 400+ commits to our blogs and sites SVN already.  Great work Michael, Enej,  Pan and to all the  students Andre, Alex, Vince, Godfrey  who contributed code you rock.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/03/4001.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/03/4001.png" alt="400" title="400" width="550" height="349" class="aligncenter size-full wp-image-767" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/03/04/400/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Positive response.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/03/02/positive-response/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/03/02/positive-response/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 23:11:45 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=750</guid>
		<description><![CDATA[I love our Pingdom account it&#8217;s great for monitoring performance and notifying of you if there are server problems. This is an interesting graphic from Pingdom our response times have dropped in half since Jan 27, 2010 . There could &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/03/02/positive-response/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I love our<a href="http://pingdom.com"> Pingdom</a> account it&#8217;s great for monitoring performance and notifying of you if there are server problems. </p>
<p>This is an interesting graphic from Pingdom  our response times have dropped in half since  Jan 27, 2010 . There could be many contributing factors network activity, server load etc for this.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/03/response_time.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/03/response_time.png" alt="response_time" title="response_time" width="629" height="301" class="aligncenter size-full wp-image-751" /></a></p>
<p>I think the real reason was we dropped some mu plugins on that date:</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/03/poistive_commits.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/03/poistive_commits.png" alt="poistive_commits" title="poistive_commits" width="474" height="76" class="aligncenter size-full wp-image-752" /></a></p>
<p>WPMU-Topposts was a total hog. I noticed a drop in CPU use immediately upon removing. It was basically writing to the db every time a page was opened and sorting several million records to determine which blog was popular, a cool feature on the homepage to show the most popular blogs but who cares if it is making the server sluggish&#8230; </p>
<p>Or it could have been a magical network change, who knows as long as the curve  is  not going up that quickly I am happy.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/03/02/positive-response/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Blog, blog, blog, blogs, Sites! In WordPress 3.0 blogs are sites Finally!</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/02/19/blog-blog-blog-blogs-sites-in-wordpress-3-0-blogs-are-sites-finally/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/02/19/blog-blog-blog-blogs-sites-in-wordpress-3-0-blogs-are-sites-finally/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 18:44:20 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=731</guid>
		<description><![CDATA[I have heard the word blog several thousand times in the last 2 years. Sometimes it seems like several hundred times in a meeting if Novak is there. Now with the upcoming WordPress 3.0 blogs will be referred to as &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/02/19/blog-blog-blog-blogs-sites-in-wordpress-3-0-blogs-are-sites-finally/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have heard the word blog several thousand times in the last 2 years. Sometimes it seems like several hundred times in a meeting if Novak is there.</p>
<p>Now with the upcoming WordPress 3.0 blogs will be referred to as sites! Although just a word I really like the change, WordPress is much more than a blog platform it can be used as a CMS, portfolio, lightweight LMS (from what I hear&#8230;), news magazine etc.  The name change will answer the &#8220;I thought WordPress was for blogging&#8221;&#8230; </p>
<p>I guess In the future I will not  be a &#8220;Site Admin&#8221; but a &#8220;Network Admin&#8221; just don&#8217;t ask me to debug your Cisco router <img src='http://blogs.ubc.ca/scottmcmillan/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  </p>
<p><strong>WordPress 3.0</strong><br />
<a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/network_.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/network_.png" alt="network_" title="network_" width="164" height="118" class="aligncenter size-full wp-image-732" /></a></p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/dashboard_3.0.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/dashboard_3.0.png" alt="dashboard_3.0" title="dashboard_3.0" width="160" height="85" class="aligncenter size-full wp-image-734" /></a></p>
<p><strong>**We better have a meeting about this to discuss how to best inform all users because it will be very confusing to them and many will think their blogs disappeared.**</strong> (I am joking but in reality it seems as if academic users are not the most adaptive users out there). </p>
<p>Also new in 3.0 is the default theme Twenty Ten, much more flexible and clean, with most users using the default theme this is a good thing.  Things I wish it also included:</p>
<ul>
<li>Font Choice</li>
<li>Color Selection</li>
<li>Column  Layout  Choices</li>
<li>**Custom CSS upload**</li>
</ul>
<p>With those options that would satisfy 95% of user needs on our system. </p>
<p>Here is a screenshot of the default theme Twenty Ten  with a custom background and header image. Super patriotic Eh!</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/2010_theme.jpg"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/2010_theme.jpg" alt="2010_theme" title="2010_theme" width="550" height="398" class="aligncenter size-full wp-image-737" /></a></p>
<p>Here is the video in the screen because it is cool.</p>
<p><object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/BSXVv80XXDQ&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/BSXVv80XXDQ&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/02/19/blog-blog-blog-blogs-sites-in-wordpress-3-0-blogs-are-sites-finally/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Performance Testing with Google Speed Tracer</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/02/17/performance-testing-with-google-speed-tracer/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/02/17/performance-testing-with-google-speed-tracer/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 19:21:32 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=705</guid>
		<description><![CDATA[Google released a new performance inspection tool for Chrome today called Speed Tracer and I am impressed. It is very similar to the Web Inspector profiling but with an additional slick timeline feature. Googles description of the tool: Speed Tracer &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/02/17/performance-testing-with-google-speed-tracer/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Google released a new performance inspection tool for Chrome today called <a href="http://code.google.com/webtoolkit/speedtracer/">Speed Tracer</a> and I am impressed. It is very similar to the <a href="http://trac.webkit.org/wiki/WebInspector">Web Inspector</a> profiling  but with an additional  slick timeline feature. </p>
<p>Googles description of the tool:</p>
<blockquote><p>Speed Tracer is a tool to help you identify and fix performance problems in your web applications. It visualizes metrics that are taken from low level instrumentation points inside of the browser and analyzes them as your application runs. Speed Tracer is available as a Chrome extension and works on all platforms where extensions are currently supported (Windows and Linux).</p>
<p>Using Speed Tracer you are able to get a better picture of where time is being spent in your application. This includes problems caused by JavaScript parsing and execution, layout, CSS style recalculation and selector matching, DOM event handling, network resource loading, timer fires, XMLHttpRequest callbacks, painting, and more.</p></blockquote>
<p><em>**It is supported for OSX as well they need to update the description**</em><strong></p>
<p></strong><strong>Example usage:</strong></p>
<p>Using <a href="http://leap.ubc.ca">LEAP</a> as an example again because it is a total pig of a site, we can see where Speed Tracer picks up the sluggishness. </p>
<p>Sluggishness is designated by events taking longer than 100ms which is generally when latency is noticed. Starting at 3.13s we had one of these events on the LEAP homepage.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/speed_trace_leap_home_page.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/speed_trace_leap_home_page.png" alt="speed_trace_leap_home_page" title="speed_trace_leap_home_page" width="550" height="447" class="aligncenter size-full wp-image-706" /></a></p>
<p>Looking at the Network activity for that range you can see we have some calls to  Facebook and Google Analytics which are slowing things down.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/speed_trace_netowork_activity.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/speed_trace_netowork_activity.png" alt="speed_trace_netowork_activity" title="speed_trace_netowork_activity" width="550" height="307" class="aligncenter size-full wp-image-707" /></a></p>
<p>I love tools like this because they are great for answering the &#8220;Why is my blog so slow?&#8221; If the user is blaming the server (and you know it is not the server) and know it&#8217;s their  shoddy web design send them some screen shots from Speed Tracer showing them their bottle necks.</p>
<p><strong>Google Speed Tracer Intro:</strong></p>
<p><object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/Sn_3rJaexKc&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Sn_3rJaexKc&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/02/17/performance-testing-with-google-speed-tracer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Holy HTTP requests! Our WordPress themes and plugins are HTTP hogs.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2010/02/03/holy-http-requests-our-wordpress-themes-and-plugins-are-http-hogs/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2010/02/03/holy-http-requests-our-wordpress-themes-and-plugins-are-http-hogs/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 21:56:57 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=644</guid>
		<description><![CDATA[This was inspired by todays post on WPMU.org with regards to WP-Minify . About WP-Minify: WP Minify intercepts scripts and style printing at the ‘wp_print_scripts’ and ‘wp_print_styles’ hook. WP Minify grabs these files in the proper order (minding dependencies) and &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2010/02/03/holy-http-requests-our-wordpress-themes-and-plugins-are-http-hogs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This was inspired by todays <a href="http://wpmu.org/speed-up-your-wordpress-buddypress-loading-time-with-this-quick-tip/">post</a> on WPMU.org with regards to <a href="http://wordpress.org/extend/plugins/wp-minify/">WP-Minify</a> .  </p>
<p>About WP-Minify:</p>
<blockquote><p>WP Minify intercepts scripts and style printing at the ‘wp_print_scripts’ and ‘wp_print_styles’ hook. WP Minify grabs these files in the proper order (minding dependencies) and passes that list to the Minify engine. The Minify engine then returns a consolidated, minified, and compressed script or style. WP Minify then references this compressed script or style in the WordPress header instead of each individual scripts/styles.</p></blockquote>
<p>The way most themes and plugins are developed has always bugged me so I was happy to see this plugin released.  Most WordPress sites have   way to many HTTP requests,  if you are going to be hosting a large number blogs/sites you have to start to think about details like this.  For example  say you have 500 sites on your system and the sites use the same set of plugins and each site is averaging 200 unique visitors/day with an average of 20 HTTP requests to JS and CSS files that is  1+ million HTTP requests (I am using the assumption that all users have a browser cache enabled or else it could be more). This could be greatly reduced in many cases using a plugin like WP-Minify . </p>
<p>I decided to take a poke at checking HTTP requests to LEAP on verf,   LEAP was developed with the <a href="http://themehybrid.com/">HyBrid</a> theme  and uses around a  dozen plugins. I used <a href="http://developer.yahoo.com/yslow/">Yslow</a> and <a href="http://trac.webkit.org/wiki/WebInspector">Web Inspector</a>  to check HTTP requests and load times. </p>
<p><strong>Before Minify</strong> </p>
<p><strong>HTTP Requests</strong></p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/http_requests_before_minify.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/http_requests_before_minify.png" alt="http_requests_before_minify" title="http_requests_before_minify" width="446" height="256" class="aligncenter size-full wp-image-678" /></a></p>
<p><strong>Load time before Minify</strong></p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_load_time_before_minify.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_load_time_before_minify.png" alt="leap_verf_load_time_before_minify" title="leap_verf_load_time_before_minify" width="504" height="69" class="aligncenter size-full wp-image-646" /></a></p>
<p><strong>After Minify with  empty cache</strong></p>
<p><strong>HTTP Requests</strong></p>
<p>*still high (using the default setting) with WP-Minify you can go in and add files that are not being picked up. You can see a big  reduction  in JS HTTP request calls. **LEAP may not be the best site to use as an example because of the calls to 3rd parties.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_http_requests_empty_cache_after.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_http_requests_empty_cache_after.png" alt="leap_verf_http_requests_empty_cache_after" title="leap_verf_http_requests_empty_cache_after" width="431" height="250" class="aligncenter size-full wp-image-677" /></a></p>
<p><strong>Load time after Minify</strong></p>
<p>Almost cut in half! Over half as many HTTP requests for JS files is the key. </p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_response_time_after_minify.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2010/02/leap_verf_response_time_after_minify.png" alt="leap_verf_response_time_after_minify" title="leap_verf_response_time_after_minify" width="515" height="81" class="aligncenter size-full wp-image-674" /></a></p>
<p>From the Yahoo! Developer Performance <a href="http://developer.yahoo.com/performance/rules.html#num_http">rules</a>:</p>
<blockquote><p>Reducing the number of HTTP requests in your page is the place to start. This is the most important guideline for improving performance for first time visitors. As described in Tenni Theurer&#8217;s blog post <a href="http://yuiblog.com/blog/2007/01/04/performance-research-part-2/">Browser Cache Usage &#8211; Exposed!</a> , 40-60% of daily visitors to your site come in with an empty cache. Making your page fast for these first time visitors is key to a better user experience.</p></blockquote>
<p>It would be great is something like WP-Minify was included in the WordPress core but until then this plugin is a great start. Would also help if plugin and theme developers did not include redundant JS in their plugins that already exists in the core! </p>
<p>We will be taking a closer look at WP-Minify and hopefully roll it out to all the sites on blogs@ubc and the CMS hosting service.</p>
<p>Time to step it up and help make the web a faster place!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2010/02/03/holy-http-requests-our-wordpress-themes-and-plugins-are-http-hogs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redirecting pages in WordPress</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/12/15/redirecting-pages-in-wordpress/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/12/15/redirecting-pages-in-wordpress/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 20:15:24 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=607</guid>
		<description><![CDATA[Have you ever tried to redirect over a 150 URLs to their new locations? That was a challenge faced with the launch of the new OLT website. After Michael tortured himself trying to write mod_rewrite rules to match the conditions &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/12/15/redirecting-pages-in-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Have you ever tried to redirect over a 150 URLs to their new locations? That was a challenge faced with the launch of the new OLT website.</p>
<p>After Michael tortured himself trying to write mod_rewrite rules to match the conditions along with writing a custom 404 redirect I decided to do a Google &#8220;WordPress Redirection&#8221; and low and behold <a href=" http://wordpress.org/extend/plugins/redirection/">Redirection</a> a little rockstar of a plugin popped up first hit. This plugin has pretty much every feature you would need 301, pass through abilities, logging (great to see who is linking to the old pages still) and CSV bulk import (which was super useful because Michael had all the links in a spreadsheet), .htaccess rule export&#8230;</p>
<p>**This is a good lesson to all developers, somebody has probably done what you are going to start work on so do a search first especially when working with WordPress!</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/12/redirections.png"><img class="aligncenter size-medium wp-image-609" title="redirections" src="http://blogs.ubc.ca/scottmcmillan/files/2009/12/redirections-300x130.png" alt="redirections" width="300" height="130" /></a></p>
<p>I give this plugin 5 stars not a sexy plugin but very useful for  those moving an old website to WP. Probably worth adding some bills into the developers PayPal account.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/12/15/redirecting-pages-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changing the MediaWiki edit warning</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/12/11/changing-the-harsh-mediawiki-edit-warning/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/12/11/changing-the-harsh-mediawiki-edit-warning/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 22:49:10 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=599</guid>
		<description><![CDATA[This was brought to my attention by Jeff Miller. MediaWiki uses some harsh default Terms of Service warning text on the Edit page which to be honest I never noticed but I do understand how it might sketch out a &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/12/11/changing-the-harsh-mediawiki-edit-warning/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This was brought to my attention by <a href="http://twitter.com/tzeffmiller">Jeff Miller</a>. MediaWiki uses some harsh default Terms of Service warning text on the Edit page which  to be honest I never noticed  but I do understand how it might sketch out a user taking the plunge into the open wiki world:</p>
<blockquote><p>
Please note that all contributions to UBC Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here. You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see UBC Wiki:Copyrights for details). Do not submit copyrighted work without permission!</p></blockquote>
<p>To change this text go to MediaWiki:Copyrightwarning2 and edit the text. We removed the &#8220;mercilessly&#8221; better would be adding a Copyright notice like Wikipedia <img src='http://blogs.ubc.ca/scottmcmillan/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  which we do not use&#8230; </p>
<blockquote><p>Content that violates any copyrights will be deleted. Encyclopedic content must be verifiable. You irrevocably agree to release your contributions under the  CC-BY-SA 3.0 License and the GFDL. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license. See the Terms of Use for details. </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/12/11/changing-the-harsh-mediawiki-edit-warning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Delete old revisions in MediaWiki</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/12/11/delete-old-revisions-in-mediawiki/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/12/11/delete-old-revisions-in-mediawiki/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 21:35:16 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[MediaWiki]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=588</guid>
		<description><![CDATA[A course instructor just asked if he could delete revision histories so he could reuse group project pages in his wiki without exposing the previous history to the next group of users. Generally deleting anything in a MediaWiki is quite &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/12/11/delete-old-revisions-in-mediawiki/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A course instructor just asked if he could delete revision histories so he could reuse group project pages in his wiki without exposing the previous history to the next group of users. Generally deleting anything in a MediaWiki is quite difficult,  I knew this may have been possible   via a command line maintenance script <a href="http://www.mediawiki.org/wiki/Manual:DeleteOldRevisions.php">DeleteOldRevisions.php </a> but this was not the greatest solution (who wants to be bothered each term to run this) after a Google found this great extension <a href="http://www.mediawiki.org/wiki/Extension:SpecialDeleteOldRevisions2">SpecialDeleteOldRevisions2</a> which did the trick and then some .  Allows wild card revision deletes along with date range revision deletes. Very handy for any stand alone course wiki installs.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/12/delete_old_mediawiki_revisions.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/12/delete_old_mediawiki_revisions-300x155.png" alt="delete old mediawiki revisions" title="delete old mediawiki revisions" width="300" height="155" class="aligncenter size-medium wp-image-592" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/12/11/delete-old-revisions-in-mediawiki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Direct upload to YouTube through MediaWiki</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/12/08/direct-upload-to-youtube-through-mediawiki/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/12/08/direct-upload-to-youtube-through-mediawiki/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 20:54:02 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[MediaWiki]]></category>
		<category><![CDATA[YouTube]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=576</guid>
		<description><![CDATA[Might be of interest for those who want to get more content into their YouTube EDU account. We have have been experimenting with ways to get content into YouTube from a single app with a trusted user base. So that &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/12/08/direct-upload-to-youtube-through-mediawiki/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Might be of interest for those who want to get more content into their YouTube EDU account.</p>
<p>We have have been experimenting with ways to get content into YouTube from a single app with a trusted user base. So that meant either MediaWiki or WordPress (only two apps we have with CWL right now). WordPress was the first choice but there was nothing out there, eventually found this great little extension from Travis Derouin of <a href="http://www.wikihow.com">http://www.wikihow.com</a> called <a href="http://www.mediawiki.org/wiki/Extension:YouTubeAuthSub ">YouTubeAuthSub</a> which takes advantage of the YouTube AuthSub/ClientLogin features. </p>
<p>After quite a few email exchanges with Travis I managed to get it working (discovered someone mangled the SVN on MediaWiki.org hosting his extension without his knowledge)  ended up finding a working copy from the Wikia SVN in the mean time&#8230;  </p>
<p><strong>Recommends</strong></p>
<p>You probably do not want all users in your wiki to access this extension so I recommend creating a YouTube group on your wiki install and assigning users to that group through the Special:UserRights . To add a group to MediaWiki  add something like this to your LocalSettings.php:</p>
<p><code><br />
## YouTube Namespace<br />
define("NS_YOUTUBE", 116);<br />
define("NS_YOUTUBE_TALK", 117);</p>
<p>$wgExtraNamespaces[NS_YOUTUBE] = "YouTube";<br />
$wgExtraNamespaces[NS_YOUTUBE_TALK] = "YouTube_talk";</p>
<p>## Subpages has to be enabled explictly.<br />
$wgNamespacesWithSubpages[NS_YOUTUBE] = false;<br />
$wgNamespacesWithSubpages[NS_YOUTUBE_TALK] = false;</p>
<p>$wgContentNamespaces[] = NS_YOUTUBE;<br />
</code></p>
<p>You will also need to add this to the extension YouTubeAuthSub/YouTubeAuthSub_body.php  after the $this->setHeaders(); in the function execute()</p>
<p><code><br />
# Check permissions<br />
                /// OLT BEGIN ///<br />
                // Make sure the user is in the youtube OR  sysop group<br />
                $isYouTubeEduGroup = ( in_array('youtube', $wgUser->getGroups()) || in_array('sysop', $wgUser->getGroups()) );<br />
                if(!$isYouTubeEduGroup ) {</p>
<p>                        if( !$wgUser->isLoggedIn() ) {<br />
                                $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' );<br />
                        }else{<br />
                                if(!$isYouTubeEduGroup){<br />
                                        $wgOut->showErrorPage( 'badaccess', 'badaccess-groups', $result = array('YouTube') );<br />
                                }<br />
                        }<br />
                        return;<br />
                }<br />
                /// OLT END ///</p>
<p></code></p>
<p><strong>Possible Bugs</strong></p>
<p>We recently had issues with some accounts because of a change in the YouTube API which they did not warn users against! They basically decided to add &#8220;=&#8221; into some of the tokens. The original code used a split() to extract tokens so this broke. I recommend doing something really ugly like this to avoid failed tokens if you are having issues (for some reason not all accounts have issues). </p>
<p>Look for the foreach ($lines as $line) { in the YouTubeAuthSub_body.php and add and comment the following:</p>
<p><code><br />
                                      /// OLT BEGIN ///<br />
                                        // Check if string contains Auth<br />
                                        $authPat = '/^Auth/';<br />
                                        preg_match($authPat,$line,$authMatch);<br />
                                        if(!empty($authMatch)){<br />
                                          $token = substr($line, 5);<br />
                                          var_dump($token);<br />
                                        }</p>
<p>                                        // Check if string contains YouTubeUser<br />
                                        $userPat = '/^YouTubeUser/';<br />
                                        preg_match($userPat,$line,$userMatch);<br />
                                        if(!empty($userMatch)) {<br />
                                          $YouTubeUser = substr($line, 12);<br />
                                        }</p>
<p>                                        /// OLT END ///</p>
<p>                                        /**<br />
                                         ** This does not work. YouTube API decided to add = into token strings so split breaks.</p>
<p>                                        $params = split("=", $line);</p>
<p>                                        switch ($params[0]) {<br />
                                                case "Auth":<br />
                                                $token = $params[1];<br />
                                                var_dump($token);<br />
                                                break;<br />
                                                case "YouTubeUser":<br />
                                                $YouTubeUser = $params[1];<br />
                                                break;<br />
                                        }</p>
<p>                                        **/</p>
<p></code></p>
<p>Other change YouTube change the client login URL look for the:<br />
<code><br />
$result = wfSpecialYouTubePost("https://www.google.com/youtube/accounts/ClientLogin?"<br />
</code><br />
and change to:<br />
<code><br />
$result = wfSpecialYouTubePost("https://www.google.com/accounts/ClientLogin?"<br />
</code></p>
<p><strong>To Do</strong><br />
Add ability to add to playlists within the YouTube account, not sure when I will get to this but it is a &#8220;to do&#8221; maybe someone will to do it first <img src='http://blogs.ubc.ca/scottmcmillan/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<p>That&#8217;s it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/12/08/direct-upload-to-youtube-through-mediawiki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improved add user feature on UBC Blogs</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/11/27/improved-add-user-feature-on-ubc-blogs/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/11/27/improved-add-user-feature-on-ubc-blogs/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 19:22:46 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpmu]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=542</guid>
		<description><![CDATA[Today we implemented probably my favorite new feature on UBC Blogs. It&#8217;s not a sexy plugin like the Section Widget which is very cool and useful for someone trying trying to make a WordPress/CMS , but is is a VERY &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/11/27/improved-add-user-feature-on-ubc-blogs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today we implemented  probably my favorite new feature on UBC Blogs. It&#8217;s not a sexy plugin like the <a href="http://wordpress.org/extend/plugins/section-widget/">Section Widget</a> which is very cool and useful for someone trying trying to make a WordPress/CMS , but is is a VERY useful and VERY MUCH needed Add User feature on blogs.ubc.ca. If anyone has tried to add more than one user to a blog on our setup  they know what I am talking about, for those that haven&#8217;t here was the problem. There was a huge bug in our system if someone tried to add a user to a blog that was not already in the system the user would  most often not end up in the blog, the problem resulted from the  CWL layer  and a username/email mismatch. They could add a user to the blog <strong>IF</strong> they read the instructions on how to add a user to a blog properly on our system (basically ensure the user is in the system then add the exact username and email they signed up with) sounds easy? Wrong 95% of people do not read instructions doesn&#8217;t matter how many PhD&#8217;s they have nobody <a href="http://en.wikipedia.org/wiki/RTFM"><strong>RTFM</strong></a> anymore they just fill out forms and click. So there has been ALOT of support issues especially at the beginning of the term  and quite a few unhappy users.  We told users about the  &#8220;<a href="http://wordpress.org/extend/plugins/add-users-sidebar-widget/">Add User Sidebar Widget</a>&#8221; to bypass these issues which worked for some but was still  too many steps for most to comprehend (amazes me really). </p>
<p>Now with the new Add User site admins can bulk add users either by email or Student/Staff/Faculity ID. By email users receive an invite similiar to the  default  WordPress Add User if they are in the system they will be added, if not they will be directed to sign up.  If the admin uses ID&#8217;s they will have to tell the user ahead of time to sign up for an account (I expect some problems with this) once the user logs in for the first time they will be added. </p>
<p>I know there are  bulk add user <a href="http://www.dagondesign.com/articles/import-users-plugin-for-wordpress/">plugins</a> out there already but they would not work with the CWL and to be honest I think this Add User functionality is much slicker.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/add_user_screen_large.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/add_user_screen_small.png" alt="add_user_screen_small" title="add_user_screen_small" width="500" height="358" class="aligncenter size-full wp-image-545" /></a></p>
<p>Also we are not connected to the SIS (probably never will be) so this is the next best thing at the moment.  Special thanks to OLT super programmers <a href="http://blogs.ubc.ca/compass">Pan Luo</a> and <a href="http://twitter.com/godfreychan">Godfrey Chan</a> for working on this. This was Pan&#8217;s first time working with WordPress and he did a great job implementing the new CWL features, Godfrey showed him the ropes in WP plugin development which he is pretty much a master of.  The <a href="http://seleniumhq.org/">Selenium </a> QA  tests they developed for this also make me very happy <img src='http://blogs.ubc.ca/scottmcmillan/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/11/27/improved-add-user-feature-on-ubc-blogs/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>UBC Blogs Stats and Growth</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/11/23/ubc-blogs-stats-and-growth/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/11/23/ubc-blogs-stats-and-growth/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 21:16:06 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpmu]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=502</guid>
		<description><![CDATA[This is inspired by Jim Groom&#8217;s recent post. I used to be a little obsessed with stats I did a brief stint doing  the &#8220;Internet Marketing&#8221; thing back in the heyday so the numbers were very important $$ but now &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/11/23/ubc-blogs-stats-and-growth/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is inspired by Jim Groom&#8217;s recent <a href="http://bavatuesdays.com/umw-blogs-traffic-stats-do-they-mean-anything/">post</a>. I used to be a little obsessed with stats I did a brief stint doing  the &#8220;Internet Marketing&#8221; thing back in the heyday so the numbers were very important $$ but now they take on a little different meaning in academia (justification of existence?? which == $$ I guess)&#8230; </p>
<p>UBC Blogs in it&#8217;s current state (using WordPress MU) has been online since September 2008 the OLT has been hosting blogs for many years prior on a Moveable Type platform. We are currently officially a pilot which means (at least the way I interpret it)  we cannot really advertise the service and we hide the account setup/login page&#8230; That being said we still have a decent number of users and blogs probably 10% of the user base was migrated over from the old Moveable Type platform the rest are newbies. We have a another server for more VIP sites (basically means mapped domains and custom themes) which sees about the same traffic with only a couple dozen sites.</p>
<p><strong>User and Blogs Growth</strong><br />
This chart is interesting shows the user account growth chart in the system overtime  1438 users and 795 blogs.<br />
 <div id="attachment_504" class="wp-caption alignleft" style="width: 610px"><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/users_blogs_2009_large.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/users_blogs_2009_small.png" alt="Blogs growth" title="users_blogs_2009_small" width="600" height="93" class="size-full wp-image-504" /></a><p class="wp-caption-text">Blogs growth (click for large)</p></div></p>
<p><strong>Content Growth.</strong><br />
We ran this a few weeks ago on verf(too much of a hog to run on production)  to check the total posts and comments in the system. These numbers go way back to 2004 because some of the old MT blogs were moved into the new system. Still pretty impressive numbers with over 24,000 posts. I am pretty sure this has to be one of the larger websites on campus in terms of number of hosted pages.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/blog_posts_total_large.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/blog_posts_total_small.png" alt="blog_posts_total_small" title="blog_posts_total_small" width="600" height="257" class="aligncenter size-full wp-image-520" /></a></p>
<p><strong>Traffic</strong><br />
We haven&#8217;t been using Google Analytics since the start but here are some numbers from this term so far. </p>
<div id="attachment_510" class="wp-caption aligncenter" style="width: 610px"><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/sept_nov_09_large.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/sept_nov_09_small.png" alt="Sept-Nov 2009 stats" title="sept_nov_09_small" width="600" height="187" class="size-full wp-image-510" /></a><p class="wp-caption-text">Sept-Nov 2009 stats</p></div>
<p>Bounce rate is not the greatest 60% of people leave after visiting one page. </p>
<p><strong>How are people arriving? </strong><br />
<a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/traffic_sources_09t1.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/traffic_sources_09t1.png" alt="traffic_sources_09t1" title="traffic_sources_09t1" width="513" height="148" class="aligncenter size-full wp-image-514" /></a></p>
<p>Top 10 URL&#8217;s this term<br />
<a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/top10_t1_2009.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/top10_t1_2009.png" alt="top10_t1_2009" title="top10_t1_2009" width="186" height="286" class="aligncenter size-full wp-image-516" /></a></p>
<p>Interesting that four of the blogs are courses: <a href=" http://blogs.ubc.ca/digitalliteracy2009/"> digitalliteracy2009</a>, <a href="http://blogs.ubc.ca/etec522sept09/">etec522sept09</a>, <a href="http://blogs.ubc.ca/etec540sept09/">etec540sept09</a> and  <a href="http://blogs.ubc.ca/micb405/">micb405</a> (private).</p>
<p>Where are people coming from? Top 10 visiting countries.</p>
<p><a href="http://blogs.ubc.ca/scottmcmillan/files/2009/11/visitor_location.png"><img src="http://blogs.ubc.ca/scottmcmillan/files/2009/11/visitor_location.png" alt="visitor_location" title="visitor_location" width="136" height="289" class="aligncenter size-full wp-image-522" /></a></p>
<p>From our web traffic and content growth it seems that this campus  &#8220;publishing platform&#8221;  is alive and well and growing at a healthy rate despite being on the down low. </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/11/23/ubc-blogs-stats-and-growth/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A Word on WordPress Spam.</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/09/25/a-word-on-wordpress-spam/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/09/25/a-word-on-wordpress-spam/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 16:53:39 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpmu]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=487</guid>
		<description><![CDATA[A couple weeks ago Brian and Novak mentioned they seemed to see more spam after the upgrade to WordPress MU 2.8.4 interesting I thought so I checked my blog the main blog which had virtually no spam, looking at their &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/09/25/a-word-on-wordpress-spam/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A couple weeks ago <a href="http://blogs.ubc.ca/brian">Brian</a> and <a href="http://blogs.ubc.ca/novak">Novak</a> mentioned they seemed to see more spam after the upgrade to WordPress MU 2.8.4 interesting I thought so I checked my blog the main blog which had virtually no spam, looking at their blogs they had quite a bit of spam but <a href="http://akismet.com/"> Akismet</a> was catching 95% of it so I though no big deal, I also chalked it up to the fact people read their blogs and in the case of Brian&#8217;s alot of people read his blog (still not the most popular on blog on  blogs.ubc.ca which receives virtually no spam odd but not that odd). The last three days things changed and it was basically out of control, the two blogs combined were receiving over 4000 spam messages a day, most were being caught by Akismet but many were getting through.  I checked the other top 10 blogs and they had nothing in comparison.  I was starting to get paranoid if this happened to other blogs on our site this would for sure end up being a DoS.</p>
<p>On further investigation, looking at Novak&#8217;s blog he had reCapthca off for some reason (not so Super Novak)&#8230; after he turned it on spam went down a little but it was still up big time. Next step was looking at the server logs at first I thought we could use some .htaccess trickery to block the bots from hitting the wp-comments-post.php </p>
<p><code><br />
RewriteEngine On<br />
RewriteCond %{REQUEST_METHOD} POST<br />
RewriteCond %{REQUEST_URI} .wp-comments-post\.php*<br />
RewriteCond %{HTTP_REFERER} !.*blogs.ubc.ca.* [OR]<br />
RewriteCond %{HTTP_USER_AGENT} ^$<br />
RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]<br />
</code></p>
<p>But the bot was smart enough to send proper referrals so this would not work. What to do next? I started grepping through the server logs to see what the bots were hitting on their blogs both were being hit by old posts (although both do not post that often so almost everything is old)  but I mean old like over 3 months old. Both had a lot of spam being directed at post on a &#8220;Forum like display plugin&#8221;  post as well as a couple others. So on both blogs I set turn off comments after 90 days (Novak) and 120 days (Brian) and I disabled trackbacks. This pretty much had an immediate impact spam was virtually stopped on both blogs.  In conclusion this is a temporary fix I recommend everyone having spam issues right now should do this (I always recommend disabling trackbacks).  </p>
<p>This definitely is a bigger issue if bots can spam and bypass both reCaptcha and Akismet (in some cases) WordPress has a fairly serious security issue hopefully <a href="http://wordpress.org">WordPress</a> addresses this soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/09/25/a-word-on-wordpress-spam/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Realtime Syndication with the PubSubHubbub protocol</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/08/06/realtime-syndication-with-the-pubsubhubbub-protocol/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/08/06/realtime-syndication-with-the-pubsubhubbub-protocol/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 17:38:33 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[Syndication]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=469</guid>
		<description><![CDATA[Seems like whenever you come back from a vacation there is something new being discussed that rocks your world. This time for it&#8217;s the PubSubHubbub protocol developed by Google Engineers. A simple, open, server-to-server web-hook-based pubsub (publish/subscribe) protocol as an &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/08/06/realtime-syndication-with-the-pubsubhubbub-protocol/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Seems like whenever you come back from a vacation there is something new being discussed that rocks your world. This time for it&#8217;s the <a href="http://code.google.com/p/pubsubhubbub/">PubSubHubbub</a> protocol developed by Google Engineers.</p>
<blockquote><p>A simple, open, server-to-server web-hook-based pubsub (publish/subscribe) protocol as an extension to Atom (and RSS).</p>
<p>Parties (servers) speaking the PubSubHubbub protocol can get near-instant notifications (via webhook callbacks) when a topic (feed URL) they&#8217;re interested in is updated.</p></blockquote>
<p>The thing I like about this is in a &#8220;Feed WordPress&#8221; scenario. Instead of polling the same system a Hub Server could be polled taking some of the strain of the publishing WPMU server and also allowing faster content updates&#8230; I think Feed WordPress would need some changes but seems doable.</p>
<p>There is already a WordPress <a href="http://wordpress.org/extend/plugins/pubsubhubbub/">Plugin</a> that supports the protocol&#8230;</p>
<p><strong>PubSubHubbub Demo &#8211; Real-Time CrunchUp</strong><br />
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/ewQBgbysSOQ&amp;hl=en&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/ewQBgbysSOQ&amp;hl=en&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/08/06/realtime-syndication-with-the-pubsubhubbub-protocol/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Timber PHP debugging in WordPress</title>
		<link>http://blogs.ubc.ca/scottmcmillan/2009/06/24/timber-php-debugging-in-wordpress/</link>
		<comments>http://blogs.ubc.ca/scottmcmillan/2009/06/24/timber-php-debugging-in-wordpress/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:40:40 +0000</pubDate>
		<dc:creator>Scott McMillan</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blogs.ubc.ca/scottmcmillan/?p=444</guid>
		<description><![CDATA[Stumbled upon Blurbia and interesting WordPress development company that is doing some pretty solid work. Timber http://www.blurbia.com/plugins/timber/ Timber is intended primarily as a developer’s tool, to be enabled in a sandbox environment while debugging plugins or themes in-progress. However, it &#8230; <a href="http://blogs.ubc.ca/scottmcmillan/2009/06/24/timber-php-debugging-in-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Stumbled upon Blurbia and interesting WordPress development company that is doing some pretty solid work. </p>
<p><strong>Timber</strong><br />
<a href="http://www.blurbia.com/plugins/timber/">http://www.blurbia.com/plugins/timber/</a></p>
<p><em>Timber is intended primarily as a developer’s tool, to be enabled in a sandbox environment while debugging plugins or themes in-progress. However, it also has potential in a production setting, as a way to hide errors from the end-user while still logging them for administrator review. The configuration settings allow for precise control of what type of errors and what error information is logged, so it can be deployed in varying scenarios without runaway logs filling the database.</em></p>
<p><strong>Synected</strong><br />
<a href="http://www.blurbia.com/plugins/synected/">http://www.blurbia.com/plugins/synected/</a></p>
<p><em>Synected enables shortened URL creation on your own blog. Rather than relying on services such as tinyurl.com or bit.ly, Synected lets you easily create and use short links based off your own domain. This releases you from dependence on a third party — a server error on tinyurl no longer prevents visitors from reaching your site. In addition, it strengthens your brand, keeping your domain name in view of your audience even on Twitter and other micro-communication platforms.</em></p>
<p>These guys develop some pretty tight themes also:<br />
<a href="http://demo.blurbia.com/melora/">http://demo.blurbia.com/melora/</a> Fully customizable. With sites like this, plus the other framework themes we are getting very close to not having to design themes anymore&#8230; which is great because you will be able to role out a site in a day vs weeks. </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ubc.ca/scottmcmillan/2009/06/24/timber-php-debugging-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

