Kevin Cupp2012-08-05T23:24:39-04:00http://kevincupp.com/Kevin Cuppkevin.cupp@gmail.comPhotos of 20112011-12-25T00:00:00-05:00/2011/12/25/photos-of-2011<p>I <a href='http://flickr.com/photos/kevincupp/sets/'>take photos</a> a bit on the side, and at the end of the year I like to look back the year’s fun and creations. This year has been a bit slower than usual, photo-wise, mainly due to not following the Virginia Tech football team around, and also because the best moments are often times I don’t want to be fooling with a big SLR camera.</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627732930953/'><img src='http://farm7.staticflickr.com/6053/6228221683_626d7cfd20_z.jpg' /></a></p>
<p>Quidditch has become <a href='http://www.internationalquidditch.org/'>quite a popular sport</a>, and it sure is fun to watch and photograph. As you can see, sometimes they actually fly.</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627795197710/'><img src='http://farm7.staticflickr.com/6162/6201121105_973ac9a8ec_z.jpg' /></a></p><p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627795197710/'><img src='http://farm7.staticflickr.com/6175/6201613484_ba6136f231_z.jpg' /></a></p>
<p>Martin Sheen and Elimio Estevez visited Virginia Tech at the persuasion of <a href='http://plaidavenger.com'>John Boyer</a> and his class of 3000 students to promote their film, “The Way.” This kind of power also brought on a <a href='http://www.flickr.com/photos/kevincupp/sets/72157628299166841/'>Skype call with Aung Sang Suu Kyi</a>:</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157628299166841/'><img src='http://farm8.staticflickr.com/7022/6463465951_fd2d25bc67_z.jpg' /></a></p>
<p>Memorial Day weekend at Sewell Point was a blast and included photographing water sports and people falling off a tube.</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157626728703319/'><img src='http://farm4.staticflickr.com/3466/5778442755_57b1c71ae5_z.jpg' /></a></p>
<p>The following photos from <a href='http://www.flickr.com/photos/kevincupp/sets/72157627370576010/'>Virginia Tech’s football media day</a> are in tribute to the Hokies’ great season. Logan Thomas and David Wilson have been the ones to watch this year, giving Coach Beamer many reasons to smile in the last photo.</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627370576010/'><img src='http://farm7.staticflickr.com/6004/6014780169_df84ace099_z.jpg' /></a></p><p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627370576010/'><img src='http://farm7.staticflickr.com/6127/6015344006_9fbf423682_z.jpg' /></a></p><p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157627370576010/'><img src='http://farm7.staticflickr.com/6131/6014772437_134c3efbf6_z.jpg' /></a></p>
<p>Last, and possibly least, a photo of Gary Vaynerchuk signing a dude’s chest. He <a href='http://www.flickr.com/photos/kevincupp/sets/72157626492930691/'>visited Virginia Tech</a> to share his wisdom and also ended up giving away A LOT of prizes, including Super Bowl tickets, a trip to Las Vegas, and even startup cash.</p>
<p align='center'><a href='http://www.flickr.com/photos/kevincupp/sets/72157626492930691/'><img src='http://farm6.staticflickr.com/5307/5673580477_2020515a2f_z.jpg' /></a></p>SiriProxy with TiVo2011-12-04T00:00:00-05:00/2011/12/04/siriproxy<p>I never thought Apple would come out with something that would make the “app experience” seem tedious. By app experience, I mean: going to your home screen, finding the right app, opening the app, then tapping your way to your objective, and heaven forbid you have to type anything long along the way. That description, which was the same even before Siri, makes it sound tedious, yet we never really thought of it as so until Siri came out. Now, a simple sentence can be translated into any number of taps to get a task done. Powerful possibilities now, and in the future.</p>
<p>The question is, how powerful? Apple has not yet provided a Siri SDK, but the question can now be answered sooner thanks to a <a href='http://twitter.com/applidium'>couple</a> of <a href='http://twitter.com/plamoni'>tinkerers</a> that ultimately led to the creation of <a href='https://github.com/plamoni/SiriProxy'>SiriProxy</a>.</p>
<p>SiriProxy has matured a lot since its conception about two weeks ago, and is now fairly easy to get set up in your own home network. So, I decided to give it a shot last night and within about 1-2 hours<sup id='fnr1-2011-12-04'><a href='#fn1-2011-12-04'>1</a></sup>, I had Siri talking to my TiVo<sup id='fnr2-2011-12-04'><a href='#fn2-2011-12-04'>2</a></sup>:</p>
<p align='center'><img src='/images/posts/siritivo.png' /></p>
<p>It’s an awesome feeling knowing you’ve just done something that’s probably never been done before<sup id='fnr3-2011-12-04'><a href='#fn3-2011-12-04'>3</a></sup>. Not only that, this solved an actual need. Every now and then, we walk by our TiVo and see both tuners are recording shows and we’re curious what it’s recording<sup id='fnr4-2011-12-04'><a href='#fn4-2011-12-04'>4</a></sup>. Now, it’s just a question away.</p>
<p>The dream is to eventually be able to schedule recordings on the TiVo, (<strong>“Siri, record the next new episode of Mythbusters”</strong>) but that may remain a dream unless I can come up with a web service to submit TiVo’s online forms for scheduling shows.</p>
<p>But, these dreams are now that much closer. Here are some awesome examples of things people are doing with SiriProxy:</p>
<ul>
<li><strong><a href='http://www.youtube.com/watch?v=AN6wy0keQqo'>Thermostat control</a></strong> - The original SiriProxy plugin by <a href='http://twitter.com/plamoni'>@plamoni</a>. Get the temperature of your house and make adjustments if needed.</li>
<li><strong><a href='http://vimeo.com/32891123'>Universal remote</a></strong> - I’d love to take this a step further and integrate it with my Logitech Harmony One remote. I would say, <strong>“I want to watch a DVD”</strong>, and watch my entertainment system switch TV inputs and turn on my DVD player.</li>
<li><strong><a href='https://github.com/parm289/SiriProxy-SiriIMDB'>IMDB reference</a></strong> - This is a great example of querying for information. It can tell you who was in a movie, or even make a recommendation based on the IMDB rating.</li>
<li><strong><a href='http://www.youtube.com/watch?v=p4LamngB070'>That’s what she said</a></strong> - This is just hilarious.</li>
</ul>
<p>That second example made the use of an <a href='http://www.arduino.cc/'>Arduino</a> board. I plan on using one to have Siri open my garage (<strong>“Open my garage door”</strong>, <strong>“Is my garage door open?”</strong>, <strong>“Close it, please”</strong>). I could also perform another first and integrate Siri with the <a href='http://www.youtube.com/watch?v=DLhMEpGBBtk'>Wings-a-Loft system</a> to open the doors on my DeLorean.</p>
<h2 id='how_does_siriproxy_work'>How does SiriProxy work?</h2>
<p>While we await an official Siri SDK, SiriProxy gives us a look at patterns Siri uses to parse information and have a conversation. Let’s take a look.</p>
<pre><code>listen_for /test siri proxy/i do
say "Siri Proxy is up and running!"
request_completed
end</code></pre>
<p>Once the speech objects are parsed, SiriProxy gives you a chance to act on certain words or a phrase before Apple handles it. The above example is akin to “hello world.” The script listens for <strong>“Test Siri proxy”</strong> and then tells the user that it’s working. Now, let’s say you want Siri to ask a question:</p>
<pre><code>listen_for /siri proxy test question/i do
response = ask "Is this thing working?" # Ask the user for something
if (response =~ /yes/i) # Process their response
say "Great!"
else
say "You could have just said 'yes'!"
end
request_completed # Always complete your request! Otherwise the phone will "spin" at the user!
end</code></pre>
<p>You can see we use the “ask” command to prompt for data, then we use an if statement to figure out what to do with the answer. This is great for getting input or confirmation from the user, but it’s not the best way for Siri to follow a conversation. For example, you may ask Siri, <strong>“Where’s the best Chinese food?”</strong>, and then follow up with, <strong>“How about Mexican?”</strong> This is achieved with states.</p>
<pre><code>listen_for /siri proxy test state/i do
set_state :some_state
say "I set the state, try saying 'confirm state change'"
request_completed
end
listen_for /confirm state change/i, within_state: :some_state do
say "State change works fine!"
set_state nil # Clear out the state!
request_completed
end</code></pre>
<p>In the first listen_for statement, we set a state. Then in the second listen_for statement, we act on the phrase only if the previous state was set, allowing the conversation to flow.</p>
<p>For the last example, I’ll show how easy it is to grab data out of a sentence sent to Siri:</p>
<pre><code>listen_for /siri proxy number ([0-9,]*[0-9])/i do |number|
say "Detected number: #{number}"
request_completed
end</code></pre>
<p>Yes, you can use the power of regular expressions to listen to and act on phrases. This is really the key to figuring out the meaning of a sentence, a key value of Siri, rather than relying on the user using a specific syntax.</p>
<p>SiriProxy has raised the bar in terms of what we should expect in an SDK from Apple. It’s confirmed we’re not just looking for ways to tweet or add to-do items to our favorite to-do app, we want to interact with the things and information around us. This means Apple has to be willing to let Siri run any (approved) code thrown at it, which should be an interesting decision to see made. There are already apps to control your TiVo or thermostat, they just need this extra way of executing their code.</p>
<hr /><ol class='footnotes'>
<li id='fn1-2011-12-04'>This includes everything from the research on the XML TiVo provides of the shows it has recorded to getting SiriProxy up and running. <a href='#fnr1-2011-12-04'>↩</a></li>
<li id='fn2-2011-12-04'>I wanted to share the code on GitHub, but TiVo requres Digest authentication and it turns out there's no easy way to do this in Ruby without installing a gem, I didn't want users to have to do that. So right now, the code executes a PHP script that executes a curl shell command. Kind of a Rube Goldberg series of events, not ideal. <a href='#fnr2-2011-12-04'>↩</a></li>
<li id='fn3-2011-12-04'>At least, it's safe to assume given the time SiriProxy has been out and the lack of discussion online about a TiVo implementation. <a href='#fnr3-2011-12-04'>↩</a></li>
<li id='fn4-2011-12-04'>O' how I miss the TiVo Series 3's OLED display on the front that would tell you what it was recording. We now have the TiVo Premiere since the Series 3 was on its last leg, so now the time of day and what our TiVo is recording is often a mystery. <a href='#fnr4-2011-12-04'>↩</a></li>
</ol>Making EE Sites Fly with Varnish2011-05-22T00:00:00-04:00/2011/05/22/marking-ee-sites-fly-with-varnish<p><em><strong>UPDATE</strong>: I wrote a much longer, accurate primer for pairing ExpressionEngine and Varnish <a href='http://expressionengine.com/blog/entry/making_sites_fly_with_varnish'>here</a>.</em></p>
<p>Since <a href='http://www.kevincupp.com/2011/05/09/purge.html'>publishing my Purge addon</a>, several requests have come in from developers asking how to set up Varnish with ExpressionEngine, how well it works and if I have any tips. When I was first setting up Varnish with EE, there were no guides online specific to the CMS, so here’s a first crack at a guide for caching ExpressionEngine with Varnish.</p>
<p>First, a quick explanation about what Varnish does: <a href='http://www.varnish-cache.org'>Varnish</a> is a caching proxy that sits between your users and your “backend,” which can be Apache, nginx, anything that serves HTTP requests. As requests come in, Varnish caches the fully-rendered output from the backend in memory so that future requests within a specified time frame don’t require the overhead needed to construct the page from scratch.</p>
<p>With that said, Varnish pairs best with EE when your site is mainly static content that users don’t interact with. For example, <a href='http://plaidavenger.com'>Plaid Avenger</a> is a site I built in EE, and the only dynamic parts that update are when the site admins create entries in the EE backend. The comments are handled by Disqus, so those are handled once the page has landed in the user’s browser<sup id='fnr1-2011-05-22'><a href='#fn1-2011-05-22'>1</a></sup>. So this is a perfect site for Varnish.</p>
<p>For a site like <a href='http://devot-ee.com'>Devot-EE</a> where there is user-specific content delivered to the browser, and developers are adding, editing, rating and reviewing addons frequently, you do not get all of the benefits from serving your entire site out of a cache. You could configure Varnish to only cache when a user is not logged in which would definitely help server load when people are just browsing, but most logged-in requests will need to hit the backend and those would not scale as nicely to high traffic.</p>
<h2 id='installing'>Installing</h2>
<p>Depending on your flavor of Linux, Varnish will be more or less set up for you out of the package manager. I’ve installed it from <a href='http://archlinux.org'>Arch Linux’s</a> User Repository which is basically like compiling from source. I won’t go into detail about starting the actual Varnish daemon on your distro, but it’s actually pretty easy as you’ll see from <a href='http://www.varnish-cache.org/docs/2.1/tutorial/starting_varnish.html'>the wiki</a>, just be sure to use malloc as your storage method so that pages are stored in RAM instead of on the disk. Avoiding disk I/O is crucial for achieving a high hitrate.</p>
<p>Once you have Varnish running and serving requests from your backend, now you need a good VCL file.</p>
<h2 id='the_vcl'>The VCL</h2>
<p>Here is a bare minimum VCL file to get ExpressionEngine caching properly.</p>
<pre><code>sub vcl_recv {
if (req.url ~ "^/system" ||
req.url ~ "ACT=" ||
req.request == "POST") {
return (pass);
}
unset req.http.Cookie;
return (lookup);
}
sub vcl_fetch {
set beresp.ttl = 60s;
return (deliver);
}</code></pre>
<p>What this will do is return cached objects for all requests except those for the system directory, otherwise you won’t be able to log into EE. We will also choose not to cache action (ACT) requests which some third-party addons use, and we shouldn’t want any POST requests cached since those will likely be unique.</p>
<p>You may also notice we are unsetting some cookies. This is because Varnish assumes that if a page is setting a cookie, there is user-specific content to be displayed and therefore it shouldn’t be cached. There are a few session cookies EE sets for guest users, so we need to tell Varnish to ignore those.</p>
<p>And finally, we are setting the TTL to 60 seconds, meaning that when a request is pulled from the backend, any requests that happen within the next 60 seconds for that object will be pulled from the cache. Say you have an resource-intensive EE template, under high traffic that template will only need to be generated at most once every 60 seconds. Pretty nice, huh? But even that didn’t satisfy me, I wanted a longer TTL while still allowing content administrators to update the site, so I created Purge so that my cache could be purged only when it needs to be.</p>
<p>Now that everything is being passed through Varnish, you might notice your Apache logs are nearly useless<sup id='fnr2-2011-05-22'><a href='#fn2-2011-05-22'>2</a></sup>. All that’s logged are requests from 127.0.0.1 and no referrer information. We need to add something else to our vcl_recv function to fix that:</p>
<pre><code>remove req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;</code></pre>
<p>The above will pass along the client’s IP address and their referrer to your server logs.</p>
<p>Varnish can also protect you from downtime if your backend is unresponsive. There’s always that time where we make a mistake in an Apache configuration file and Apache fails to restart gracefully, or the process died for other reasons. The trick is to set <a href='http://www.varnish-cache.org/trac/wiki/VCLExampleGrace'>Grace time</a> on your requests. You add this both to your vcl_recv and vcl_fetch:</p>
<pre><code>set req.grace = 1h; #vcl_recv
set beresp.grace = 1h; #vcl_fetch</code></pre>
<p>With the addition of <a href='http://www.varnish-cache.org/trac/wiki/BackendPolling'>backend polling</a>, Varnish will now keep objects for 1 hour past their expiry time while you work on getting your backend back up and running. Grace time also kicks in if another user’s request for an object in the backend has not finished yet, it will return the cached version while the other request completes so there aren’t multiple requests for the same intensive object in the backend.</p>
<p>Here is our new VCL file with everything above implemented:</p>
<pre><code># Configure backend with probing
backend default {
.host = "127.0.0.1";
.port = "8080";
.probe = {
.url = "/";
.timeout = 34 ms;
.interval = 1s;
.window = 10;
.threshold = 8;
}
}
sub vcl_recv {
# Don't cache EE system directory, ACT requests or POST requests
if (req.url ~ "^/system" ||
req.url ~ "ACT=" ||
req.request == "POST") {
return (pass);
}
# Purge site from cache when
if (req.request == "EE_PURGE") {
ban("req.http.host ~ mysite.com && req.url ~ ^/.*$");
error 200 "Purged";
}
# Pass along client information to backend
remove req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;
unset req.http.Cookie;
set req.grace = 1h;
return (lookup);
}
sub vcl_fetch {
set beresp.grace = 1h;
set beresp.ttl = 24h;
return (deliver);
}</code></pre>
<p>I hope the above information is a good primer for you to get started caching your sites with Varnish. There are <a href='http://www.varnish-cache.org/trac/wiki/VCLExamples'>many more</a> ways to get the most out of Varnish, so please take a look around and work out the best solution for you. For fun, hammer on your newly-cached site with <a href='http://httpd.apache.org/docs/2.0/programs/ab.html'>Apache Benchmark</a> and watch your site serve hundreds of requests per second without batting an eyelash.</p>
<p><em><strong>UPDATE:</strong> Simplified VCL and updated syntax to match Varnish 3 (2011-12-04)</em></p>
<hr /><ol class='footnotes'>
<li id='fn1-2011-05-22'>Even if comments were managed by EE, it would be ok to use Varnish if the commenting level wasn't very high, I would just modify the Purge extension to also purge when a comment is posted. But if people are commenting every few seconds, caching becomes less effective if you're serving off of a single server. <a href='#fnr1-2011-05-22'>↩</a></li>
<li id='fn2-2011-05-22'>I often analyze my Apache logs to get accurate numbers of unique requests and referrers, as well to watch for any unusual traffic. <a href='#fnr2-2011-05-22'>↩</a></li>
</ol>Symbolicating iOS Crash Logs2011-05-12T00:00:00-04:00/2011/05/12/symbolicating-ios-crash-logs<p>During iPhone app beta testing, and even when you have apps on the App Store, it’s often difficult to reproduce crashes reported from users. Luckily, iOS devices keep logs of each crash<sup id='fnr1-2011-05-12'><a href='#fn1-2011-05-12'>1</a></sup> and can even tell you the exact line of code that caused the problem. Let’s take a look at a crash log for MyApp:</p>
<pre><code>Exception Type: EXC_BAD_ACCESS (SIGBUS)
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x313fec98 0x313fc000 + 11416
1 MyApp 0x00019c12 0x1000 + 101394
2 MyApp 0x0000a1cc 0x1000 + 37324
3 MyApp 0x0000c474 0x1000 + 46196
4 libdispatch.dylib 0x33e9d8e0 0x33e92000 + 47328
5 libdispatch.dylib 0x33e991ee 0x33e92000 + 29166
6 CoreFoundation 0x3568e934 0x35616000 + 493876
7 CoreFoundation 0x3561eebc 0x35616000 + 36540
8 CoreFoundation 0x3561edc4 0x35616000 + 36292
9 GraphicsServices 0x343cd418 0x343c9000 + 17432
10 GraphicsServices 0x343cd4c4 0x343c9000 + 17604
11 UIKit 0x3608ad62 0x3605c000 + 191842
12 UIKit 0x36088800 0x3605c000 + 182272
13 MyApp 0x000024ec 0x1000 + 5356
14 MyApp 0x000024ac 0x1000 + 5292</code></pre>
<p>How are we supposed to tell anything from that? Only the hex symbols of the objects are there, so we need to <em>symbolicate</em><sup id='fnr2-2011-05-12'><a href='#fn2-2011-05-12'>2</a></sup> them. I am writing this short guide because Apple hasn’t documented this process very well, and no single article online had all the information I needed to get the job done. This post assumes a certain ability to debug your code too once you have the log symbolicated.</p>
<p>First, and most importantly, you need to have the .app and .dSYM file for the build that generated the crash log. This is why it’s very important to <strong>archive every build you distribute</strong><sup id='fnr3-2011-05-12'><a href='#fn3-2011-05-12'>3</a></sup>, whether it be ad hoc or via the App Store. If you don’t have the original build, you’re out of luck.</p>
<p>I find it’s easiest to have everything, the .app, .dSYM, and .crash files, in the same directory. Next, we have to run a shell command called symbolicate which comes with Xcode. It’s a long path, so I recommend creating a bash/zsh alias for this, here’s mine:</p>
<pre><code>alias symbolicate="/Developer/Platforms/iPhoneOS.platform/Developer/Library/\
PrivateFrameworks/DTDeviceKit.framework/Versions/A/\
Resources/symbolicatecrash -v"</code></pre>
<p>Once that’s set in your shell, you can run the following, replacing the appropriate values of course:</p>
<pre><code>symbolicate "MyApp_2011-05-10-170924-iPhone.crash" "MyApp.app"</code></pre>
<p>Now you should see a lovely, symbolicated crash log spat out into the terminal:<sup id='fnr4-2011-05-12'><a href='#fn4-2011-05-12'>4</a></sup></p>
<pre><code>Exception Type: EXC_BAD_ACCESS (SIGBUS)
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x33b24c98 objc_msgSend + 16
1 MyApp 0x00019c12 -[TwoLineNavBarTitleView setLine2:]
(TwoLineNavBarTitleView.m:43)
2 MyApp 0x0000a1cc -[ListViewController
listModelDidFinishQueryingForRadius:]
(ListViewController.m:160)
3 MyApp 0x0000c474 __45-[ListViewModel
filterParksBasedOnCategories]
(ListViewModel.m:129)
4 libdispatch.dylib 0x33d108e0 _dispatch_call_block_and_release + 4
5 libdispatch.dylib 0x33d0c1ee _dispatch_main_queue_callback + 306
6 CoreFoundation 0x3039f934 __CFRunLoopRun + 1328
7 CoreFoundation 0x3032febc CFRunLoopRunSpecific + 224
8 CoreFoundation 0x3032fdc4 CFRunLoopRunInMode + 52
9 GraphicsServices 0x35571418 GSEventRunModal + 108
10 GraphicsServices 0x355714c4 GSEventRun + 56
11 UIKit 0x358c7d62 -[UIApplication _run] + 398
12 UIKit 0x358c5800 UIApplicationMain + 664
13 MyApp 0x000024ec main (main.m:14)
14 MyApp 0x000024ac 0x1000 + 5292</code></pre>
<p>Here I can see which method was called (setLine2: in my custom view class) and that it was called from line 43 of the same class. Much more helpful. Now I can fix my over-released memory reference and call this bug squashed.</p>
<hr /><ol class='footnotes'>
<li id='fn1-2011-05-12'>How you get the logs is another story. They're stored on the user's computer after syncing with iTunes. If you have a line of communication with your users, it's usually easy for them to find the relevant logs and send them to you. iTunes Connect supposedly gathers crash logs for you but I've never seen any in there. I haven't experimented with ways of in-app crash reporting yet. <a href='#fnr1-2011-05-12'>↩</a></li>
<li id='fn2-2011-05-12'>Isn't that a cool word? <a href='#fnr2-2011-05-12'>↩</a></li>
<li id='fn3-2011-05-12'>Xcode's built-in Archive function is great for this, especially when paired with Time Machine. <a href='#fnr3-2011-05-12'>↩</a></li>
<li id='fn4-2011-05-12'>I typically like to use the -o tack on the symbolicate command to output the results to a file for easier reading and organization. <a href='#fnr4-2011-05-12'>↩</a></li>
</ol>New EE Addon: Purge2011-05-09T00:00:00-04:00/2011/05/09/purge<p>I knew I loved <a href='http://www.varnish-cache.org/'>Varnish Cache</a> when it transformed an ExpressionEngine template’s load time from 9 seconds<sup id='fnr1-2011-05-09'><a href='#fn1-2011-05-09'>1</a></sup> down to 23 milliseconds, and made it capable of 700 hits per second. A page that would previously bring my server to its knees if accessed too many times in succession was now being served effortlessly.</p>
<p>Well, this is awesome, I thought. I’ll just set the time-to-live for objects in the cache to like 1000 hours. But the problem is if we make a change in the backend, it won’t show up until that 1000-hour TTL is over. So I need a way to automatically purge all objects out of this site when something in the CMS is updated. Enter <a href='http://github.com/kevincupp/purge.ee2_addon'>Purge</a>.</p>
<p>Purge will send a purge request to Varnish whenever an entry is submitted, edited or deleted. There is even a link in the control panel to manually send a purge request, in case you change a category label and need the change to show on the front end.</p>
<p>So if you use Varnish and EE (I think there’s 4 of us), let me know how it works for you and let me know of any issues or suggestions via the GitHub page.</p>
<hr /><ol class='footnotes'>
<li id='fn1-2011-05-09'>There are many <a href='http://expressionengine.com/blog/entry/troubleshooting_site_performance_issues/'>bottlenecks</a> to check when diagnosing poor ExpressionEngine performance, but unfortunately there was no getting around some complex relationships we needed. <a href='#fnr1-2011-05-09'>↩</a></li>
</ol>SSDs2011-05-07T00:00:00-04:00/2011/05/07/SSDs<p>With the recent line of iMac and MacBook Air updates, there has been much <a href='http://www.marco.org/2011/05/04/imac-vs-mac-pro-vs-macbook-pro'>discussion</a> over what’s the perfect hardware setup. Can you live on just a MacBook Air? Or would you want an iMac to accompany it? How about just a maxed-out MacBook Pro? Should you even consider a Mac Pro?</p>
<p>Personally, I’m happy with my maxed-out, mid-2010 Core i7 MacBook Pro. I’ve upgraded the RAM to 8GB<sup id='fnr1-2011-05-07'><a href='#fn1-2011-05-07'>1</a></sup>, but what I consider to be the most important upgrade is replacing the hard drive with an SSD.</p>
<p>If you’re curious about how your computing experience would be different on an SSD, imagine this: click something, or open a document or an application, and not have to wait. Here’s a nonscientific<sup id='fnr2-2011-05-07'><a href='#fn2-2011-05-07'>2</a></sup>, nonexact benchmark of applications who popularly hog time during launch running on an SSD:</p>
<ul>
<li>Photoshop: 2.5 seconds</li>
<li>Final Cut Pro: 4 seconds</li>
<li>Firefox: < 1 second<sup id='fnr3-2011-05-07'><a href='#fn3-2011-05-07'>3</a></sup></li>
</ul>
<p>Regular applications launch nearly instantaneous, and the general responsiveness of the computer is dream-like, it’s still hard for me to believe after 6 months. Installing an SSD is the most effective performance upgrade you can perform since you are replacing the biggest speed bottleneck of your computer.</p>
<p>A frequently cited con of SSDs is the capacity issue<sup id='fnr4-2011-05-07'><a href='#fn4-2011-05-07'>4</a></sup>. Curmudgeony people typically use this excuse to discount SSDs entirely, but I’ve actually enjoyed purging data. Music was the biggest offender for me, but now with services like <a href='http://rdio.com'>Rdio</a>, I’m fine leaving my music stored externally at home. And with less stored locally, the less I have to worry about replacing if something happens to my MacBook Pro<sup id='fnr5-2011-05-07'><a href='#fn5-2011-05-07'>5</a></sup>, or if I want to swtich to a new computer. Having a slow hard disk so that I can store copious amounts of things I hardly ever need or look at isn’t worth the lag.</p>
<p>Now, which SSD? I prefer <a href='http://eshop.macsales.com/shop/internal_storage/Mercury_Extreme_SSD_Sandforce/Solid_State_Pro'>OWC’s Mercury Extreme Pro</a> drives, simply because the reviews and benchmarks were impressive, and OWC hardware has never failed me. You can even buy <a href='http://eshop.macsales.com/owcpages/datadoubler/'>kits</a> to replace your Mac’s optical drive slot with another hard drive for those who need the extra storage.</p>
<p>So once you decide which Mac is right for you, do yourself a favor and get an upgrade that counts. Once you go SSD, you don’t go back.</p>
<hr /><ol class='footnotes'>
<li id='fn1-2011-05-07'>Firefox can be open ALL DAY now! <a href='#fnr1-2011-05-07'>↩</a></li>
<li id='fn2-2011-05-07'>Me counting Mississippily. <a href='#fnr2-2011-05-07'>↩</a></li>
<li id='fn3-2011-05-07'>Test was done with Firefox 4 which does has significant speed improvements, but I remember Firefox 3 still launching within a second or so. <a href='#fnr3-2011-05-07'>↩</a></li>
<li id='fn4-2011-05-07'>That is, if you want a ~500GB SSD or a capacity considered good by today's standards, prepare to spend up to $1000. <a href='#fnr4-2011-05-07'>↩</a></li>
<li id='fn5-2011-05-07'>Not in terms of replacing data that wasn't backed up, but just having to replace things period. The less I have to put back, the quicker I can get back up and running. I use SuperDuper of course to create drive clones, but that's not as portable across different Mac models. <a href='#fnr5-2011-05-07'>↩</a></li>
</ol>Starting Fresh2011-04-26T00:00:00-04:00/2011/04/26/starting-fresh<p>I’ve been starting my blog off and on since 2002. Well, here we go again, fullfilling the itch.</p>
<p>Ever since 2002, I’ve run my blog using <a href='http://movabletype.org/'>Movable Type</a>. Ah those were the days, when Ben and Mena Trott were still coding a little CMS in Perl out of their home and no one knew what a blog was. The explosion of blogging has made me hesitate rejoining, I figured I would get lost in the noise. But, the itch wins.</p>
<p>I’ve decided to start fresh archives. No one wants to go back and read my ramblings as a high schooler or college student complaining about the weather or Comcast, or see my reviews of 5-year-old products.</p>
<p>I’m also using a new blogging tool called <a href='https://github.com/mojombo/jekyll'>Jekyll</a>. Basically, it’s a static file blog generator. Having to manage highly-trafficked sites lately, I’ve become fascinated with the idea of serving up content with very little processing power, and extremely quickly. The key is serving up pregenerated content, and if you want to be really safe, put it behind a caching proxy like <a href='http://www.varnish-cache.org/'>Varnish</a>. Thousands of requests per second? No problem.</p>
<p>The site will be pretty minimal in terms of design and fluff. Don’t worry, I’m not one of those minimalist guys who’s going to tell you how to wash your dishes. But since I’m not a designer, this site will usually look terrible, so you might just want to <a href='/atom.xml'>subscribe</a> and keep up in your favorite <a href='http://reederapp.com/'>feed reader</a>.</p>