<?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/"
	>

<channel>
	<title>kill the radio</title>
	<atom:link href="http://blog.killtheradio.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.killtheradio.net</link>
	<description>or die trying</description>
	<lastBuildDate>Wed, 03 Apr 2013 00:44:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Infinite health in Terraria (in Windows)</title>
		<link>http://blog.killtheradio.net/tricks-hacks/infinite-health-in-terraria-in-windows/</link>
		<comments>http://blog.killtheradio.net/tricks-hacks/infinite-health-in-terraria-in-windows/#comments</comments>
		<pubDate>Thu, 28 Feb 2013 05:34:28 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Tricks/Hacks]]></category>
		<category><![CDATA[cracking]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[memory]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=884</guid>
		<description><![CDATA[Back in the days of DOS, before steam, in the long-long ago, there were tools like SoftICE and IDA and W32Dasm that would allow you to hook into your operating system or running executables and modify them in perverted ways. Today, I&#8217;m going to show you a little trick from my game cracking days for [...]]]></description>
			<content:encoded><![CDATA[<p>Back in the days of DOS, before steam, in the long-long ago, there were tools like SoftICE and IDA and W32Dasm that would allow you to hook into your operating system or running executables and modify them in perverted ways. Today, I&#8217;m going to show you a little trick from my game cracking days for unlimited health in the game <a href="http://www.terraria.org/">Terraria</a>, which I tend to play a lot when I don&#8217;t have access to my gaming machine.</p>
<h2>Memory searching</h2>
<p>Every game has variables that store information: your ammo, your health, how large your penis is, etc. Each of these variables generally has a dedicated position in memory where it&#8217;s stored. If you can find the location of this value, you can modify it to your liking. But how to you find it? This is the process of memory searching.</p>
<p>The tool we&#8217;re going to use is called TSearch. I don&#8217;t think it has an official site anymore (assuming it ever did), but you can get it off <a href="http://www.angelfire.com/ultra2/fd0/tools.html">this completely legit Angelfire website</a> (<a href="http://www.angelfire.com/ultra2/fd0/tsearch_16.zip">direct link</a>). While I can&#8217;t guarantee the executable is free of pathogens of the digital persuasion, I can say that I&#8217;ve scanned it with several tools and come up blank. <strong>UPDATE:</strong> There are probably better tools you can use, for instance <a href="http://www.cheatengine.org/">Cheat Engine</a>, an open source program in the same vein as TSearch. I Chose TSearch because that&#8217;s what I used in the old days, and had a copy laying around on my machine.</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2013/02/open-process.png"><img src="http://blog.killtheradio.net/wp-content/uploads/2013/02/open-process-300x202.png" alt="" title="Locate the Terraria process" width="300" height="202" class="alignright size-medium wp-image-893" /></a>The way memory searching works is you pick a value you want to modify. We&#8217;re going to do health. So open start Terraria, open your favorite world, and let&#8217;s go to town. Once Terraria is loaded, open TSearch. On the top-left, you&#8217;ll see a button called &#8220;Open process.&#8221; Click it and select Terraria.</p>
<p>Now that the process is open, TSearch has access to Terraria&#8217;s memory, including your health value >=]. We&#8217;ll start our search for the location soon, but first we need a starting point.</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2013/02/drowning.png"><img src="http://blog.killtheradio.net/wp-content/uploads/2013/02/drowning-300x234.png" alt="" title="Drowning can drop your health" width="300" height="234" class="alignright size-medium wp-image-895" /></a>The next step is to hurt yourself in Terraria. Yes, we&#8217;re going to to be playing the part of the masochist (but only for a little while). So jump off that cliff, dip your toe in lava, tango with a skeleton, whatever it takes&#8230;you want your health value to not be in its default position.</p>
<p>We&#8217;re going to search for that health value in Tsearch and as a starting point to try and find its exact location in memory.</p>
<p>Once we have lowered our health, open Tsearch. Make note of the value your health is in Terraria (and also make sure the game is paused).</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2013/02/search1.png"><img src="http://blog.killtheradio.net/wp-content/uploads/2013/02/search1-300x236.png" alt="" title="search1" width="300" height="236" class="alignright size-medium wp-image-899" /></a>Open TSearch and click on the little magnifying glass icon under the &#8220;Open process&#8221; button (the one furthest to the left). It will bring up a dialog that allows us to search for locations in memory based on value. We&#8217;re going to pull down the menu and select &#8220;range.&#8221; We use &#8220;range&#8221; instead of &#8220;exact value&#8221; because the health value regenerates, meaning at any given point it might be between two integers.</p>
<p>Let&#8217;s say our health is at 268 (like the image to the right). For value one, we enter 267, and value two 269. Then select Type: &#8220;2-byte.&#8221; This means we&#8217;re searching for a 2-byte value between 267 and 269. Hit &#8220;Ok.&#8221;</p>
<p>It&#8217;s going to find probably tens of thousands of values. Don&#8217;t worry, we can narrow these down. Open Terraria again and let your health regenerate (or hurt yourself again, being careful not to kill yourself). Once your health changes by a few points, open TSearch again.</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2013/02/search2.png"><img src="http://blog.killtheradio.net/wp-content/uploads/2013/02/search2-300x236.png" alt="" title="Narrowing down the results" width="300" height="236" class="alignright size-medium wp-image-903" /></a>We&#8217;re going to search again, but search within our current results. Click the magnifying glass directly to the right of the first one (it has &#8220;&#8230;&#8221; on it). This will open the same dialog before. Do a ranged search. Let&#8217;s say our new health value is 259, we&#8217;re going to search between 258 and 260. Run the search.</p>
<p>If you&#8217;re lucky, you&#8217;ll get only one result. If you&#8217;re unlucky and you get more than one search result, repeat the above filtering step one more time (change the health value, filter withing the current results, rinse &amp; repeat until only one value remains). Sometimes you&#8217;ll have to do many searches in a row to get the results you want.</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2013/02/success.png"><img src="http://blog.killtheradio.net/wp-content/uploads/2013/02/success-300x198.png" alt="" title="Great success!" width="300" height="198" class="alignright size-medium wp-image-904" /></a>Once you have your one search result, click on that entry in the search box and then click the green plus icon. It should add it to the list on the right. Double click under the &#8220;Description&#8221; field and name the value &#8220;health.&#8221; On the right, you&#8217;ll notice the value 259. Change it to 400. The click the box next to the value&#8217;s name (it should turn blue). You just froze your health at 400.</p>
<p>Go back into the game and hurt yourself. You&#8217;ll notice that your health goes down, but immediately bounces back after about half a second. Ladies and gentlemen, enjoy your infinite health =].</p>
<h2>Notes</h2>
<p>Hopefully this can answer some more questions about memory searching.</p>
<ul>
<li>This method only works while TSearch is open. Once you close it, the game will start tracking health again. If you want your hacks to persist, it&#8217;s a whole nother set of tools and processes, worthy of at least a few more posts. Keep in mind that if you use Steam, it will probably overwrite any changes you make to the exe. Such is life.</li>
<li>Memory searching works for values besides health. Be creative! You can get unlimited ammo, unlimited money, etc.</li>
<li>In Terraria, using this method for money can be tricky. If you move money from one of the money slots, it will change memory locations and you&#8217;ll lose your hack.</li>
<li>This method works for other games as well. I chose Terraria because it&#8217;s the only game I currently use it on.</li>
</ul>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/tricks-hacks/infinite-health-in-terraria-in-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling RethinkDB on Slackware (and probably other linuxes)</title>
		<link>http://blog.killtheradio.net/how-tos/compiling-rethinkdb-on-slackware-and-probably-other-linuxes/</link>
		<comments>http://blog.killtheradio.net/how-tos/compiling-rethinkdb-on-slackware-and-probably-other-linuxes/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 05:39:54 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[How to's]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[rethinkdb]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=866</guid>
		<description><![CDATA[UPDATE: Since RethinkDB 1.4, this post is pretty irrelevant. You can now just do: ./configure --allow-fetch make ALLOW_WARNINGS=1 This will build RethinkDB without a hitch. UPDATE: Check out Samuel Hughes&#8217; comment on compiling in Slack, which may make some of the below process simpler. Specifically, the section about editing the Makefile to not use static [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE</strong>: Since RethinkDB 1.4, this post is pretty irrelevant. You can now just do:</p>
<pre><code>./configure --allow-fetch
make ALLOW_WARNINGS=1
</code></pre>
<p>This will build RethinkDB without a hitch.</p>
<p><strong>UPDATE</strong>: Check out <a href="/how-tos/compiling-rethinkdb-on-slackware-and-probably-other-linuxes/#comments">Samuel Hughes&#8217; comment on compiling in Slack</a>, which may make some of the below process simpler. Specifically, the section about editing the Makefile to not use static libraries (apparently you can pass <code>RECOMMEND_STATIC=0</code> to the make process to do this instead).</p>
<p>So I&#8217;ve had a theoretical boner for <a href="http://www.rethinkdb.com/">RethinkDB</a> ever since reading about it. I decided to try and give it a go, but have had problems compiling. I&#8217;m going to try and give an overview of how to get it running. These instructions are aimed at people who don&#8217;t have a linux with the targeted packaging systems that RethinkDB currently supports (in other words, you&#8217;re stuck with compiling it yourself). The build process is slightly annoying (which is why I&#8217;m writing this guide). Slava from the RethinkDB team told me that they are working on a new build system, so hopefully we&#8217;ll soon be able to just to a <code>make</code>.</p>
<h2>Installing V8</h2>
<p>See the instructions for <a href="http://code.google.com/p/v8/wiki/BuildingWithGYP">building and installing V8</a>. They are pretty simple, but I believe you need Python (since they use GYP for the build):</p>
<pre><code>cd v8
make dependencies
make native
# do a manual installation
sudo mkdir -p /usr/local/v8/include /usr/local/v8/lib
sudo cp include/* /usr/local/v8/include
sudo cp out/native/lib.target/libv8.so /usr/local/v8/lib
</code></pre>
<p>Done (yeah, I know, my syntax highlighting is annoying).</p>
<h2>Building RethinkDB</h2>
<p>This was a bit trickier, but hey I&#8217;ve compiled alpha versions of Compiz on top of Slack before, this should be a cakewalk. It took some Makefile tweaking to get it running, so here&#8217;s how I did it. Note that you&#8217;ll need Python >= 2.7 to do the full make process (or else you&#8217;ll get &#8220;AttributeError: &#8216;module&#8217; object has no attribute &#8216;check_output&#8217;&#8221;). Slack 13.1 comes with 2.6.x so I had to compile it. Guess I need to upgrade soon. So grab the latest source:</p>
<pre><code>git clone git://github.com/rethinkdb/rethinkdb.git
cd rethinkdb
</code></pre>
<p>First things first, <code>src/Makefile</code> adds the option <code>-Werror</code> to the build. This is great, but causes the build to fail when it includes <code>v8.h</code> since there are unused variables. So for now, we&#8217;ll have to trust them that there are no other warnings/errors and remove this from the Makefile. So open <code>src/Makefile</code> in your favorite editor and change:</p>
<pre><code>RT_CXXFLAGS+=-Wall -Wextra -Werror -Wnon-virtual-dtor
</code></pre>
<p>to</p>
<pre><code>RT_CXXFLAGS+=-Wall -Wextra -Wnon-virtual-dtor
</code></pre>
<p>Also the Makefile tries to use static versions of some of the boost libs, but I only have dynamic versions on my system. So let&#8217;s comment out that line. Find this and <strong>comment it out</strong> (UPDATE: per <a href="/how-tos/compiling-rethinkdb-on-slackware-and-probably-other-linuxes/#comments">Samuel Hughes&#8217; comment below</a>, you can skip this step and pass <code>RECOMMEND_STATIC=0</code> to the make commend instead of hacking up the Makefile):</p>
<pre><code>STATIC_RECOMMENDS_INDIFFERENT:=boost_serialization boost_program_options
</code></pre>
<p>becomes</p>
<pre><code>#STATIC_RECOMMENDS_INDIFFERENT:=boost_serialization boost_program_options
</code></pre>
<p>Now let&#8217;s write a &#8220;simple&#8221; build script that wraps the make process:</p>
<pre><code>#!/bin/bash

BIN="`pwd -P`/support/usr/bin"
export PATH=$PATH:$BIN
export RT_CXXFLAGS="-I./include -I./src -I/usr/local/v8/include"
export RT_LDFLAGS="-L/usr/local/v8/lib ../support/usr/lib/libprotobuf.a ../support/usr/lib/libtcmalloc_minimal.a -lboost_program_options -lboost_serialization"
export STATIC_LIBRARY_PATHS=$RT_LDFLAGS
make \
        VERBOSE=1 \
        FETCH_INTERNAL_TOOLS=1 \
        RECOMMEND_STATIC=0 \
        STATIC_LIBRARY_PATHS="$RT_LDFLAGS"
</code></pre>
<p>Save it to <code>compile.sh</code> (or just <code>c</code> like I do because life is just too short to be typing &#8220;ompile.sh&#8221; all over the place) and run it.</p>
<p>That should do it! If all the post-build stuff (like installing js modules and crap) works fine, you should be able to start the db like so:</p>
<pre><code>LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/v8/lib/ ./build/release/rethinkdb
</code></pre>
<p>If that&#8217;s too cumbersome for you, you can either link <code>/usr/local/v8/lib/libv8.so</code> to <code>/usr/local/lib</code> or add <code>/usr/local/v8/lib</code> to your <code>/etc/ld.so.conf</code> file (and, of course, run <code>ldconfig</code> as root) and run rethinkdb freely, without the worries of library paths.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/how-tos/compiling-rethinkdb-on-slackware-and-probably-other-linuxes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Keyboard/mouse not working in Xorg on FreeBSD</title>
		<link>http://blog.killtheradio.net/tricks-hacks/keyboardmouse-not-working-in-xorg-on-freebsd/</link>
		<comments>http://blog.killtheradio.net/tricks-hacks/keyboardmouse-not-working-in-xorg-on-freebsd/#comments</comments>
		<pubDate>Mon, 14 Jan 2013 21:03:26 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Tricks/Hacks]]></category>
		<category><![CDATA[drivers]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[xorg]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=862</guid>
		<description><![CDATA[I recently installed FreeBSD 9.1-RELEASE on a VirtualBox VM to do some cl-async testing. I wanted to get Xorg running so I could edit code at a more &#8220;comfortable&#8221; resolution. I was able to get Xorg running fairly easily just by installing Xfce from /usr/ports. However, upon starting Xorg, my keyboard mouse would not work. [...]]]></description>
			<content:encoded><![CDATA[<p>I recently installed <a href="http://www.freebsd.org/">FreeBSD</a> 9.1-RELEASE on a <a href="https://www.virtualbox.org/">VirtualBox</a> VM to do some <a href="https://github.com/orthecreedence/cl-async">cl-async</a> testing. I wanted to get Xorg running so I could edit code at a more &#8220;comfortable&#8221; resolution. I was able to get Xorg running fairly easily just by installing <a href="http://www.xfce.org/">Xfce</a> from <code>/usr/ports</code>.</p>
<p>However, upon starting Xorg, my keyboard mouse would not work. I tried many things: following the <a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/x-config.html">steps in the handbook</a>, enabling/disabling hald, reconfiguring Xorg, etc. No luck. My Xorg.0.log was telling me that it couldn&#8217;t load the kdb/mouse drivers. After snooping around some forums, I found the solution:</p>
<ul>
<li>Install the <code>x11-drivers/xf86-input-keyboard</code> port</li>
<li>Install the <code>x11-drivers/xf86-input-mouse</code> port</li>
</ul>
<p>After doing this, all was right with the world. Just to clarify, I <em>am</em> using dbus/hald and more or less using the default configuration that <code>Xorg -configure</code> gave me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/tricks-hacks/keyboardmouse-not-working-in-xorg-on-freebsd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cl-async: Non-blocking, asynchronous programming for Common Lisp</title>
		<link>http://blog.killtheradio.net/technology/cl-async-non-blocking-asynchronous-programming-for-common-lisp/</link>
		<comments>http://blog.killtheradio.net/technology/cl-async-non-blocking-asynchronous-programming-for-common-lisp/#comments</comments>
		<pubDate>Tue, 27 Nov 2012 00:57:10 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[cl-async]]></category>
		<category><![CDATA[common lisp]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=849</guid>
		<description><![CDATA[A while ago, I released cl-async, a library for non-blocking programming in Common Lisp. I&#8217;ve been updating it a lot over the past month or two to add features and fix bugs, and it&#8217;s really coming along. My goal for this project is to create a general-purpose library for asynchronous programming in lisp. I think [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, I released <a href="http://orthecreedence.github.com/cl-async/">cl-async, a library for non-blocking programming in Common Lisp</a>. I&#8217;ve been updating it a lot over the past month or two to add features and fix bugs, and it&#8217;s really coming along.</p>
<p>My goal for this project is to create a general-purpose library for asynchronous programming in lisp. I think I have achieved this. With the finishing of the <a href="http://orthecreedence.github.com/cl-async/future">futures implementation</a>, not only is the library stable, but there is now a platform to build drivers on top of. This will be my next focal point over the next few months.</p>
<p>There are a few reasons I decided to build something new. Here&#8217;s an overview of the non-blocking libraries I could find:</p>
<ul>
<li><a href="http://common-lisp.net/project/iolib/">IOLib</a> &#8211; An IO library for lisp that has a built-in event loop, only works on *nix.</li>
<li><a href="https://github.com/sshirokov/hinge">Hinge</a> &#8211; General purpose, non-blocking library. Only works on *nix, requires <a href="http://software.schmorp.de/pkg/libev.html">libev</a> and <a href="http://www.zeromq.org/">ZeroMQ</a>.</li>
<li><a href="https://github.com/sykopomp/conserv">Conserv</a> &#8211; A nice layer on top of IOLib (so once again, only runs on *nix). Includes TCP client/server and HTTP server implementations. Very nice.</li>
<li><a href="http://common-lisp.net/projects/teepeedee2/">teepeedee2</a> &#8211; A non-blocking, performant HTTP server written on top of IOLib.</li>
</ul>
<p>I created cl-async because of all the available libraries, they are either non-portable, not general enough, have too many dependencies, or a combination of all three. I wanted a library that worked on Linux <em>and</em> Windows. I wanted a portable base to start from, and I also wanted tools to help make drivers.</p>
<p>Keeping all this in mind, I created <a href="https://github.com/orthecreedence/cl-libevent2">bindings for libevent2</a> and built cl-async on top of them. There were <a href="http://orthecreedence.github.com/cl-async/implementation-notes#libevent">many good reasons for choosing libevent2</a> over other libraries, such as <a href="http://software.schmorp.de/pkg/libev.html">libev</a> and <a href="https://github.com/joyent/libuv">libuv</a> (the backend for Node.js). Libuv would have been my first choice because it supports IOCP in Windows (libevent does not), however wrapping it in CFFI was like getting a screaming toddler to see the logic behind your decision to put them to bed. It could have maybe happened if I&#8217;d written a compatibility layer in C, but I wanted to have a <em>maximum</em> of 1 (one) dependency. <a href="http://libevent.org/">Libevent2</a> won. It&#8217;s fast, portable, easy to wrap in CFFI, and on top of that, has a lot of <em>really</em> nice features like an HTTP client/server, TCP buffering, DNS, etc etc etc. The list goes on. That means less programming for me.</p>
<p>Like I mentioned, my next goal is to build drivers. I&#8217;ve already built a few, but I don&#8217;t consider them stable enough to release yet. Drivers are the elephant in the room. Anybody can implement non-blocking IO for lisp, but the real challenge is converting everything that talks over TCP/HTTP to be async. If lisp <a href="http://orthecreedence.github.com/cl-async/2012/11/07/missing-coroutines-in-common-lisp.html">supported coroutines, this would be trivial</a>, but alas, we&#8217;re stuck with <a href="http://orthecreedence.github.com/cl-async/future#nicer-syntax">futures and the lovely syntax they afford</a>.</p>
<p>I&#8217;m going to start with drivers I use every day: beanstalk, redis, cl-mongo, drakma, zs3, and cl-smtp. These are the packages we use at work in our queue processing system (now threaded, soon to be evented + threaded). Once a few of these are done, I&#8217;ll update the <a href="http://orthecreedence.github.com/cl-async/drivers">cl-async drivers page</a> with best practices for building drivers (aka <a href="http://orthecreedence.github.com/cl-async/examples#future-example">wrapping async into futures</a>). Then I will take over the world.</p>
<p>Another goal I have is to build a real HTTP server on top of the bare <a href="http://orthecreedence.github.com/cl-async/http#http-server">http-server</a> implementation provided by cl-async. This will include nice syntax around routing (allowing REST interfaces), static file serving, etc.</p>
<p>Cl-async is still a work in progress, but it&#8217;s starting to become stabilized (both in lack of bugs and the API itself), so <a href="http://orthecreedence.github.com/cl-async/documentation">check out the docs</a> or the <a href="https://github.com/orthecreedence/cl-async">github project</a> and give it a shot. All you need is a lisp and libevent =].</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/cl-async-non-blocking-asynchronous-programming-for-common-lisp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cl-mongo and multithreading</title>
		<link>http://blog.killtheradio.net/technology/cl-mongo-and-multithreading/</link>
		<comments>http://blog.killtheradio.net/technology/cl-mongo-and-multithreading/#comments</comments>
		<pubDate>Sun, 08 Jul 2012 06:56:26 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[common lisp]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=832</guid>
		<description><![CDATA[We&#8217;re building a queuing system for Musio written in common lisp. To be accurate, we already built a queuing system in common lisp, and I recently needed to add a worker to it that communicates with MongoDB via cl-mongo. Each worker spawns four worker threads, each thread grabbing jobs from beanstalkd via cl-beanstalk. During my testing, each [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re building a queuing system for <a href="http://musio.com">Musio</a> written in common lisp. To be accurate, we already built a queuing system in common lisp, and I recently needed to add a worker to it that communicates with <a href="http://www.mongodb.org/">MongoDB</a> via <a href="https://github.com/fons/cl-mongo">cl-mongo</a>. Each worker spawns four worker threads, each thread grabbing jobs from <a href="http://kr.github.com/beanstalkd/">beanstalkd</a> via <a href="https://github.com/antifuchs/cl-beanstalk">cl-beanstalk</a>. During my testing, each worker was updating a Mongo collection with some values scraped from our site. However, after a few seconds of processing jobs, the worker threads begin to spit out USOCKET errors and eventually <a href="http://ccl.clozure.com/">Clozure CL</a> enters it&#8217;s debugger of death (ie, lisp&#8217;s version of a segfault). <a href="http://www.sbcl.org/">SBCL</a> didn&#8217;t fare too much better, either.</p>
<p>The way cl-mongo&#8217;s connections work is that it has a global hash table that holds connections: cl-mongo::*mongo-registry*. When the threads are all running and communicating with MongoDB, they are using the same hash table without any inherent locking or synchronization. There are a few options to fix this. You can implement a connection pool that supports access from multiple threads (complicated), you can give each thread its own connection and force the each thread to use its connection when communicating, or you can take advantage of special variables in lisp (the easiest, simplest, and most elegant IMO). Let&#8217;s check out the last option.</p>
<p>Although it&#8217;s not in the CL spec, just about all implementations allow you to have global thread-local variables by using (defparameter) or (defvar), both of which create special variables (read: dynamic variables, as opposed to lexical). Luckily, cl-mongo uses defvar to create *mongo-registry*. This means in our worker, we can re-bind this variable above the top level loop using (let) and all subsequent calls to MongoDB will use our new thread-local version of *mongo-registry* instead of the global one that all the threads we&#8217;re bumping into each other using:</p>
<pre>
<span class="Comment">;; Main worker loop, using global *mongo-registry* (broken)</span>
<span class="Special">(</span><span class="Statement">defun</span> start-worker <span class="Special">()</span>
  <span class="Special">(</span><span class="Statement">loop</span>
    <span class="Special">(</span><span class="Statement">let</span> <span class="Special">((</span>job <span class="Special">(</span>get-job<span class="Special">)))</span>
      <span class="Special">(</span><span class="Statement">let</span> <span class="Special">((</span>results <span class="Special">(</span>process-job job<span class="Special">)))</span>
        <span class="Comment">;; this uses the global registry. not good if running multiple threads.</span>
        <span class="Special">(</span>with-mongo-connection <span class="Special">(</span>:db <span class="Constant">&quot;musio&quot;</span><span class="Special">)</span>
          <span class="Special">(</span>db.save <span class="Constant">&quot;scraped&quot;</span> results<span class="Special">))))))</span></pre>
<p>New version:</p>
<pre><span class="Comment">;; Replace *mongo-registry* above worker loop, creating a local version of the</span>
<span class="Comment">;; registry for this thread.</span>
<span class="Special">(</span><span class="Statement">defun</span> start-worker <span class="Special">()</span>
  <span class="Comment">;; setting to any value via let will re-create the variable as a local thread</span>
  <span class="Comment">;; variable. nil will do just fine.</span>
  <span class="Special">(</span><span class="Statement">let</span> <span class="Special">((</span>cl-mongo::*mongo-registry* <span class="Statement">nil</span><span class="Special">))</span>
    <span class="Special">(</span><span class="Statement">loop</span>
      <span class="Special">(</span><span class="Statement">let</span> <span class="Special">((</span>job <span class="Special">(</span>get-job<span class="Special">)))</span>
        <span class="Special">(</span><span class="Statement">let</span> <span class="Special">((</span>results <span class="Special">(</span>process-job job<span class="Special">)))</span>
          <span class="Comment">;; with-mongo-connection now uses the local registry, which stops the</span>
          <span class="Comment">;; threads from touching each other.</span>
          <span class="Special">(</span>with-mongo-connection <span class="Special">(</span>:db <span class="Constant">&quot;musio&quot;</span><span class="Special">)</span>
            <span class="Special">(</span>db.save <span class="Constant">&quot;scraped&quot;</span> results<span class="Special">)))))))</span>
</pre>
<p>BOOM everything works great after this change, and it was only a one line change. It may not be as efficient as connection pooling, but that&#8217;s a lot more prone to strange errors and synchronization issues than just segregating the connections from each other and calling it a day. One issue: *mongo-registry* is not exported by cl-mongo, which is why we access it via cl-mongo::*mongo-registry* (notice the double colon instead of single). This means in future versions, the variable name may change, breaking our above code. So, don&#8217;t update cl-mongo without testing. Not hard.</p>
<p>Hopefully this helps a few people out, let me know if you have better solutions to this issue!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/cl-mongo-and-multithreading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Email is not broken: It&#8217;s a framework, not an application</title>
		<link>http://blog.killtheradio.net/technology/email-is-not-broken-its-a-framework-not-an-application/</link>
		<comments>http://blog.killtheradio.net/technology/email-is-not-broken-its-a-framework-not-an-application/#comments</comments>
		<pubDate>Sun, 15 Apr 2012 08:16:28 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=816</guid>
		<description><![CDATA[I&#8217;ve been seeing a lot of posts on the webz lately about how we can fix email. I have to say, I think it&#8217;s a bit short-sighted. People are saying it has outgrown it&#8217;s original usage, or it contains bad error messages, or it&#8217;s not smart about the messages received. These are very smart people, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been seeing a lot of posts on the webz lately about how we can fix email. I have to say, I think it&#8217;s a bit short-sighted.</p>
<p>People are saying it has <a href="http://paulgraham.com/ambitious.html">outgrown it&#8217;s original usage</a>, or it contains <a href="http://dewith.com/2012/this-is-the-mail-system/">bad error messages</a>, or <a href="http://joncalhoun.posterous.com/email-sucks-this-is-how-we-fix-it">it&#8217;s not smart about the messages received</a>.</p>
<p>These are very smart people, with real observations. The problem is, their observations are misplaced.</p>
<h2>What email is</h2>
<p>Email is a distributed, asynchronous messaging protocol. It does this well. It does this <em>very</em> well. So well, I&#8217;m getting a boner thinking about it. You send a message and it either goes where it&#8217;s supposed to, or you get an error message back. That&#8217;s it, that&#8217;s email. It&#8217;s simple. It works.</p>
<p>There&#8217;s no company controlling all messages and imposing their will on the ecosystem as a whole. There&#8217;s no single point of failure. It&#8217;s beautifully distributed and functions near-perfectly.</p>
<h2>The problem</h2>
<p>So why does it suck so much? It doesn&#8217;t. It&#8217;s awesome. The problem is the way people view it. Most of the perceived suckiness comes from its simplicity. It doesn&#8217;t manage your TODOs. It doesn&#8217;t have built-in calendaring. It doesn&#8217;t give you oral pleasure (personally I think this should be built into the spec though). So why don&#8217;t we build all these great things into it if they don&#8217;t exist? We could add TODOs and calendaring and dick-sucking to email!!</p>
<p>Because that&#8217;s a terrible idea. People are viewing email as an application; one that has limited features and needs to be extended so it supports more than just <em>stupid</em> messages.</p>
<p><strong>This is wrong.</strong></p>
<p>We need to view email as a framework, <em>not an application</em>. It is used for sending messages. That&#8217;s it. It does this reliably and predictably.</p>
<p>Replacing email with &#8220;smarter&#8221; features will inevitably leave people out. I understand the desire to have email just be one huge TODO list. But sometimes I just want to send a fucking message, not &#8220;make a TODO.&#8221; Boom, I just &#8220;broke&#8221; the new email.</p>
<p>Email works <em>because</em> it does nothing but messaging.</p>
<h2>How do we fix it then?</h2>
<p>We fix it by building smart clients. Let&#8217;s take a look at some of our email-smart friends.</p>
<p>Outlook has built-in calendaring. <strong>BUT WAIT!!!!!</strong> Calendaring isn&#8217;t part of email!!1 No, it&#8217;s not.</p>
<p>Gmail has labels. You can categorize your messages by using tags essentially. Also, based on usage patterns, Gmail can give weight to certain messages. <em>That&#8217;s not part of email either!!</em> No, my friend, it&#8217;s not.</p>
<p>Xobni also has built incredible contact-management and intelligence features on top of email. How do they know it&#8217;s time to take your daily shit before you do? <em>Defecation scheduling is NOT part of the email spec!!</em></p>
<p>How have these companies made so much fucking money off of adding features to email that <em>are not part of email?</em></p>
<h2>It&#8217;s all in the client</h2>
<p>They do it by building smart clients! As I said, you can send any message your heart desires using email. You can send JSON messages with a TODO payload and attach a plaintext fallback. If both clients understand it, then <strong>BAM!</strong> Instant TODO list protocol. There, you just fixed email. Easy, no? Why, with the right client, <em>you could fly a fucking space shuttle with email.</em> That&#8217;s right, dude, a fucking space shuttle.</p>
<p>If your client can create a message and send it, and the receiving client can decode it, <em>you can build any protocol you want on top of email.</em></p>
<p>That&#8217;s it. Use your imaginations. I&#8217;ll say it one more time:</p>
<h2>There&#8217;s nothing to fix</h2>
<p>Repeat after me: &#8220;There&#8217;s nothing to fix!&#8221; If you have a problem with email, fork a client or <em>build your own!</em> Nobody&#8217;s stopping you from &#8220;fixing&#8221; email. Many people have made a <em>lot</em> of cash by &#8220;fixing&#8221; email.</p>
<p>We don&#8217;t have to sit in fluorescent-lit, university buildings deliberating for hours on end about how to change the spec to fit everyone&#8217;s new needs. We don&#8217;t need 100 stupid startups &#8220;disrupting&#8221; the &#8220;broken&#8221; email system with their new protocols, that will inevitably end up being  a proprietary, non-distributed, &#8220;ad hoc, informally-specified, bug-ridden, slow implementation of half of&#8221; the current email system.</p>
<p><em>Please</em> don&#8217;t try to fix email, you&#8217;re just going to fuck it up!! Trust me, you can&#8217;t do any better. Instead, let&#8217;s build all of our awesome new features <em>on top of an already beautifully-working system</em> by making smarter clients.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/email-is-not-broken-its-a-framework-not-an-application/feed/</wfw:commentRss>
		<slash:comments>69</slash:comments>
		</item>
		<item>
		<title>MongoDB: &#8220;can&#8217;t map file memory &#8211; mongo requires 64 bit build for larger datasets&#8221; fix</title>
		<link>http://blog.killtheradio.net/how-tos/mongodb-cant-map-file-memory-mongo-requires-64-bit-build-for-larger-datasets-fix/</link>
		<comments>http://blog.killtheradio.net/how-tos/mongodb-cant-map-file-memory-mongo-requires-64-bit-build-for-larger-datasets-fix/#comments</comments>
		<pubDate>Sat, 07 Apr 2012 02:35:59 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[How to's]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=809</guid>
		<description><![CDATA[So I started getting this annoying error on our staging server today. I searched all over and people&#8217;s only answer was &#8220;use a 64-bit server.&#8221; Ok, but my data is less than 200MB so don&#8217;t tell me my server can&#8217;t handle it. To make a long story short, some of the Mongo data files in [...]]]></description>
			<content:encoded><![CDATA[<p>So I started getting this annoying error on our staging server today. I searched all over and people&#8217;s only answer was &#8220;use a 64-bit server.&#8221; Ok, but my data is less than 200MB so don&#8217;t tell me my server can&#8217;t handle it.</p>
<p>To make a long story short, some of the Mongo data files in the datadir were owned by root, not the &#8220;mongodb&#8221; user. I chowned them back to &#8220;mongodb&#8221; and everything went back to normal. Why this happened, I don&#8217;t know, but at least there&#8217;s a fix ;-).</p>
<pre><span class="lnr">1 </span>chown <span class="Special">-R</span> mongodb:mongodb /srv/mongo-datadir</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/how-tos/mongodb-cant-map-file-memory-mongo-requires-64-bit-build-for-larger-datasets-fix/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Vim syntax highlighting (void.vim)</title>
		<link>http://blog.killtheradio.net/reviews/vim-syntax-highlighting-void-vim/</link>
		<comments>http://blog.killtheradio.net/reviews/vim-syntax-highlighting-void-vim/#comments</comments>
		<pubDate>Thu, 22 Mar 2012 00:30:39 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=793</guid>
		<description><![CDATA[A while ago I created a vim highlighting script called void.vim. I&#8217;ve been using it for over a year now and just updated some things that have been bothering me recently, so feel free to check it out. This is my main color scheme I use for everything, and I created it to be be [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I created a <a href="http://www.vim.org/scripts/script.php?script_id=3334">vim highlighting script called void.vim</a>. I&#8217;ve been using it for over a year now and just updated some things that have been bothering me recently, so feel free to check it out. This is my main color scheme I use for everything, and I created it to be be easy on the eyes but to actually look nice too. A lot of the color schemes I&#8217;ve used seem to have been really loud or have a bad choice of colors. <a href="http://www.vim.org/scripts/script.php?script_id=3334">Void</a> is my favorite.</p>
<p>Here&#8217;s a sample (created with vim&#8217;s <code>:TOhtml</code> command):</p>
<pre>
<span class="lnr"> 1 </span><span class="Comment">/**</span>
<span class="lnr"> 2 </span><span class="Comment"> * Trigger an event for this object, which in turn runs all callbacks for that</span>
<span class="lnr"> 3 </span><span class="Comment"> * event WITH all parameters passed in to this function.</span>
<span class="lnr"> 4 </span><span class="Comment"> *</span>
<span class="lnr"> 5 </span><span class="Comment"> * For instance, you could do:</span>
<span class="lnr"> 6 </span><span class="Comment"> * mymodel.bind(&quot;destroy&quot;, this.removeFromView.bind(this));</span>
<span class="lnr"> 7 </span><span class="Comment"> * mymodel.trigger(&quot;destroy&quot;, &quot;omg&quot;, &quot;lol&quot;, &quot;wtf&quot;);</span>
<span class="lnr"> 8 </span><span class="Comment"> *</span>
<span class="lnr"> 9 </span><span class="Comment"> * this.removeFromView will be called with the arguments &quot;omg&quot;, &quot;lol&quot;, &quot;wtf&quot;.</span>
<span class="lnr">10 </span><span class="Comment"> *</span>
<span class="lnr">11 </span><span class="Comment"> * Note that any trigger event will also trigger the &quot;all&quot; event. the idea</span>
<span class="lnr">12 </span><span class="Comment"> * being that you can subscribe to anything happening on an object.</span>
<span class="lnr">13 </span><span class="Comment"> */</span>
<span class="lnr">14 </span>trigger: <span class="Identifier">function</span>(ev)
<span class="lnr">15 </span><span class="Identifier">{</span>
<span class="lnr">16 </span>    <span class="Identifier">var</span> args   =   shallow_array_clone(<span class="Type">Array</span>.from(<span class="Identifier">arguments</span>));
<span class="lnr">17 </span>    <span class="Identifier">[</span>ev, <span class="Constant">'all'</span><span class="Identifier">]</span>.each(<span class="Identifier">function</span>(type) <span class="Identifier">{</span>
<span class="lnr">18 </span>        <span class="Statement">if</span>(!<span class="Identifier">this</span>._events<span class="Identifier">[</span>type<span class="Identifier">]</span>) <span class="Statement">return</span>;
<span class="lnr">19 </span>        <span class="Type">Array</span>.clone(<span class="Identifier">this</span>._events<span class="Identifier">[</span>type<span class="Identifier">]</span>).each(<span class="Identifier">function</span>(callback) <span class="Identifier">{</span>
<span class="lnr">20 </span>            callback.apply(<span class="Identifier">this</span>, (type == <span class="Constant">'all'</span>) ? args : args.slice(1));
<span class="lnr">21 </span>        <span class="Identifier">}</span>, <span class="Identifier">this</span>);
<span class="lnr">22 </span>    <span class="Identifier">}</span>, <span class="Identifier">this</span>);
<span class="lnr">23 </span>
<span class="lnr">24 </span>    <span class="Statement">return</span> <span class="Identifier">this</span>;
<span class="lnr">25 </span><span class="Identifier">}</span>
</pre>
<p>This is javascript, but I also use it for HTML, CSS, php, and lisp. Note that all code highlighting on this blog is done via vim with this color scheme.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/reviews/vim-syntax-highlighting-void-vim/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TMUX/screen and root shells: a new trick I just learned (TMOUT)</title>
		<link>http://blog.killtheradio.net/technology/tmuxscreen-and-root-shells-a-new-trick-i-just-learned-tmout/</link>
		<comments>http://blog.killtheradio.net/technology/tmuxscreen-and-root-shells-a-new-trick-i-just-learned-tmout/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 22:42:54 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=776</guid>
		<description><![CDATA[I&#8217;m currently doing some server management. My current favorite tool is TMUX, which among many other things, allows you to save your session even if you are disconnected, split your screen into panes, etc etc. If it sounds great, that&#8217;s because it is. Every sysadmin would benefit from using TMUX (or it&#8217;s cousin, GNU screen). [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently doing some server management. My current favorite tool is <a href="http://tmux.sourceforge.net/">TMUX</a>, which among many other things, allows you to save your session even if you are disconnected, split your screen into panes, etc etc. If it sounds great, that&#8217;s because it is. Every sysadmin would benefit from using TMUX (or it&#8217;s cousin, <a href="http://www.gnu.org/software/screen/">GNU screen</a>).</p>
<p>There&#8217;s a security flaw though. Let&#8217;s say I log in as user &#8220;andrew&#8221; and attach to my previous TMUX session: <code>tmux attach</code>. Now I have to run a number of commands as root. Well, prefixing every command with sudo and manually typing in all the /sbin/ paths to each executable it a pain in the ass. I know this is a bad idea, but I&#8217;ll often spawn a root shell. Let&#8217;s say I spawn a root shell in a TMUX session, then go do something else, fully intending log out later, but I forget. My computer disconnects, and I forget there&#8217;s a root shell sitting there.</p>
<p>If someone manages to compromise the machine, and gain access to my user account, getting a root shell is as easy as doing <code>tmux attach</code>. Oops.</p>
<p>Well, I just found out you can timeout a shell after X seconds of inactivity, which is perfect for this case. As root:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">echo</span><span class="Constant"> -e </span><span class="Operator">&quot;</span><span class="Special">\n</span><span class="Constant"># logout after 5 minutes of inactivity</span><span class="Special">\n</span><span class="Constant">export TMOUT=300</span><span class="Special">\n</span><span class="Operator">&quot;</span><span class="Constant"> </span><span class="Operator">&gt;&gt;</span> /root/.bash_profile
</pre>
<p>Now I can open root shells until my ass bleeds, and after 5 minutes of inactivity, it will log out back into my normal user account.</p>
<p>A good sysadmin won&#8217;t make mistakes. A great sysadmin will make mistakes self-correct ;-].</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/tmuxscreen-and-root-shells-a-new-trick-i-just-learned-tmout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick cache &#8211; my new favorite wordpress cache</title>
		<link>http://blog.killtheradio.net/reviews/quick-cache-my-new-favorite-wordpress-cache/</link>
		<comments>http://blog.killtheradio.net/reviews/quick-cache-my-new-favorite-wordpress-cache/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 03:37:22 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=772</guid>
		<description><![CDATA[I just spent ~1 hour installing (and uninstalling) various cache plugins for WP and each of them sucking in their own special way. The main problem is that they don&#8217;t work with PHP in safe_mode, which Nearly Free Speech turns on. This is limiting because it doesn&#8217;t let PHP make directory trees on its own, [...]]]></description>
			<content:encoded><![CDATA[<p>I just spent ~1 hour installing (and uninstalling) various cache plugins for WP and each of them sucking in their own special way. The main problem is that they don&#8217;t work with PHP in safe_mode, which <a href="https://nearlyfreespeech.net">Nearly Free Speech</a> turns on. This is limiting because it doesn&#8217;t let PHP make directory trees on its own, the directories have to be created by hand and then have special permissions applied to them. Most caching plugins create a ton of directory trees in the wp-content/cache/ folder, rendering them useless unless for my purposes.</p>
<p>I just installed <a href="http://wordpress.org/extend/plugins/quick-cache/">QuickCache</a> which uses flat files installed into the wp-content/cache/ folder. Here was my installation:</p>
<ul>
<li>Upload the plugin to wp-content/plugins/</li>
<li>In SSH:
<pre>chgrp web wp-content/
mkdir wp-content/cache
chgrp web wp-content/cache</pre>
</li>
<li>Enable plugin in admin.</li>
<li>Done!</li>
</ul>
<p>Stupid easy, works really well. It seems commonplace for people to develop wordpress plugins with their error reporting set to the absolute lowest and display_errors=0. I don&#8217;t appreciate this as it usually produces broken code. I&#8217;m thankful that the QuickCache authors put in the effort to, like, actually make it work. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/reviews/quick-cache-my-new-favorite-wordpress-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Composer.js &#8211; a new Javascript MVC framework for Mootools</title>
		<link>http://blog.killtheradio.net/technology/composer-js-a-new-javascript-mvc-framework-for-mootools/</link>
		<comments>http://blog.killtheradio.net/technology/composer-js-a-new-javascript-mvc-framework-for-mootools/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 00:12:56 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[releases]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=745</guid>
		<description><![CDATA[So my brother Jeff and I are building to Javascript-heavy applications at the moment (heavy as in all-js front-end). We needed a framework that provides loose coupling between the pieces, event/message-based invoking, and maps well to our data structures. A few choices came up, most notably Backbone.js and Spine. These are excellent frameworks. It took [...]]]></description>
			<content:encoded><![CDATA[<p>So my brother <a href="http://zinn-x.com">Jeff</a> and I are building to Javascript-heavy applications at the moment (heavy as in all-js front-end). We needed a framework that provides loose coupling between the pieces, event/message-based invoking, and maps well to our data structures. A few choices came up, most notably <a href="http://documentcloud.github.com/backbone/">Backbone.js</a> and <a href="http://spinejs.com/">Spine</a>. These are excellent frameworks. It took a while to wrap my head around the paradigms because I was so used to writing five layers deep of embedded events. Now that I have the hang of it, I can&#8217;t think of how I ever lived without it. There&#8217;s just one large problem&#8230;these libraries are for <a href="http://jquery.com/">jQuery</a>.</p>
<p>jQuery isn&#8217;t bad. We&#8217;ve always gravitated towards <a href="http://mootools.net/">Mootools</a> though. Mootools is a framework to make javascript more usable, jQuery is nearly a completely new language in itself written on top of javascript (and mainly for DOM manipulation). Both have their benefits, but we were always good at javascript before the frameworks came along, so something that made that knowledge more useful was an obvious choice for us. </p>
<p>I&#8217;ll also say that after spending some time with these frameworks and being sold (I especially liked Backbone.js) I gave jQuery another shot. I ported all of our common libraries to jQuery and I spent a few days getting used to it and learning how to do certain things. I couldn&#8217;t stand it. The thing that got me most was that there is no distinction between a DOM node and a collection of DOM nodes. Maybe I&#8217;m just too used to Moo (4+ years).</p>
<h2 style="font-weight: normal;"><a href="http://lyonbros.github.com/composer.js/">Composer.js &raquo;</a></h2>
<p><a href="http://lyonbros.github.com/composer.js/"><img src="http://lyonbros.github.com/composer.js/composer.gif" width="254" height="250" alt="composer" style="float: right; padding: 0 0 0 5px;" /></a>So we decided to roll our own. <a href="http://github.com/lyonbros/composer.js">Composer.js</a> was born. It merges aspects of Spine and Backbone.js into a Mootools-based MVC framework. It&#8217;s still in progress, but we&#8217;re solidifying a lot of the API so developers won&#8217;t have to worry about switching their code when v1 comes around.</p>
<p><a href="http://lyonbros.github.com/composer.js/">Read the docs</a>, give it a shot, and let us know if you have any problems or questions.</p>
<p>Also, yes, we blatantly ripped off Backbone.js in a lot of places. We&#8217;re pretty open about it, and also pretty open about attributing everything we took. They did some really awesome things. We didn&#8217;t necessarily want to do it differently more than we wanted a supported Mootools MVC framework that works like Backbone.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/composer-js-a-new-javascript-mvc-framework-for-mootools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rekon &#8211; a simple Riak GUI</title>
		<link>http://blog.killtheradio.net/technology/rekon-a-simple-riak-gui/</link>
		<comments>http://blog.killtheradio.net/technology/rekon-a-simple-riak-gui/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 06:17:34 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=735</guid>
		<description><![CDATA[I was looking around for Riak information when I stumbled (not via stumble, but actually doing my own blundering) across a blog post that mentioned a Riak GUI. I checked it out. Install is simple and oddly enough, the tool uses only javascript and Riak (no web server needed). I have to say I&#8217;m thoroughly [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking around for Riak information when I stumbled (not via stumble, but actually doing my own blundering) across a <a href="http://jbbarth.com/archives/2011/4/21/a_first_sight_at_riak/">blog post</a> that mentioned a <a href="https://github.com/adamhunter/rekon">Riak GUI</a>. I checked it out. Install is simple and oddly enough, the tool uses only javascript and Riak (no web server needed). I have to say I&#8217;m thoroughly impressed by it. Currently the tool doesn&#8217;t do a ton besides listing buckets, keys, and stats, but you can edit your data inline and delete objects. It also supports <a href="http://wiki.basho.com/Luwak.html">Luwak</a>, which I have no first-hand experience with and was unable to try out.  </p>
<p>One thing I thought that was missing was a way to run a <a href="http://wiki.basho.com/MapReduce.html">map-reduce</a> on the cluster via text input boxes for the functions. It would make writing and testing them a bit simpler I think, but then again it would be easy enough to write this myself in PHP or even JS, so maybe I&#8217;ll add it in. <a href="http://wiki.basho.com/Riak-Search.html">Search</a> integration would be nice too, although going to 127.0.0.1:8098/solr/[bucket]search?&#8230; is pretty stupid easy.</p>
<p>All in all, a <a href="https://github.com/adamhunter/rekon">great tool</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/rekon-a-simple-riak-gui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A small modification to John Resig&#8217;s JS micro-templating (to make it like PHP)</title>
		<link>http://blog.killtheradio.net/technology/a-small-modification-to-john-resigs-js-micro-templating-to-make-it-like-php/</link>
		<comments>http://blog.killtheradio.net/technology/a-small-modification-to-john-resigs-js-micro-templating-to-make-it-like-php/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 22:17:52 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[templating]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=718</guid>
		<description><![CDATA[John Resign created some incredibly wonderful Javascript code for templating. It&#8217;s so terse that it almost shouldn&#8217;t work&#8230;but it does. I&#8217;ve been using it on a lot of front-end JS apps lately, and realized I could make a few changes and improvements. First off, I don&#8217;t like &#60;% asp style tags %&#62;. It reminds me [...]]]></description>
			<content:encoded><![CDATA[<p>John Resign created some <a href="http://ejohn.org/blog/javascript-micro-templating/">incredibly wonderful Javascript code for templating</a>. It&#8217;s so terse that it almost shouldn&#8217;t work&#8230;but it does. I&#8217;ve been using it on a lot of front-end JS apps lately, and realized I could make a few changes and improvements.</p>
<p>First off, I don&#8217;t like &lt;% asp style tags %&gt;. It reminds me of programming ASP. It reminds me of a trip through hell I&#8217;ve taken too many times. I changed it to use PHP-style tags instead:</p>
<pre>
<span class="lnr">1 </span><span class="Identifier">&lt;</span><span class="Statement">ul</span><span class="Identifier"> </span><span class="Type">class</span><span class="Identifier">=</span><span class="Constant">&quot;</span><span class="Special">&lt;?</span><span class="Operator">=</span>myclass<span class="Special">?&gt;</span><span class="Constant">&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">2 </span>    <span class="Special">&lt;?</span> <span class="Statement">for</span><span class="Special">(</span><span class="Statement">var</span> i <span class="Operator">=</span> <span class="Constant">0</span>; i <span class="Statement">&lt;</span> items<span class="Operator">.</span>length; i<span class="Operator">++</span><span class="Special">)</span> <span class="Special">{</span> <span class="Special">?&gt;</span>
<span class="lnr">3 </span>        <span class="Identifier">&lt;</span><span class="Statement">li</span><span class="Identifier">&gt;</span><span class="Special">&lt;?</span><span class="Operator">=</span>items<span class="Special">[</span>i<span class="Special">]</span><span class="Operator">.</span>name<span class="Special">?&gt;</span>
<span class="lnr">4 </span>    <span class="Special">&lt;?</span> <span class="Special">}</span> <span class="Special">?&gt;</span>
<span class="lnr">5 </span><span class="Identifier">&lt;/</span><span class="Statement">ul</span><span class="Identifier">&gt;</span>
</pre>
<p>This makes it easier for me to type. I also made one further modification. Adding $ in front of your variables will check if they are undefined before using them, and if not defined will return them as null:</p>
<pre>
<span class="lnr">1 </span>Hello, <span class="Special">&lt;?</span><span class="Operator">=</span><span class="Operator">$</span><span class="Identifier">name</span><span class="Special">?&gt;</span>.
<span class="lnr">2 </span><span class="Special">&lt;?</span> <span class="Statement">if</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">user</span><span class="Operator">.</span>friends<span class="Special">)</span> <span class="Special">{</span> <span class="Special">?&gt;</span>
<span class="lnr">3 </span>    You have <span class="Special">&lt;?</span><span class="Operator">=</span><span class="Operator">$</span><span class="Identifier">user</span><span class="Operator">.</span>friends<span class="Operator">.</span>length<span class="Special">?&gt;</span> friends.
<span class="lnr">4 </span><span class="Special">&lt;?</span> <span class="Special">}</span> <span class="Special">?&gt;</span>
</pre>
<p>The if statement above will compile to </p>
<pre>
<span class="lnr">1 </span><span class="Statement">if</span>((<span class="Operator">typeof</span>(user.friends) == <span class="Constant">'undefined'</span> ? <span class="Statement">null</span> : user.friends)) <span class="Identifier">{</span> ...
</pre>
<p>This allows some simple usages of undefined variables, such as &#8220;if(undefined_var) { &#8230; } else { &#8230; }&#8221; which actually pops up a lot. You still can&#8217;t access non-existent properties of variables that aren&#8217;t defined, but this should catch a lot of errors that would otherwise turn your code into a bunch of if(typeof &#8230;)&#8217;s. </p>
<p>Here&#8217;s the code (for brevity, I left out all the caching stuff that makes this fast):</p>
<pre>
<span class="lnr"> 1 </span><span class="Identifier">var</span> template    =   <span class="Constant">'&lt;h1&gt;&lt;?=$title?&gt;&lt;/h1&gt; ...'</span>;
<span class="lnr"> 2 </span>template        =   template.replace(<span class="Constant">/(\r\n|\n\r)/g</span>, <span class="Constant">&quot;</span><span class="Special">\n</span><span class="Constant">&quot;</span>);
<span class="lnr"> 3 </span><span class="Identifier">var</span> fnstr       =
<span class="lnr"> 4 </span>    <span class="Constant">&quot;var ___p=[],print=function(){___p.push.apply(___p,arguments);};&quot;</span> +
<span class="lnr"> 5 </span>    <span class="Constant">&quot;with(obj) {___p.push('&quot;</span> +
<span class="lnr"> 6 </span>    template
<span class="lnr"> 7 </span>        <span class="Comment">// fix single quotes in html (escape them)</span>
<span class="lnr"> 8 </span>        .replace(<span class="Constant">/(^|\?&gt;)([\s\S]*?)($|&lt;\?)/g</span>, <span class="Identifier">function</span>(match) <span class="Identifier">{</span>
<span class="lnr"> 9 </span>            <span class="Statement">return</span> match.replace(<span class="Constant">/'/g</span>, <span class="Constant">'</span><span class="Special">\\\'</span><span class="Constant">'</span>);
<span class="lnr">10 </span>        <span class="Identifier">}</span>)
<span class="lnr">11 </span>        <span class="Comment">// implement safe usage of $varname</span>
<span class="lnr">12 </span>        .replace(<span class="Constant">/&lt;\?([\s\S]*?)\?&gt;/g</span>, <span class="Identifier">function</span>(match) <span class="Identifier">{</span>
<span class="lnr">13 </span>            <span class="Statement">return</span> match.replace(<span class="Constant">/\$([a-z_][a-z0-9_\.]+)/gi</span>, <span class="Constant">'(typeof($1) == &quot;undefined&quot; ? null : $1)'</span>).replace(<span class="Constant">/[\r\n]+/g</span>, <span class="Constant">' '</span>);
<span class="lnr">14 </span>        <span class="Identifier">}</span>)
<span class="lnr">15 </span>        .replace(<span class="Constant">/\r?\n/g</span>, <span class="Constant">'___::NEWLINE::___'</span>)
<span class="lnr">16 </span>        .split(<span class="Constant">&quot;&lt;?&quot;</span>).join(<span class="Constant">'___::TABBBBB::___'</span>)
<span class="lnr">17 </span>        .replace(<span class="Constant">/((^|\?&gt;)(?!=___::TABBBBB::___))'/g</span>, <span class="Constant">&quot;$1___::SLASHR::___&quot;</span>)
<span class="lnr">18 </span>        .replace(<span class="Constant">/___::TABBBBB::___=\s*\$?(.*?)\?&gt;/g</span>, <span class="Constant">&quot;',$1,'&quot;</span>)
<span class="lnr">19 </span>        .split(<span class="Constant">'___::TABBBBB::___'</span>).join(<span class="Constant">&quot;');&quot;</span>)
<span class="lnr">20 </span>        .split(<span class="Constant">'?&gt;'</span>).join(<span class="Constant">&quot;___p.push('&quot;</span>)
<span class="lnr">21 </span>        .split(<span class="Constant">&quot;___::SLASHR::___&quot;</span>).join(<span class="Constant">&quot;</span><span class="Special">\\</span><span class="Constant">'&quot;</span>)
<span class="lnr">22 </span>        .replace(<span class="Constant">/___::NEWLINE::___/g</span>, <span class="Constant">'</span><span class="Special">\'</span><span class="Constant">+ &quot;</span><span class="Special">\\</span><span class="Constant">n&quot; + </span><span class="Special">\'</span><span class="Constant">'</span>) +
<span class="lnr">23 </span>        <span class="Constant">&quot;');}&quot;</span> + <span class="Constant">&quot;return ___p.join('');&quot;</span>;
<span class="lnr">24 </span><span class="Identifier">var</span> tpl_fn  =   <span class="Operator">new</span> <span class="Type">Function</span>(<span class="Constant">&quot;obj&quot;</span>, fnstr);
</pre>
<p>This has been working for me for a bit now, and has saved me countless annoying declarations at the top if my templates. If you run into any problems, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/a-small-modification-to-john-resigs-js-micro-templating-to-make-it-like-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mono, C# for a large backend system</title>
		<link>http://blog.killtheradio.net/technology/mono-c-for-a-large-backend-system/</link>
		<comments>http://blog.killtheradio.net/technology/mono-c-for-a-large-backend-system/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 23:13:53 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=710</guid>
		<description><![CDATA[I just did a writeup about MongoDB&#8217;s performance in the last big app we did. Now it&#8217;s time to rip Mono a new one. Mono has been great. It&#8217;s .NET for linux. We originally implemented it because it&#8217;s noted for being a fast, robust compiled language. I didn&#8217;t know C# before starting the project, but [...]]]></description>
			<content:encoded><![CDATA[<p>I just did a writeup about <a href="http://blog.killtheradio.net/technology/mongodb-for-a-large-queuing-system/">MongoDB&#8217;s performance in the last big app we did</a>. Now it&#8217;s time to rip <a href="http://www.mono-project.com/Main_Page">Mono</a> a new one.</p>
<p>Mono has been great. It&#8217;s .NET for linux. We originally implemented it because it&#8217;s noted for being a fast, robust compiled language. I didn&#8217;t know C# before starting the project, but afterwards I feel I have a fairly good grasp on it (10 months of using it constantly will do that). I have to say I like it. Coming from a background in C++, C# is very similar except the biggest draw is you don&#8217;t separate out your definitions from your code. Your code is your definition. No header files. I understand this is a requirement if you&#8217;re going to link code in C/C++ to other C/C++ code, but I hate doing it.</p>
<p>Back to the point, mono is great in many ways. It is fast, compiles from source fairly easily (although <a href="http://www.mono-project.com/Libgdiplus">libgdiplus</a> is another story, if you want to do image processing), and easy to program in.</p>
<p>We built out a large queuing system with C#. You enter jobs into a queue table in MongoDB, and they get processed based on priority/time entered (more or less) by C#. Jobs can be anything from gathering information from third-parties to generating images and layering them all together (I actually learned first-hand how some of these Photoshop filters work). The <a href="http://www.mono-project.com/Interop_with_Native_Libraries">P/Invoke</a> system allowed us to integrate with third party libraries where the language failed (such as simple web requests with timeouts or loading custom fonts,  for instance).</p>
<p>As with any project, it started off great. Small is good. Once we started processing large numbers of items in parallel, we&#8217;d get horrible crashes with native stacktraces. At first glance, it looked like problems with the Boehm garbage collector. We recompiled Mono with &#8211;enable-big-arrays and &#8211;with-large-heap. No luck. We contacted the Mono guys and, probably in lieu of all the political shenanigans happening with Mono at the moment, didn&#8217;t really have a good response for us. Any time the memory footprint got greater than 3.5G, it would crash. It didn&#8217;t happen immediately though, it seems random. Keep in mind Mono and the machines running it were 64bit&#8230;4G is not the limit!</p>
<p>Our solution was two fold:</p>
<ul>
<li>Put crash-prone code into separate binaries and call them via shell. If the process crashes, oh well, try again. The entire queue doesn&#8217;t crash though. This is especially handy with the image libraries, which seem to have really nasty crashes every once in a while (not related to the garbage collection).</li>
<li>Make sure <a href="http://mmonit.com/monit/">Monit</a> is watching at all times.</li>
</ul>
<p>We also gave the new <a href="http://www.mono-project.com/Generational_GC">sgen GC</a> a try, but it was much too slow to even compare to the Boehm. It&#8217;s supposed to be faster, but pitting the two against each other in a highly concurrent setting crowned Boehm the clear winner.</p>
<p>All in all, I like C# the language and Mono seemed very well put together at a small to medium scale. The garbage collector shits out at a high memory/concurrency level. I wouldn&#8217;t put Mono in a server again until the GC stuff gets fixed, which seems low priority from my dealings with the devs. Still better than Java though.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/mono-c-for-a-large-backend-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MongoDB for a large queuing system</title>
		<link>http://blog.killtheradio.net/technology/mongodb-for-a-large-queuing-system/</link>
		<comments>http://blog.killtheradio.net/technology/mongodb-for-a-large-queuing-system/#comments</comments>
		<pubDate>Mon, 12 Sep 2011 22:48:04 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=708</guid>
		<description><![CDATA[Let me set the background by saying that I currently (until the end of the week anyway) work for a large tech company. We recently launched a reader app for iPad. On the backend we have a thin layer of PHP, and behind that a lot of processing via C# with Mono. I, along with [...]]]></description>
			<content:encoded><![CDATA[<p>Let me set the background by saying that I currently (until the end of the week anyway) work for a large tech company. We recently launched a reader app for iPad. On the backend we have a thin layer of PHP, and behind that a lot of processing via <a href="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)">C#</a> with <a href="http://www.mono-project.com/Main_Page">Mono</a>. I, along with my brother <a href="http://zinn-x.com">Jeff</a>, wrote most of the backend (PHP and C#). The C# side is mainly a queuing system driven off of <a href="http://www.mongodb.org/">MongoDB</a>.</p>
<p>Our queuing system is different from others in that it supports dependencies. For instance, before one job completes, its four children have to complete first. This allows us to create jobs that are actually trees of items all processing in parallel.</p>
<p>On a small scale, things went fairly well. We built the entire system out, and tested and built onto it over the period of a few months. Then came time for production testing. The nice thing about this app was that most of it could be tested via fake users and batch processing. We loaded up a few hundred thousand fake users and went to town. What did we find?</p>
<p>Without a doubt, MongoDB was the biggest bottleneck. What we really needed was a ton of write throughput. What did we do? <a href="http://www.mongodb.org/display/DOCS/Sharding">Shard</a>, of course. Problem was that we needed even distribution <em>on insert</em>&#8230;which would give us almost near-perfect balance for insert/update throughput. From what we found, there&#8217;s only one way to do this: give each queue item a randomly assigned &#8220;bucket&#8221; and shard based on that bucket value. In other words, do your own sharding manually, for the most part.</p>
<p>This was pretty disappointing. One of the whole reasons for going with Mongo is that it&#8217;s fast and scales easily. It really wasn&#8217;t as painless as everyone led us to believe. If I could do it all over again, I&#8217;d say screw dependencies, and put everything into <a href="http://redis.io/">Redis</a>, but the dependencies required more advanced queries than any key-value system could do. I&#8217;m also convinced a single <a href="http://www.mysql.com/">MySQL</a> instance could have easily handled what four MongoDB shards could barely keep up with&#8230;but at this point, that&#8217;s just speculation.</p>
<p>So there&#8217;s my advice: don&#8217;t use MongoDB for evenly-distributed high-write applications. One of the hugest problems is that there is a global write lock on the database. Yes, the database&#8230;not the record, not the collection. You cannot write to MongoDB while another write is happening anywhere. Bad news bears.</p>
<p>On a more positive note, for everything BUT the queuing system (which we did get working GREAT after throwing enough servers at it, by the way) MongoDB has worked flawlessly. The schemaless design has cut development time in half AT LEAST, and replica sets really do work insanely well. After all&#8217;s said and done, I would use MongoDB again, but for read-mostly data. Anything that&#8217;s high-write, I&#8217;d go <a href="http://redis.io/">Redis</a> (w/client key-hash sharding, like most memcached clients) or <a href="http://wiki.basho.com/">Riak</a> (which I have zero experience in but sounds very promising).</p>
<p>TL,DR; MongoDB is awesome. I recommend it for most usages. We happened to pick one of the few things it&#8217;s not good at and ended up wasting a lot of time trying to patch it together. This could have been avoided if we picked something that was built for high write throughput, or dropped our application&#8217;s &#8220;queue dependency&#8221; requirements early on. I would like if MongoDB advertised the <a href="http://www.mongodb.org/display/DOCS/How+does+concurrency+work#Howdoesconcurrencywork-Read%2FWriteLock">global write lock</a> a bit more prominently, because I felt gypped when one of their devs mentioned it in passing months after we&#8217;d started. I do have a few other projects in the pipeline and plan on using MongoDB for them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/mongodb-for-a-large-queuing-system/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>SDL 1.2.14 Windows 64 bit DLL</title>
		<link>http://blog.killtheradio.net/programming-2/sdl-1-2-14-windows-64-bit-dll/</link>
		<comments>http://blog.killtheradio.net/programming-2/sdl-1-2-14-windows-64-bit-dll/#comments</comments>
		<pubDate>Fri, 27 May 2011 20:44:13 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=696</guid>
		<description><![CDATA[I looked long and hard (reallly long and reallly hard) for an x86_64 version of the SDL.dll file (Simple DirectMedia Layer) but found it nowhere. I ended up compiling it myself with mingw64 and figured maybe some other people might benefit from my hard work and dedication. Get it here, and place the DLL in [...]]]></description>
			<content:encoded><![CDATA[<p>I looked long and hard (reallly long and reallly hard) for an x86_64 version of the SDL.dll file (<a href="http://www.libsdl.org/download-1.2.php">Simple DirectMedia Layer</a>) but found it nowhere. I ended up compiling it myself with <a href="http://mingw-w64.sourceforge.net/">mingw64</a> and figured maybe some other people might benefit from my hard work and dedication.</p>
<p><a href="http://blog.killtheradio.net/filez/SDL.zip">Get it here</a>, and place the DLL in %WINDOWS%\System32\</p>
<p>Keep in mind this was compiled on my system, so it may not work on yours, although I&#8217;ve tested it on three different x86_64 Windows 7 machines and it works fine, just fine. <a href="http://code.google.com/p/lispbuilder/wiki/LispbuilderSDL">Lispbuilder-sdl</a> loads the DLL and I&#8217;m able to do OpenGL programming in Common Lisp with it (at least in <a href="http://ccl.clozure.com/">ClozureCL</a>).</p>
<p>Check out my <a href="https://github.com/orthecreedence/som">self-organizing map project on github</a> for example usage (<a href="http://en.wikipedia.org/wiki/Self-organizing_map">info on SOMs</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/programming-2/sdl-1-2-14-windows-64-bit-dll/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP finally has anonymous functions??</title>
		<link>http://blog.killtheradio.net/technology/php-finally-has-anonymous-functions/</link>
		<comments>http://blog.killtheradio.net/technology/php-finally-has-anonymous-functions/#comments</comments>
		<pubDate>Fri, 15 Apr 2011 18:30:37 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[features]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=679</guid>
		<description><![CDATA[Wow, I can&#8217;t believe I missed this&#8230;nobody seems to be talking about it at all. Ever since PHP 5.3, I can finally do non-generic callbacks. UPDATE: Check out this description of PHP lambdas (much better than what I&#8217;ve done in the following). 2 function do_something($value) 3 { 4 // used &#38;gt;= 2 times, but only [...]]]></description>
			<content:encoded><![CDATA[<p>Wow, I can&#8217;t believe I missed this&#8230;nobody seems to be talking about it at all. Ever since PHP 5.3, <a href="http://php.net/manual/en/functions.anonymous.php">I can finally do non-generic callbacks</a>.</p>
<p>UPDATE: <a href="http://www.ibm.com/developerworks/opensource/library/os-php-5.3new2/index.html">Check out this description of PHP lambdas</a> (much better than what I&#8217;ve done in the following).</p>
<pre>
<span class="lnr"> 2 </span><span class="PreProc">function</span> do_something<span class="Special">(</span><span class="Operator">$</span><span class="Identifier">value</span><span class="Special">)</span>
<span class="lnr"> 3 </span><span class="Special">{</span>
<span class="lnr"> 4 </span>    <span class="Comment">// used &amp;gt;= 2 times, but only in this function, so no need for a global</span>
<span class="lnr"> 5 </span>    <span class="Operator">$</span><span class="Identifier">local_function</span> <span class="Operator">=</span> <span class="PreProc">function</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">value</span><span class="Special">)</span> <span class="Special">{</span> <span class="Operator">...</span> <span class="Special">}</span>;
<span class="lnr"> 6 </span>
<span class="lnr"> 7 </span>    <span class="Comment">// use our wonderful anonymous function</span>
<span class="lnr"> 8 </span>    <span class="Operator">$</span><span class="Identifier">result</span> <span class="Operator">=</span> <span class="Operator">$</span><span class="Identifier">local_function</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">value</span><span class="Special">)</span>;
<span class="lnr"> 9 </span>    <span class="Operator">...</span>
<span class="lnr">10 </span>    <span class="Comment">// and again</span>
<span class="lnr">11 </span>    <span class="Operator">$</span><span class="Identifier">result</span> <span class="Operator">=</span> <span class="Operator">$</span><span class="Identifier">local_function</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">result</span><span class="Special">)</span>;
<span class="lnr">12 </span>    <span class="Statement">return</span> <span class="Operator">$</span><span class="Identifier">result</span>;
<span class="lnr">13 </span><span class="Special">}</span>
</pre>
<p>There&#8217;s also some other great stuff you can do:</p>
<pre>
<span class="lnr">2 </span><span class="Operator">$</span><span class="Identifier">favorite_songs</span> <span class="Operator">=</span> <span class="Type">array</span><span class="Special">(</span>
<span class="lnr">3 </span>    <span class="Type">array</span><span class="Special">(</span>'<span class="Constant">name</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">hit me baby one more time</span>', '<span class="Constant">artist</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">britney</span>'<span class="Special">)</span>,
<span class="lnr">4 </span>    <span class="Type">array</span><span class="Special">(</span>'<span class="Constant">name</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">genie </span><span class="Statement">in</span><span class="Constant"> a bottle</span>', '<span class="Constant">artist</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">xtina</span>'<span class="Special">)</span>,
<span class="lnr">5 </span>    <span class="Type">array</span><span class="Special">(</span>'<span class="Constant">name</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">last resort</span>', '<span class="Constant">artist</span>' <span class="Operator">=</span><span class="Operator">&gt;</span> '<span class="Constant">papa roach</span>'<span class="Special">)</span>
<span class="lnr">6 </span><span class="Special">)</span>;
<span class="lnr">7 </span><span class="Operator">$</span><span class="Identifier">song_names</span> <span class="Operator">=</span> <span class="Identifier">array_map</span><span class="Special">(</span><span class="PreProc">function</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">item</span><span class="Special">)</span> <span class="Special">{</span> <span class="Statement">return</span> <span class="Operator">$</span><span class="Identifier">item</span><span class="Special">[</span>'<span class="Constant">name</span>'<span class="Special">]</span>; <span class="Special">}</span>, <span class="Operator">$</span><span class="Identifier">favorite_songs</span><span class="Special">)</span>;
</pre>
<p>GnArLy bra. If PHP was 20 miles behind Lisp, it just caught up by about 30 feet. This has wonderful implications because there are a lot of functions that take a callback, and the only way to use them was to define a global function and send in an array() callback. Terrible. Inexcusable. Vomit-inducing.</p>
<p>Not only can you now use anonymous functions for things like array_map() and preg_replace_callback(), you can define your own functions that take functions as arguments:</p>
<pre>
<span class="lnr"> 2 </span><span class="PreProc">function</span> do_something_binary<span class="Special">(</span><span class="Operator">$</span><span class="Identifier">fn_success</span>, <span class="Operator">$</span><span class="Identifier">fn_failed</span><span class="Special">)</span>
<span class="lnr"> 3 </span><span class="Special">{</span>
<span class="lnr"> 4 </span>    <span class="Operator">$</span><span class="Identifier">success</span> <span class="Operator">=</span> <span class="Operator">...</span>
<span class="lnr"> 5 </span>    <span class="Statement">if</span><span class="Special">(</span><span class="Operator">$</span><span class="Identifier">success</span><span class="Special">)</span>
<span class="lnr"> 6 </span>    <span class="Special">{</span>
<span class="lnr"> 7 </span>        <span class="Statement">return</span> <span class="Operator">$</span><span class="Identifier">fn_success</span><span class="Special">()</span>;
<span class="lnr"> 8 </span>    <span class="Special">}</span>
<span class="lnr"> 9 </span>    <span class="Statement">return</span> <span class="Operator">$</span><span class="Identifier">fn_failed</span><span class="Special">()</span>;
<span class="lnr">10 </span><span class="Special">}</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span>do_something_binary<span class="Special">(</span>
<span class="lnr">13 </span>    <span class="PreProc">function</span><span class="Special">()</span> <span class="Special">{</span> <span class="PreProc">echo</span> &quot;<span class="Constant">I successfully fucked a goat!</span>&quot;; <span class="Special">}</span>,
<span class="lnr">14 </span>    <span class="PreProc">function</span><span class="Special">()</span> <span class="Special">{</span> <span class="PreProc">echo</span> &quot;<span class="Constant">The goat got away...</span>&quot;; <span class="Special">}</span>
<span class="lnr">15 </span><span class="Special">)</span>;
</pre>
<p>Sure, you could just return $success and call whichever function you need after that, but this is just a simple example. It can be very useful to encapsulate code and send it somewhere, this is just a demonstration of the beautiful new world that just opened for PHP.</p>
<p>So drop your crap shared host (unless it has &gt;= 5.3.0), get a VPS, and start using this wonderful new feature.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/php-finally-has-anonymous-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Anti-stupidity pills fly off shelves of drug stores at record rates</title>
		<link>http://blog.killtheradio.net/articles/anti-stupidity-pills-fly-off-shelves-of-drug-stores-at-record-rates/</link>
		<comments>http://blog.killtheradio.net/articles/anti-stupidity-pills-fly-off-shelves-of-drug-stores-at-record-rates/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 23:41:44 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[america]]></category>
		<category><![CDATA[government]]></category>
		<category><![CDATA[intelligence]]></category>
		<category><![CDATA[radiation]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=651</guid>
		<description><![CDATA[After coming to terms with how completely idiotic the rapid over-consumption of anti-radiation pills was after a recent nuclear energy scare, the American public realized it had to turn in another direction to fix all of its problems: anti-stupidity pills. The new drug, dubbed dioxide-enisium-rectopeptide (or &#8220;Derp&#8221;), recently gained FDA approval and hit the shelves [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.killtheradio.net/wp-content/uploads/2011/03/potassium-iodide.jpg"><img class="alignright size-medium wp-image-652" title="potassium iodide" src="http://blog.killtheradio.net/wp-content/uploads/2011/03/potassium-iodide-300x169.jpg" alt="" width="300" height="169" /></a>After coming to terms with how completely idiotic the rapid over-consumption of anti-radiation pills was after a recent nuclear energy scare, the American public realized it had to turn in another direction to fix all of its problems: anti-stupidity pills. The new drug, dubbed dioxide-enisium-rectopeptide (or &#8220;Derp&#8221;), recently gained FDA approval and hit the shelves of drug stores last week.</p>
<p>Since the phenomenon started, the average IQ rates of Americans has rocketed from 16.4 to a staggering 16.7. Not only are 99% of Americans now able to withstand a 400-year nuclear holocaust, but most can recite <em>the entire</em> English alphabet or even distinguish between highly complex shapes, such as squares and triangles. With this increase in smarts, scientists predict that within two weeks, 99% of the population will be scientists.</p>
<p>Plans to build over 100 million nuclear bombs and detonate them around the globe are being drafted by Congress; the idea being that only Americans are worthy of living because they are so incredibly intelligent and amazing.</p>
<p>&#8220;Just think! Without the other countries, where will be no war, no fighting, no trade embargoes, no failing world economy. Just peace,&#8221; Republic Senator Rick Harris stated. &#8220;Americans can finally hold hands in circles and dance and laugh and sing. And with everyone here taking anti-radiation pills, the nuclear fallout won&#8217;t even affect us. We can live like kings! KINGS!!! HAHAHAHA!!&#8221;</p>
<p>President Obama has signed the bill and the motion is currently in action.</p>
<p>Although things are looking good for the U.S. right now, there is a dark side to being the smartest nation in the universe and all containing dimensions. Top thinkers worry that nobody will want to empty trash cans, sweep floors, pay taxes, or any of the other horribly mundane tasks that years of failure and stupidity have forced us into. Some have suggested that a select few people be banned from taking the smart pills, effectively forcing them into perpetual state of drooling idiocy. Others think we could spare Canada from the final bombing and enslave the entire country. A general consensus has not been reached.</p>
<p>Just when you thought Americans couldn&#8217;t be any more intelligent, fun-loving, passionate, humble, caring, progressive, radiation-resistant, cultured, intelligent, helpful, and intelligent enough already, they proved the world wrong again.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/articles/anti-stupidity-pills-fly-off-shelves-of-drug-stores-at-record-rates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vim: Cursor at beginning of tab in normal mode</title>
		<link>http://blog.killtheradio.net/how-tos/vim-cursor-at-beginning-of-tab-in-normal-mode/</link>
		<comments>http://blog.killtheradio.net/how-tos/vim-cursor-at-beginning-of-tab-in-normal-mode/#comments</comments>
		<pubDate>Sun, 21 Nov 2010 21:57:32 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[How to's]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=645</guid>
		<description><![CDATA[One thing that annoys me in Vim is that in normal mode, the cursor defaults to being at the end of a tab character. When I hit &#8220;Home&#8221; I expect the cursor to go all the way to the left, but instead it hovers 4 spaces to the right of where I expect it to. [...]]]></description>
			<content:encoded><![CDATA[<p>One thing that annoys me in Vim is that in normal mode, the cursor defaults to being at the end of a tab character. When I hit &#8220;Home&#8221; I expect the cursor to go all the way to the left, but instead it hovers 4 spaces to the right of where I expect it to. I stumbled across the answer after reading a <a href="http://www.mail-archive.com/vim_dev@googlegroups.com/msg04592.html">mailing list thread for vim</a>.</p>
<pre>set list lcs=tab:\ \ 
" Note the extra space after the second \</pre>
<p>You can put this in your .vimrc to automatically set this behavior. Very useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/how-tos/vim-cursor-at-beginning-of-tab-in-normal-mode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Vim: I can&#8217;t believe I ignored you all these years</title>
		<link>http://blog.killtheradio.net/reviews/vim-i-cant-believe-i-ignored-you-all-these-years/</link>
		<comments>http://blog.killtheradio.net/reviews/vim-i-cant-believe-i-ignored-you-all-these-years/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 05:06:04 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=632</guid>
		<description><![CDATA[All these years, since the day I first turned on a linux distribution, I&#8217;ve ignored vi/vim. Sure, there are swarms of geeks covering you with saliva as they spew fact after fact about how superior vim is to everything else, but to me it&#8217;s always been &#8220;that editor that is on every system that I [...]]]></description>
			<content:encoded><![CDATA[<p>All these years, since the day I first turned on a linux distribution, I&#8217;ve ignored vi/<a href="http://www.vim.org/">vim</a>. Sure, there are swarms of geeks covering you with saliva as they spew fact after fact about how superior vim is to everything else, but to me it&#8217;s always been &#8220;that editor that is on every system that I eventually replace with pico anyway.&#8221;</p>
<p>Not anymore. Starting a few years back, I&#8217;ve done all of my development in <a href="http://www.eclipse.org/">Eclipse</a>. It has wonderful plugins for PHP, C++, Javascript, etc. The past week or so I&#8217;ve been weening myself off of it and diving into vim. What actually got me started is I bought a Droid 2 off ebay for various hacking projects (I&#8217;m planning on reviewing it soon). Well, it was really easy to get vim working in it (sorry, lost the link already). I thought, well, shit, I&#8217;ve got vim, what the hell can I do with it? First things first, let&#8217;s get a plugin for syntax coloring/indentation for a few of my favorite languages. What?! It has all of them already.</p>
<p>Ok, now I&#8217;m interested. I installed vim for Windows (gvim), which was followed by a slow-but-steady growing period of &#8220;well, how do I do this&#8221; and &#8220;HA&#8230;I bet vim can&#8217;t do THI&#8230;oh, it can.&#8221; There are &#8220;marks&#8221; for saving your place in code, you can open the same file in multiple views (aka &#8220;windows&#8221;), you can bind just about any key combination to run any command or set of commands, etc. I even discovered tonight there&#8217;s a <a href="http://serverfault.com/questions/27917/configure-vim-for-text-selection-with-shift-and-copy-paste-via-ctrlc-ctrlv">&#8220;windows&#8221; mode for vim</a> that mimics how any normal editor works. I hate to admit it, but I&#8217;ll be using that a lot. One feature that blew my mind is the <a href="http://vimdoc.sourceforge.net/htmldoc/undo.html#undo-branches">undo tree</a>. Not stack, <em>tree</em>. Make a change, undo, make a new change, and the first change you did before your undo is still accessible (:undolist)!</p>
<p>The nice thing about vim is that it saves none of its settings. Every change you make to it while inside the editor is lost after a restart. This sounds aggravating, but it actually makes playing with the editor really fun and easy. If I open 30 windows and don&#8217;t know how to close them, just restart the editor. There are literally hundreds of trillions of instances when I was like &#8220;oh, shit&#8221; *restart*.</p>
<p>Once you have a good idea of what you want your environment to be like, you put all your startup commands in .vimrc (_vimrc on Windows) and vim runs it before it loads. Your settings file uses the same syntax as the commands you run inline in the editor, which is awesome and makes it easy to remember how to actually use vim.</p>
<p>So far I&#8217;m <em>extremely</em> impressed. The makers of vim have literally thought of everything you could possibly want to do when coding. And if they haven&#8217;t thought of it, someone else <em>has</em> and has written a plugin you can drop into your plugins directory and it &#8220;just works.&#8221; Speaking of plugins, vim.org&#8217;s plugin list seems neverending. I was half expecting to see most plugins have a final mod date of 2002 or something, but a good portion have newer version released within the past two weeks. It seems the ones that are from 2002 never get updated because they&#8217;re mostly perfect. Excellent.</p>
<p>I do miss a few things though. First off, the project file list most editors have on the left side. I installed <a href="http://www.vim.org/scripts/script.php?script_id=1658">NERDTree</a> to alleviate that pain, but honestly it&#8217;s not the same as having my right click menus and pretty icons. I&#8217;m slowly getting used to it though. The nice thing about a text-only file tree is that in those instances where you only have shell access and need to do some coding, there isn&#8217;t a dependency on a GUI.</p>
<p>Tabs are another thing I miss. Gvim <em>has</em> tabs, but they aren&#8217;t one tab == one file (aka &#8220;buffer&#8221;) like most editors. You can hack it to do this, <a href="http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers">sort of</a>, but it works really jenky. Instead I&#8217;m using <a href="http://www.vim.org/scripts/script.php?script_id=159">MiniBufExplorer</a>, which takes away <em>some</em> of the pain. I actually hacked it a bit because I didn&#8217;t like the way it displays the tabs, which gave me a chance to look at some real vim script. It&#8217;s mostly readable to someone who&#8217;s never touched it before.</p>
<p>That about does it for my rant. Vim is fast, free, customizable, extendable, scriptable, portable, wonderful, etc&#8230;and I&#8217;ve barely scratched the surface.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/reviews/vim-i-cant-believe-i-ignored-you-all-these-years/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Alleged sexual assault at a tech conference</title>
		<link>http://blog.killtheradio.net/social-issues/alleged-sexual-assault-at-a-tech-conference/</link>
		<comments>http://blog.killtheradio.net/social-issues/alleged-sexual-assault-at-a-tech-conference/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 01:40:59 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Social issues]]></category>
		<category><![CDATA[assault]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=625</guid>
		<description><![CDATA[Let me preface this by saying I know neither of the two people involved in this situation nor have any connection to them other than the fact that I use both Google and Twitter. A Google tech writer recently accused Twitter engineer of sexual assault on her blog, and given the responses shot at both sides [...]]]></description>
			<content:encoded><![CDATA[<p>Let me preface this by saying I know neither of the two people involved in this situation nor have any connection to them other than the fact that I use both Google and Twitter.</p>
<p>A Google tech writer <a href="http://blog.nerdchic.net/archives/418/">recently accused Twitter engineer of sexual assault</a> on her blog, and given the responses shot at both sides (Noirin Shirley, accuser, and Florian Leibert, accused) I thought I&#8217;d inject my personal thoughts on both the actual report given by Noirin and the responses to the incident.</p>
<p>First off, it&#8217;s a big deal to make an accusation like this. Careers hang in the balance, and blah blah blah, we&#8217;ve all heard this already. That said, a lot of women are sexually assaulted and never mention it. A lot tell a few people and it never goes anywhere. A lot try to get help but it never comes.</p>
<p>I think it&#8217;s not only amazing, but brave that Noirin had the guts to stand up to her assaulter and accuse him in public. It takes brass balls to do this. It also takes brass balls to do this knowing full well the responses you&#8217;re going to get because of it. I&#8217;m not one to not take stands on things, so I will say I think she&#8217;s awesome. I&#8217;m sick of women getting pushed around and there being no consequences for the men doing it.</p>
<p>I also do know that women make false accusations, but in my experience the ones who do so have a history of doing so and don&#8217;t start off doing it later on in life.</p>
<p>Now, <a href="http://gawker.com/5683354/googler-accuses-twitter-engineer-of-sexual-assault-on-her-blog?skyline=true&amp;s=i">at least one publication</a> is saying that although it&#8217;s great to be public about this matter, it&#8217;s not ok to be public about the assailant&#8217;s name. I have to disagree. So many assaults go unresolved because it&#8217;s hard to prove unless you have a police officer right there watching, or at least 10 witnesses. Something like this wouldn&#8217;t hold up in court. It&#8217;s important that the person who did it be publicly recognized for his actions, because otherwise there very well may be no consequences, ever.</p>
<p>A lot of people are saying that she should say absolutely nothing until the police investigate and the courts make a decision. I have to wonder if they are batshit insane. First off, the police generally have &#8220;more important&#8221; things to worry about than &#8220;hey sum guy jus touched my privatz,&#8221; unfortunately. And without any material evidence, it will never hold up in court. What I&#8217;m getting at is that even though I love our justice system here in good old USA, there are many things that will fall through the cracks. Does Noirin really need the police or court system to validate what she experienced that night? That&#8217;s fucking insane! She knows what happened better than the police or courts, and has every right to talk about it. Plus, she&#8217;s opening herself up to a world of legal trouble by doing this, which is just one more reason she&#8217;s brave for doing it (and one more incentive to NOT do it falsely).</p>
<p>Let me put it this way: <strong>If somebody assaults you, you have the right to fucking let the world know who did it and what happened!</strong> Just because it won&#8217;t hold up in court (and believe me, it won&#8217;t) doesn&#8217;t mean it didn&#8217;t happen, and doesn&#8217;t mean the assailant shouldn&#8217;t suffer the social consequences. If a rape happens in the woods and nobody is there to witness it, did it happen? The courts, rightfully so, say &#8220;No.&#8221; But it still happened, and the aggressor needs to pay for it in some way.</p>
<p>If she lied about it, then that&#8217;s another issue entirely. If it did happen, as she said it did, then good for her for letting the world know and making the world that much safer for women.</p>
<p>Either way, there are some very good counter-arguments and discussion on the <a href="http://www.reddit.com/r/programming/comments/e20ct/a_hell_of_a_time_sexual_assault_at_tech/">reddit comments page for the post</a>, which I spent a good amount of time reading before making this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/social-issues/alleged-sexual-assault-at-a-tech-conference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keepalived, HAProxy, and failover on the cloud (or any VPS without multicast)</title>
		<link>http://blog.killtheradio.net/how-tos/keepalived-haproxy-and-failover-on-the-cloud-or-any-vps-without-multicast/</link>
		<comments>http://blog.killtheradio.net/how-tos/keepalived-haproxy-and-failover-on-the-cloud-or-any-vps-without-multicast/#comments</comments>
		<pubDate>Sun, 17 Oct 2010 21:26:53 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[How to's]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[failover]]></category>
		<category><![CDATA[ha computing]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[keepalived]]></category>
		<category><![CDATA[linode]]></category>
		<category><![CDATA[multicast]]></category>
		<category><![CDATA[vps]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=619</guid>
		<description><![CDATA[Let&#8217;s talk failover. Most tools for failover (keepalived, heartbeat, wackamole/spread) use a protocol known as multicast. Multicast acts as a sort of &#8220;bulletin board&#8221; between computers. Anybody on the network can look at the bulletin board, and anybody on the network can post to the bulletin board. Normally, failover tools use multicast to pass messages [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s talk failover. Most tools for failover (<a href="http://www.keepalived.org/">keepalived</a>, <a href="http://www.linux-ha.org/wiki/Main_Page">heartbeat</a>, <a href="http://www.backhand.org/wackamole/">wackamole</a>/<a href="http://www.spread.org/">spread</a>) use a protocol known as <a href="http://en.wikipedia.org/wiki/Multicast">multicast</a>. Multicast acts as a sort of &#8220;bulletin board&#8221; between computers. Anybody on the network can look at the bulletin board, and anybody on the network can post to the bulletin board. Normally, failover tools use multicast to pass messages between computers. For instance you could have three computer on a network, all posting and listening to the same multicast group: &#8220;Hey, I&#8217;m alive!&#8221; If one of the machines stops sending this repetitive  message, the others know that something is wrong&#8230;either it has been disconnected or gone down, etc. They can use that information to act: was that computer hosting a shared IP? Give the IP to one of the computers that are still responding. This is the general idea behind IP-based failover.</p>
<p>Now, there&#8217;s no inherent problem with multicast. It&#8217;s generally known for being unreliable, but when all you&#8217;re sending is &#8220;Hi!&#8221; over the wire, data integrity isn&#8217;t a high priority. The problem with multicast in reality is that most &#8220;cloud&#8221; (VPS) providers (AWS, Linode, Slicehost, Rackspace, etc) don&#8217;t support it on their networks. You can send a multicast message to a group, but your other machines listening on that group won&#8217;t hear it. The other problem with multicast is that the failover tools mentioned above ONLY support multicast. There is no way to tell them to listen to another machine directly over <a href="http://en.wikipedia.org/wiki/Unicast">unicast</a>, which <span style="text-decoration: underline;">is</span> supported by cloud providers.</p>
<p>One way you can solve this is by using GRE tunnels, which allow you to create a tunnel to another computer with everything inside encrypted. This allows multicast communications to pass between two computers, even if the router blocks them normally.</p>
<p>I recently tried to get this set up on my current host, <a href="http://www.linode.com/?r=15d5d2323910d69794b93ed02cd7d43b2f68d8c5">Linode</a>. I was not successful, even with the help of another member who had the same problem (but solved it with GRE). I just could not get two machines to talk to eachother over a GRE tunnel with keepalived.</p>
<h2>The solution</h2>
<p>I posted my question to <a href="http://serverfault.com/questions/186987/keepalived-over-gre-tunnel-for-failover-on-vps-environment">serverfault.com</a> in a <a href="http://www.youtube.com/watch?v=HqLHr17COS8">last resort</a> (video). I&#8217;d asked more or less the same question there before, but didn&#8217;t get the answer I wanted. This time, I hit a jackpot though.</p>
<p>Willy Tarreau, creator of <a href="http://haproxy.1wt.eu/">HAProxy</a>, responded with a patch to keepalived that allows it to communicate over unicast. I applied it, recompiled, set up the new options the patch gives (&#8220;<strong>vrrp_unicast_bind</strong>&#8221; &amp;&#8221;<strong>vrrp_unicast_peer</strong>&#8220;), and spun it up on both machines.</p>
<p>Yesss!! It works! Stopping HAProxy on the first server made the second machine take the shared IP.</p>
<p>Now, ideally there would be a bunch of machines, namely <em>all</em> my web servers that would be standing by ready to take the shared IP. This patch only allows me two machines. Failover is failover though, when one instance goes down, I get an email and can go in and investigate.  I&#8217;d still like to know if there is a way to do failover on a cluster of servers without multicast, but for now this works great.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/how-tos/keepalived-haproxy-and-failover-on-the-cloud-or-any-vps-without-multicast/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>PHP&#8217;s preg functions don&#8217;t release memory??</title>
		<link>http://blog.killtheradio.net/tricks-hacks/phps-preg-functions-dont-release-memory/</link>
		<comments>http://blog.killtheradio.net/tricks-hacks/phps-preg-functions-dont-release-memory/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 23:37:11 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Tricks/Hacks]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[memory leak]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=612</guid>
		<description><![CDATA[We were writing some parsing code for a client today. It takes a long string (html) and parses it out into array items. It loops over the string recursively and running a few preg_replaces on it every pass. We got &#8220;out of memory&#8221; errors when running it. After putting in some general stats, we found [...]]]></description>
			<content:encoded><![CDATA[<p>We were writing some parsing code for a client today. It takes a long string (html) and parses it out into array items. It loops over the string recursively and running a few preg_replaces on it every pass. We got &#8220;out of memory&#8221; errors when running it. After putting in some general stats, we found that memory usage was climbing 400k after each block of preg_replaces, which was being added on each loop (there were around 600 loops or so). This memory just grew and grew, even though the recursion at most got 6 levels deep. It was never being released.</p>
<p>I did some reading and found that the preg* functions cache up to 4096 regex results in a request. This is the problem&#8230;a pretty stupid one too. It would be nice if they made this a configurable option or at <em>least</em> let you turn it off when, say, you are running a regex on a different string every time (why the hell would I run the same regex on the same string twice&#8230;isn&#8217;t that what variables are for?) Unless I&#8217;m misunderstanding and PHP caches the compiled regex (but not its values)&#8230;but either way, memory was climbing based on the length of the string.</p>
<p>Since the regex was only looking at the beginning of the string and disregarding the rest (thank god), the fix was easy (although a bit of a hack):</p>
<pre>$val = preg_replace('/.../', '', $long_string);</pre>
<p>Becomes:</p>
<pre>$short_string = substr($long_string, 0, 128);
$val = preg_replace('/.../', '', $short_string);</pre>
<p>PHP guys: how about an option to make preg* NOT have memory leaks =).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/tricks-hacks/phps-preg-functions-dont-release-memory/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Our sanity, slipping away text by text</title>
		<link>http://blog.killtheradio.net/social-issues/our-sanity-slipping-away-text-by-text/</link>
		<comments>http://blog.killtheradio.net/social-issues/our-sanity-slipping-away-text-by-text/#comments</comments>
		<pubDate>Sun, 01 Aug 2010 18:56:10 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Social issues]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[cultural]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[texting]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=597</guid>
		<description><![CDATA[After reading an article about how the number of phone calls made is decreasing, I feel I have to interject something. This obviously shouldn&#8217;t be news to most people, because most of us are right in the middle of it (in North America, anyway). The fact is that people are talking less and less in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.killtheradio.net/wp-content/uploads/2010/08/Bush_Texting.jpg"><img class="alignright size-medium wp-image-599" title="Bush_Texting" src="http://blog.killtheradio.net/wp-content/uploads/2010/08/Bush_Texting-300x227.jpg" alt="" width="300" height="227" /></a>After reading an article about <a href="http://m.wired.com/magazine/2010/07/st_thompson_deadphone/">how the number of phone calls made is decreasing</a>, I feel I have to interject something. This obviously shouldn&#8217;t be news to most people, because most of us are right in the middle of it (in North America, anyway). The fact is that people are talking less and less in favor of texting each other. While this is an interesting shift in our culture, I&#8217;m starting to think things are going a bit too far.</p>
<p>It seems that since widespread adoption of the internet, although more and more people have become seemingly connected through social networking and other mediums, people are drifting further and further apart. A friend is no longer a friend. A real friend is now what a friend was, and a friend is someone you say &#8220;damn we haven&#8217;t talked in years, how r u?&#8221; to. Communities are popping up everywhere online that replace the communities around us physically.</p>
<p>This in itself I don&#8217;t feel is bad. A lot of people who never would have met are meeting and sharing new ideas. Information spreads more rapidly. Cultural consciousness is more global, which in most cases is a very good thing.</p>
<p>I think things start to go wrong when people get addicted to this information overload though. They use it as a fuel for everyday distraction, a replacement for the communities they live in, and a tool to deliver opinions and beliefs to them when they would have otherwise had to think (although this last item is true of most media).</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2010/08/texting.jpg"><img class="alignleft size-medium wp-image-600" src="http://blog.killtheradio.net/wp-content/uploads/2010/08/texting-300x240.jpg" alt="" width="300" height="240" /></a>Also, it&#8217;s one thing to not be in front of someone when you talk to them. A voice conversation can have emotion and depth, but it can also be quick and effortless. The fact that it&#8217;s being replaced by one-off messages that are 100% ignorable and have no real content to them is kind of sickening. I&#8217;ve heard arguments that &#8220;I text someone when it doesn&#8217;t make sense to have a whole conversation,&#8221; but I&#8217;ll see the same person texting back and forth with someone for 10 minutes straight. Or a text is delivered and the person who sent it squirms in anticipation for the reply, which may never come.</p>
<p><a href="http://blog.killtheradio.net/wp-content/uploads/2010/08/funcage81.jpg"><img class="alignright size-medium wp-image-609" title="funcage81" src="http://blog.killtheradio.net/wp-content/uploads/2010/08/funcage81-300x225.jpg" alt="" width="300" height="225" /></a>What&#8217;s wrong with a phone call? Granted, if you&#8217;re in a bar and it&#8217;s very loud, texting would be appropriate. If you call someone and they don&#8217;t pick up, either they don&#8217;t want to talk or, god forbid, they aren&#8217;t right next to their phone all times of the day. If you want to talk to someone, just call them. I don&#8217;t believe texting is a viable replacement for what was the last string of human contact we had.</p>
<p>That all said, I know it&#8217;s a giant ball and it rolls where it rolls and there&#8217;s no stopping it. There&#8217;s no problem with being aware of things that are going on around us though. I feel like each time a real connection between two real people is replaced with something artificial, our culture as a whole goes just a little bit more insane. I&#8217;m interested to see how this all pans out, mainly because I don&#8217;t have a whole lot of attachment to what our culture is now.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/social-issues/our-sanity-slipping-away-text-by-text/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monit, how did I ever live without you?</title>
		<link>http://blog.killtheradio.net/reviews/monit-how-did-i-ever-live-without-you/</link>
		<comments>http://blog.killtheradio.net/reviews/monit-how-did-i-ever-live-without-you/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 19:26:45 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=573</guid>
		<description><![CDATA[In my latest frenzy, which was focused on HA more than performance, I installed some new servers, new services on those servers, and the general complexity of the entire setup for beeets.com doubled. I was trying to remember a utility that I saw a while back that would restart services if they failed. I checked [...]]]></description>
			<content:encoded><![CDATA[<p>In my latest frenzy, which was focused on HA more than performance, I installed some new servers, new services on those servers, and the general complexity of the entire setup for beeets.com doubled. I was trying to remember a utility that I saw a while back that would restart services if they failed. I checked my delicious account, praying that I had thought of my future self when I originally saw it. Luckily, I had saved it under my &#8220;linux&#8221; tag. Thanks, Andrew from the past.</p>
<p>The tool is called <a href="http://mmonit.com/monit/">monit</a>, and I&#8217;m surprised I ever lived without it. Not only does it monitor your services and keep them running, it can restart them if they fail, use too much memory/cpu, stop responding on a certain port, etc. Not only that, but it will email you every time something happens.</p>
<p>While perusing monit&#8217;s site, I saw <a href="http://mmonit.com/">M/Monit</a> which allows you to monitor monit over web, essentially. The only thing I scratched my head about was that M/Monit uses port 8080 (which is fine) but NginX already uses port 8080, and I wasn&#8217;t about to change that, so I opened conf/server.xml and looked for 8080, replaced with 8082 (monit runs on 8081 =)). Then I reconfigured monit to communicate with M/Monit and vice versa, and now I have a kickass process monitor that alerts me when things go wrong, and also sends updates to a service that allows me to monitor the monitor.</p>
<p>I can&#8217;t look at things like queries/sec as I can with <a href="http://www.cacti.net/">Cacti</a> (which is awesome but a little clunky) but I can see which important services are running on each of my servers, and even restart them if I need to straight from M/Monit. The free download license allows to use M/Monit on one server, which is all I need anyway.</p>
<p>Great job monit team, you have gone above and beyond.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/reviews/monit-how-did-i-ever-live-without-you/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>New MySQL cluster test setup</title>
		<link>http://blog.killtheradio.net/technology/new-mysql-cluster-test-setup/</link>
		<comments>http://blog.killtheradio.net/technology/new-mysql-cluster-test-setup/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 19:13:41 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=566</guid>
		<description><![CDATA[I decided this weekend I wanted to go down the road of trying out MySQL Cluster for beeets.com. The reason isn&#8217;t speed, it&#8217;s availability. After countless hours of research, I decided I&#8217;d rather have a plate of turds for breakfast than have to worry about Master-Master replication (or DRBD) w/heartbeat, not to mention what to do [...]]]></description>
			<content:encoded><![CDATA[<p>I decided this weekend I wanted to go down the road of trying out <a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster.html">MySQL Cluster</a> for beeets.com. The reason isn&#8217;t speed, it&#8217;s availability. After countless hours of research, I decided I&#8217;d rather have a plate of turds for breakfast than have to worry about Master-Master replication (or <a href="http://www.drbd.org/">DRBD</a>) w/heartbeat, not to mention what to do when things get out of sync. Not my cup of tea. MySQL Cluster may be a bit slower than a replicated setup (in almost all cases except for primary key lookup, I suspect), but to me it&#8217;s worth it to have a more set-it and forget-it approach. There are many benefits of cluster over replication:</p>
<ul>
<li>Any server can go down. Assuming you have more than one <a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster-nodes-groups.html">replica</a> of your data, you can lose any server in your setup and still be up and running. This can be achieved with replication, but it&#8217;s not as easy. You have to have some form of Master-Master replication, perhaps with DRDB, and some form of failover (usually <a href="http://www.linux-ha.org/wiki/Main_Page">heartbeat</a>).</li>
<li>Your data  set scales. If you start running out of disk space with a cluster, just add a few more data nodes and your data will be spread out over them. With replication, each replicated server has to have enough storage to fit the entire database. That means if your dataset grows too large, you have to either partition (a hack, essentially) or upgrade your servers.</li>
<li>Your bandwidth scales. With a cluster, if you are running out of bandwidth, you can add more mysqld processes on your www servers or add more data nodes and your bandwidth scales almost linearly. With replication, you can only add so many slaves before your writes are the bottleneck. Then, once again, you have to look into things like circular replication (dangerous) or partitioning your data set (large updates to your app unless you have an insanely good ORM, big infrastructure change).</li>
</ul>
<p>These are the main points that helped me decide. Historically, with a clustered approach, the entire dataset would have to fit in the memory of all the data nodes, which is somewhat restrictive if the dataset gets too large. Nowadays, the cluster only needs to store indexes in memory, and can store all non-indexed data on disk. There is talk of having completely disk-based store as well.</p>
<p>All that being said, I set up cluster, which was surprisingly easy. I&#8217;m not going to go over how to set it up or anything, just read the manual. After some benchmarking with the web API for beeets.com, the cluster setup appeared to be running about the same speed as the InnoDB setup when testing various commands&#8230;a pleasant surprise. It also appeared to handle concurrency a bit better.</p>
<p>Obviously once the dataset grows past a few megs and the traffic bumps up, we&#8217;ll revisit the benchmarking, but my hope is that what cluster loses in speed from your everyday general query, it gains in speed by having ability for higher concurrency.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/new-mysql-cluster-test-setup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Strange problems with hosts resolving in PHP (and some other linux weirdness)</title>
		<link>http://blog.killtheradio.net/technology/strange-problems-with-hosts-resolving-in-php-and-some-other-linux-weirdness/</link>
		<comments>http://blog.killtheradio.net/technology/strange-problems-with-hosts-resolving-in-php-and-some-other-linux-weirdness/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 18:51:31 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[fixes]]></category>
		<category><![CDATA[hosts]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[problems]]></category>
		<category><![CDATA[sudo]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=565</guid>
		<description><![CDATA[This weekend I wen&#8217;t on a frenzy. I turned beeets.com from a single VPS enterprise to 4 VPSs: 2 web (haproxy, nginx, php-fpm, sphinx, memcached, ndb_mgmd) and 2 database servers (ndmtd). There&#8217;s still some work to do, but the entire setup seems to be functioning well. I had a few problems though. In PHP (just [...]]]></description>
			<content:encoded><![CDATA[<p>This weekend I wen&#8217;t on a frenzy. I turned beeets.com from a single VPS enterprise to <a href="http://www.linode.com/?r=15d5d2323910d69794b93ed02cd7d43b2f68d8c5">4 VPSs</a>: 2 web (<a href="http://haproxy.1wt.eu/">haproxy</a>, <a href="http://nginx.org/">nginx</a>, <a href="http://php-fpm.org/">php-fpm</a>, <a href="http://www.sphinxsearch.com/">sphinx</a>, <a href="http://memcached.org/">memcached</a>, <a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster.html">ndb_mgmd</a>) and 2 database servers (<a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster.html">ndmtd</a>). There&#8217;s still some work to do, but the entire setup seems to be functioning well.</p>
<p>I had a few problems though. In PHP (just PHP, and nothing else) hosts were not resolving. The linux OS was resolving hosts just fine, but PHP couldn&#8217;t. It was frustrating. Also, I was unable to sudo. I kept checking permissions on all my files in /etc, rebooting, checking again, etc.</p>
<h2>The fix</h2>
<p>Then I looked again. /etc itself was owned by andrew:users. Huh? I changed permissions back root:root, chmod 755. <em>Everything works</em>. Now some background.</p>
<p>A while back, I wrote some software (bash + php) that makes it insanely easy to install software to several servers at once, and sync configurations for different sets of servers. It&#8217;s called &#8220;ssync.&#8221; It&#8217;s not ready for release yet, but I can say without it, I&#8217;d have about 10% of the work done that I&#8217;d finished already. Ssync is a command-line utility that lets you set up servers (host, internal ip, external ip) and create groups. Each group has a set of install scripts and configuration files that can be synced to /etc. The configuration files are PHP scriptable, so instead of, say, adding all my hosts by hand to the /etc/hosts file, I can just loop over all servers in the group and add them automatically. Same with my www group, I can add a server to the &#8220;www&#8221; group in ssync, and all of a sudden the HAproxy config knows about the server.</p>
<p>Here&#8217;s the problem. When ssync was sending configuration files to /etc on remote servers, it was also setting permissions on those files (and folders) by default. This was because I was using -vaz, which attempts to preserve ownership, groupship, and permissions from the source (not good). I added some new params (so now it&#8217;s &#8220;-vaz &#8211;no-p &#8211;no-g &#8211;no-o&#8221;). Completely fixed it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/strange-problems-with-hosts-resolving-in-php-and-some-other-linux-weirdness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HAProxy&#8217;s keep-alive functionality (and how it can speed up your site)</title>
		<link>http://blog.killtheradio.net/technology/haproxys-keep-alive-functionality-and-how-it-can-speed-up-your-site/</link>
		<comments>http://blog.killtheradio.net/technology/haproxys-keep-alive-functionality-and-how-it-can-speed-up-your-site/#comments</comments>
		<pubDate>Tue, 11 May 2010 02:32:30 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[keep-alive]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[web servers]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=554</guid>
		<description><![CDATA[A while back I wrote a post about using NginX as a reverse-proxy cache for PHP (or whatever your backend is) and mentioned how I was using HAProxy to load balance. The main author of HAProxy wrote a comment about keep-alive support and how it would make things faster. At the time, I thought &#8220;What&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>A while back I wrote a post about using <a href="http://blog.killtheradio.net/technology/nginx-as-a-caching-reverse-proxy-for-php/">NginX as a reverse-proxy cache for PHP</a> (or whatever your backend is) and mentioned how I was using <a href="http://haproxy.1wt.eu/">HAProxy</a> to load balance. The main author of HAProxy wrote a comment about keep-alive support and how it would make things faster.</p>
<p>At the time, I thought &#8220;What&#8217;s the point of keep-alive for front-end? By the time the user navigates to the next page of your site, the timeout has expired, meaning a connection was left open for nothing.&#8221; This assumed that a user downloads the HTML for a site, and doesn&#8217;t download anything else until their next page request. I forgot about how some websites actually have things other than HTML, namely images, CSS, javascript, etc.</p>
<p>Well in a recent &#8220;omg I want everything 2x faster&#8221; frenzy, I decided for once to focus on the front-end. On beeets, we&#8217;re already using <a href="http://aws.amazon.com/s3/">S3</a> with <a title="ooooh! its &quot;THE CLOUD&quot; oooooh!!" href="http://aws.amazon.com/cloudfront/">CloudFront</a> (a CDN), aggressive HTTP caching, etc. I decided to try the latest HAProxy (1.4.4) with keep-alive.</p>
<p>I got it, compiled it, reconfigured:</p>
<pre>defaults
	...
	option httpclose

became:
defaults
	...
	timeout client  5000
	option http-server-close</pre>
<p>Easy enough&#8230;that tells HAProxy to close the server-side connection, but leave the client connection open for 5 seconds.</p>
<p>Well, a quick test and site load times were down by a little less than half&#8230;from about 1.1s client load time (empty cache) to 0.6s. An almost instant benefit. How does this work?</p>
<p>Normally, your browser hits the site. It requests /page.html, and the server says &#8220;here u go, lol&#8221; and closes the connection. Your browser reads page.html and says &#8220;hay wait, I need site.css too.&#8221; It opens a new connection and the web server hands the browser site.css and closes the connection. The browser then says &#8220;darn, I need omfg.js.&#8221; It opens another connection, and the server rolls its eyes, sighs, and hands it omfg.js.</p>
<p>That&#8217;s three connections, with high latency each, your browser made to the server. <a href="http://rescomp.stanford.edu/~cheshire/rants/Latency.html">Connection latency</a> is something that, no matter how hard you try, you cannot control&#8230;and there is a certain amount of latency for each of the connections your browser opens. Let&#8217;s say you have a connection latency of 200ms (not uncommon)&#8230;that&#8217;s 600ms you just waited to load a very minimal HTML page.</p>
<p>There is hope though&#8230;instead of trying to lower latency, you can open fewer connections. This is where keep-alive comes in.</p>
<p>With the new version of HAProxy, your browser says &#8220;hai, give me /page.html, but keep the connection open plz!&#8221; The web server hands over page.html and holds the connection open. The browser reads all the files it needs from page.html (site.css and omfg.js) and requests them over the connection that&#8217;s already open. The server keeps this connection open until the client closes it or until the timeout is reached (5 seconds, using the above config). In this case, the latency is a little over 200ms, the total time to load the page 200ms + the download time of the files (usually less than the latency).</p>
<p>So with keep-alive, you just turned a 650ms page-load time into a 250ms page-load time&#8230; a much larger margin than any sort of back-end tweaking you can do. Keep in mind most servers already support keep-alive&#8230;but I&#8217;m compelled to write about it because I use HAProxy and it&#8217;s now fully implemented.</p>
<p>Also keep in mind that the above scenario isn&#8217;t necessarily correct. Most browsers will open up to 6 concurrent connections to a single domain when loading a page, but you also have to factor in the fact that the browser blocks downloads when it encounters a javascript include, and then attempts to download and run the javascript before continuing the page load.</p>
<p>So although your connection latency with multiple requests goes down with keep-alive, you won&#8217;t get a 300% speed boost, more likely a 100% speed boost depending on how many scripts are loading in your page along with any other elements&#8230;100% is a LOT though.</p>
<p>So for most of us webmasters, keep-alive is a wonderful thing (assuming it has sane limits and timeouts). It can really save a lot of page load time on the front-end, which is where users spend the most of their time waiting. But if you happen to have a website that&#8217;s only HTML, keep-alive won&#8217;t do you much good =).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/haproxys-keep-alive-functionality-and-how-it-can-speed-up-your-site/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using gzip_static in nginx to cache gzip files</title>
		<link>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/</link>
		<comments>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/#comments</comments>
		<pubDate>Tue, 04 May 2010 03:54:12 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=542</guid>
		<description><![CDATA[Recently I&#8217;ve been working on speeding up the homepage of beeets.com. Most speed tests say it takes between 4-6 seconds. Obviously, all of them are somehow fatally flawed. I digress, though. Everyone (who&#8217;s anyone) knows that gzipping your content is a great way to reduce download time for your users. It can cut the size [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been working on speeding up the homepage of <a href="http://beeets.com/local-events/Santa+Cruz+CA">beeets.com</a>. Most speed tests say it takes between 4-6 seconds. Obviously, all of them are somehow fatally flawed. I digress, though.</p>
<p>Everyone (who&#8217;s anyone) knows that gzipping your content is a great way to reduce download time for your users. It can cut the size of html, css, and javascript by about 60-90%. Everyone also knows that gzipping can be very cpu intensive. <span style="text-decoration: underline;">Not anymore</span>.</p>
<p>I just installed <a href="http://wiki.nginx.org/NginxHttpGzipStaticModule">nginx&#8217;s Gzip Static Module</a> (compile nginx with &#8211;with-http_gzip_static_module) on beeets.com. It allows you to pre-cache your gzip files. What?</p>
<p>Let&#8217;s say you have the file /css/beeets.css. When a request for beeets.css comes through. the static gzip module will look for /css/beeets.css.gz. If it finds it, it will serve that file as gzipped content. This allows you to gzip your static files using the highest compression ratio (gzip -9) when deploying your site. Nginx then has absolutely no work to do besides serving the static gzip file (it&#8217;s very good at serving static content).</p>
<p>Wherever you have a gzip section in your nginx config, you can do:</p>
<pre>gzip_static on;</pre>
<p>That&#8217;s it. Note that you will have to create the .gz versions of the files yourself, and it&#8217;s mentioned in the docs that it&#8217;s better if the original and the .gz files have the same timestamp; so it may be a good idea to &#8220;touch&#8221; the files after both are created. It&#8217;s also a good idea to turn the gzip compression down (<a href="http://wiki.nginx.org/NginxHttpGzipModule#gzip_comp_level">gzip_comp_level 1..3</a>). This will minimally compress dynamic content without putting too much strain on the server.</p>
<p>This is a great way to get the best of both worlds: gzipping (faster downloads) <em>without</em> the extra load on the server. Once again, nginx pulls through as the best thing since multi-cellular life. Keep in mind that this only works on static content (css, javascript, etc etc). Dynamic pages can and should be gzipped, but with a lower compression ratio to keep load off the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>LiteSpeed &#8211; The upstanding Christian webserver</title>
		<link>http://blog.killtheradio.net/funny/litespeed-the-upstanding-christian-webserver/</link>
		<comments>http://blog.killtheradio.net/funny/litespeed-the-upstanding-christian-webserver/#comments</comments>
		<pubDate>Tue, 04 May 2010 03:33:21 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Funny]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[web servers]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=534</guid>
		<description><![CDATA[I never thought I&#8217;d see the day where people who build web servers would care what other people use them to host. In section 1 of LiteSpeed&#8217;s licence agreement you will see &#8220;You cannot use the SOFTWARE PRODUCT for any illegal activity or to host pornographic content.&#8221; HA! That&#8217;s the stupidest thing I&#8217;ve ever seen. [...]]]></description>
			<content:encoded><![CDATA[<p><object width="400" height="320" style="float: right; padding-left: 10px;"><param name="movie" value="http://www.youtube.com/v/hp4iiI5qTJk&#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/hp4iiI5qTJk&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="400" height="320"></embed></object>I never thought I&#8217;d see the day where people who build web servers would care what other people use them to host. In section 1 of <a rel="nofollow" href="http://www.litespeedtech.com/trial/license">LiteSpeed&#8217;s licence agreement</a> you will see &#8220;You cannot use the SOFTWARE PRODUCT for any illegal activity or to host pornographic content.&#8221; HA!</p>
<p>That&#8217;s the stupidest thing I&#8217;ve ever seen. What kind of business limits the usage of its products to upstanding citizens only? Last I checked it was the government&#8217;s job to impose its views on businesses, not businesses imposing their views on their customers.</p>
<p>I have to say, it&#8217;s nice that someone is using their business to take a stand, I guess I&#8217;d just prefer it to be in defense of free speech and expression. Sure ALL porn is smutty and violent, but that&#8217;s expression in itself. Also, can you fight basic human nature? Perhaps, on a personal level. Repression of sexual tendencies is a lot different than acceptance and non-action though. My point is that pornography is the one place where sexual fantasies are <span style="text-decoration: underline;">allowed</span> to exist in any way shape and/or form, and Americans, being extremely sexually self-repressed, <em>need</em> that outlet, not more repression.</p>
<p>I also think it&#8217;s funny when someone tries to be exclusive because they&#8217;re SO awesome when <a href="http://nginx.org/">someone else is doing it way better</a>&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/funny/litespeed-the-upstanding-christian-webserver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blog.killtheradio.net/feed/ ) in 0.56551 seconds, on May 21st, 2013 at 6:28 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 21st, 2013 at 7:28 am UTC -->
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!-- Quick Cache Is Fully Functional :-) ... A Quick Cache file was just served for (  blog.killtheradio.net/feed/ ) in 0.00128 seconds, on May 21st, 2013 at 6:52 am UTC. -->