<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>printf(" SaltwaterC ");</title>
	
	<link>http://www.saltwaterc.eu</link>
	<description>/dev/urandom</description>
	<lastBuildDate>Sun, 23 Dec 2012 17:01:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/saltwaterc/eu" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="saltwaterc/eu" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>git is distributed, stupid</title>
		<link>http://www.saltwaterc.eu/git-is-distributed-stupid.html</link>
		<comments>http://www.saltwaterc.eu/git-is-distributed-stupid.html#comments</comments>
		<pubDate>Sun, 23 Dec 2012 17:01:28 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1475</guid>
		<description><![CDATA[There&#8217;s no news that pretty often the popular code hosting services, like GitHub or Bitbucket, go down when you least expect it. Especially GitHub, or so it seems. From time to time I get into my feed reader yet another entry from Hacker News that &#8220;GitHub is down&#8221;. However, being hit by this problem, I [...]]]></description>
				<content:encoded><![CDATA[<p>There&#8217;s no news that pretty often the popular code hosting services, like GitHub or Bitbucket, go down when you least expect it. Especially GitHub, or so it seems. From time to time I get into my feed reader yet another entry from Hacker News that &#8220;GitHub is down&#8221;.</p>
<p>However, being hit by this problem, I managed to work around it by simply using stuff that&#8217;s already part of git itself. No need for going in panic mode for every GitHub hiccup. git is distributed, stupid.</p>
<p>I&#8217;ve seen a lot of solutions or proposals, but none of them were KISS compliant (or should I say: blog post title compliant), like using a different remote for pushing to a secondary service, or using hooks. Found out that git supports multiple url entries per remote, but the functionality isn&#8217;t exposed into the interface itself. You need to actually edit the config file.</p>
<p>Fortunately, git exposes a config edit shortcut: &#8220;git config -e&#8221; which opens the repository configuration file &#8220;.git/config&#8221; with the default editor. Found out that &#8220;git config -e&#8221; is easier to remember, but YMMV.</p>
<p>A real world example from one of my projects:</p>
<pre>[remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = git@bitbucket.org:SaltwaterC/aws2js.git
        url = git@github.com:SaltwaterC/aws2js.git</pre>
<p>This means that every time I issue a &#8220;git push [--tags] [remote branch]&#8221; everything is automatically synced in multiple remote repositories, removing the single point of failure.</p>
<p>The ordering of the url entries is important as only the first is use for pulling the changes. If a specific url fails to accept the changes, then the rest of the url entries are ignored. Sure, some things may go out of sync for a while, but &#8220;eventually consistent&#8221; is the term you&#8217;re looking for in this scenario. You may pull changes between team members, but that&#8217;s not always applicable, therefore it doesn&#8217;t hurt to have some failover option.</p>
<p>I found out that Bitbucket is a little bit more stable that GitHub. It defaults to that. Used to be the other way though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/git-is-distributed-stupid.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use the cache, Luke, Part 2: don’t put all your eggs into the memcached buck … basket</title>
		<link>http://www.saltwaterc.eu/use-the-cache-luke-part-2-dont-put-all-your-eggs-into-the-memcached-buck-basket.html</link>
		<comments>http://www.saltwaterc.eu/use-the-cache-luke-part-2-dont-put-all-your-eggs-into-the-memcached-buck-basket.html#comments</comments>
		<pubDate>Mon, 17 Dec 2012 15:16:13 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1331</guid>
		<description><![CDATA[This is the second part of a series called: Use the cache, Luke. If you missed the first part, here it is: From memcached to Membase memcached buckets. Meanwhile, the AWS ElastiCache service proved to have better network latency than our own rolled out Membase setup, therefore the migration was easily done by simply switching [...]]]></description>
				<content:encoded><![CDATA[<p>This is the second part of a series called: Use the cache, Luke. If you missed the first part, here it is: <a href="http://www.saltwaterc.eu/use-the-cache-luke-part-1-from-memcached-to-membase-memcached-buckets.html" title="Use the cache, Luke, Part 1: from memcached to Membase memcached buckets">From memcached to Membase memcached buckets</a>. Meanwhile, the AWS ElastiCache service proved to have better network latency than our own rolled out Membase setup, therefore the migration was easily done by simply switching the memcached config. No vendor lock in.</p>
<p>However, it took me a while to write this second part.</p>
<p><object width="448" height="386"><param name="movie" value="http://a.blip.tv/scripts/flash/stratos.swf#file=http%3A%2F%2Fblip.tv%2Frss%2Fflash%2F5572403"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="none"></param>
	<embed src="http://a.blip.tv/scripts/flash/stratos.swf#file=http%3A%2F%2Fblip.tv%2Frss%2Fflash%2F5572403" type="application/x-shockwave-flash" allowscriptaccess="none" allowfullscreen="true" width="448" height="386"></embed></object></p>
<p>Please have a look at the above video. Besides the general common sense guidelines about how to scale your stuff, and the Postgres typical stuff, there&#8217;s a general rule: cache, cache, and then cache some more.</p>
<p>However, too much caching in memcache (whatever implementation) may kill the application at some point. The application may not be database dependent, but it is cache dependent. Anything that affects the cache may have the effect of a sledgehammer on your database. Of couse, you can always scale vertically that DB instance, scale horizontally by adding read-only replicas, but the not-so-fun part is that it costs a lot just to have the provisioned resources in order to survive a cache failure.</p>
<p>The second option is to have a short lived failover cache on the application server. Something like five minutes, while the distributed cache from memcache may last for hours. Enough to keep the database from being hit from live traffic, while you don&#8217;t have to provision a really large database instance. Of course, it won&#8217;t work with stuff that needs some &#8220;real time&#8221; junk, but it works with data that doesn&#8217;t change with each request.</p>
<p>There are a lot of options for a failover cache since there&#8217;s no distributed setup to think about. It may be a memcached daemon, something like PHP&#8217;s APC API, or,  the fastest option: the file based caching. Now you may think that I&#8217;m insane, but memcached still has the IPC penalty, especially for TCP communication, while if you&#8217;re a PHP user, APC doesn&#8217;t perform as expected.</p>
<p>I say file based caching, not disk based caching, as the kernel does a pretty good job at &#8220;<a href="http://www.linuxatemyram.com/" title="Help! Linux ate my RAM!">eating your RAM</a>&#8221; with the disk caching stuff. It takes more to implement it since the cache management logic must be implemented into the application itself, you don&#8217;t have stuff like LRU, expiration, etc. by default, but for failover reasons, it is good enough to worth the effort. In fact, it ran for a few days on the failover cache without any measurable impact.</p>
<p>The next part for not using the same basket for all of your eggs is: cache everywhere you can. For example, by using the <a href="http://blog.killtheradio.net/technology/nginx-as-a-caching-reverse-proxy-for-php/" title="nginx as a caching reverse proxy for PHP">nginx FastCGI cache</a>, we could shave off 40% of our CPU load. Nothing experimental about this last part. It is production for the last 18 months. If you get it right, then it could be a really valuable addition to a web stack. However, a lot of testing is required before pushing the changes to production. We hit a lot of weird bugs for edge cases. The rule of thumb is: if you get the cache key right, then most of the issues are gone before going live.</p>
<p>In fact, by adding the cache control stuff from the application itself, we could push relatively shortly lived pages to the CDN edges, shaving off a lot of latency for repeated requests as there&#8217;s no round trip from the hosting data center to the CDN edge. Yes, <a href="http://www.stuartcheshire.org/rants/Latency.html" title="It's the Latency, Stupid">it&#8217;s the latency, stupid</a>. The dynamic acceleration that CDNs provide is nice. Leveraging the HTTP caching capabilities is nicer. Having the application in a data center closer to the client is desirable, but unless your target market is more distributed than having a bunch of machines into the same geo location, it doesn&#8217;t make any sense to deploy into a new data center which adds its fair share of complexity when scaling the data layer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/use-the-cache-luke-part-2-dont-put-all-your-eggs-into-the-memcached-buck-basket.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reverse dependencies for the installed packages in Debian + friends</title>
		<link>http://www.saltwaterc.eu/reverse-dependencies-for-the-installed-packages-in-debian-friends.html</link>
		<comments>http://www.saltwaterc.eu/reverse-dependencies-for-the-installed-packages-in-debian-friends.html#comments</comments>
		<pubDate>Wed, 12 Dec 2012 10:14:08 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1448</guid>
		<description><![CDATA[Some libraries are more libraries than others. It is one of those moments when you ask yourself if migrating to a newer version of a library fucks up the entire system. But you need that foo library as it implements feature bar. In my case, I wanted libpcre3 8.20+ in order to enable PCRE JIT. [...]]]></description>
				<content:encoded><![CDATA[<p>Some libraries are more libraries than others. It is one of those moments when you ask yourself if migrating to a newer version of a library fucks up the entire system. But you need that foo library as it implements feature bar. In my case, I wanted libpcre3 8.20+ in order to enable PCRE JIT. Though luck. Not even Debian sid packages 8.20.</p>
<p>Now I know that there&#8217;s apt-cache rdepends, but it lists <em>all</em> the reverse dependencies of a specific package. I needed just the reverse dependencies of the <em>installed</em> packages. With a little bash-fu, here it goes:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> package_rdepends
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">for</span> package <span style="color: #000000; font-weight: bold;">in</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">apt-cache rdepends</span> <span style="color: #007800;">$1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-Ev</span> <span style="color: #ff0000;">&quot;^$1$&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #ff0000;">'Reverse Depends:'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">do</span>
		<span style="color: #c20cb9; font-weight: bold;">apt-cache policy</span> <span style="color: #007800;">$package</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">'Installed: (none)'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
		<span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$package</span>
		<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
package_rdepends <span style="color: #007800;">$1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span></pre></td></tr></table></div>

<p>Saved as installed-rdepends. Made executable.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>installed-rdepends libpcre3
<span style="color: #c20cb9; font-weight: bold;">grep</span>
libglib2.0-<span style="color: #000000;">0</span>
libglib2.0-dev
libpcre3-dev
libpcrecpp0</pre></td></tr></table></div>

<p>The above script may be slow for packages with many reverse dependencies due to the fact that each package has an individual lookup. Didn&#8217;t have the patience to measure the time it takes to do a lookup for libc6. Some benchmarks for the package lookup:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">time</span> <span style="color: #c20cb9; font-weight: bold;">apt-cache policy</span> libpcre3 <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">'Installed: (none)'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
&nbsp;
real	0m0.006s
user	0m0.005s
sys	0m0.003s
&nbsp;
<span style="color: #000000; font-weight: bold;">time</span> <span style="color: #c20cb9; font-weight: bold;">dpkg</span> <span style="color: #660033;">-L</span> libpcre3 <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
&nbsp;
real	0m0.017s
user	0m0.012s
sys	0m0.005s
&nbsp;
<span style="color: #000000; font-weight: bold;">time</span> <span style="color: #c20cb9; font-weight: bold;">dpkg</span> <span style="color: #660033;">-l</span> libpcre3 <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
&nbsp;
real	0m0.667s
user	0m0.600s
sys	0m0.067s
&nbsp;
<span style="color: #000000; font-weight: bold;">time</span> <span style="color: #c20cb9; font-weight: bold;">dpkg</span> <span style="color: #660033;">-s</span> libpcre3 <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
&nbsp;
real	0m0.587s
user	0m0.533s
sys	0m0.054s
&nbsp;
<span style="color: #000000; font-weight: bold;">time</span> <span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>dpkg<span style="color: #000000; font-weight: bold;">/</span>available <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #ff0000;">&quot;Package: libpcre3$&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
&nbsp;
real	0m0.034s
user	0m0.015s
sys	0m0.048s</pre></td></tr></table></div>

<p>However, I didn&#8217;t try these results on a bare metal installation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/reverse-dependencies-for-the-installed-packages-in-debian-friends.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inlining the PEM encoded files in node.js</title>
		<link>http://www.saltwaterc.eu/inlining-the-pem-encoded-files-in-node-js.html</link>
		<comments>http://www.saltwaterc.eu/inlining-the-pem-encoded-files-in-node-js.html#comments</comments>
		<pubDate>Fri, 07 Dec 2012 15:14:42 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1439</guid>
		<description><![CDATA[Multi line strings in JavaScript are a bitch. At least till ES6. The canonical example for a node.js HTTPS server is: // curl -k https://localhost:8000/ var https = require&#40;'https'&#41;; var fs = require&#40;'fs'&#41;; &#160; var options = &#123; key: fs.readFileSync&#40;'test/fixtures/keys/agent2-key.pem'&#41;, cert: fs.readFileSync&#40;'test/fixtures/keys/agent2-cert.pem'&#41; &#125;; &#160; https.createServer&#40;options, function &#40;req, res&#41; &#123; res.writeHead&#40;200&#41;; res.end&#40;&#34;hello world\n&#34;&#41;; &#125;&#41;.listen&#40;8000&#41;; All fine [...]]]></description>
				<content:encoded><![CDATA[<p>Multi line strings in JavaScript are a bitch. At least till ES6. The canonical example for a node.js HTTPS server is:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// curl -k https://localhost:8000/</span>
<span style="color: #000066; font-weight: bold;">var</span> https <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'https'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">var</span> fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">var</span> options <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  key<span style="color: #339933;">:</span> fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'test/fixtures/keys/agent2-key.pem'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  cert<span style="color: #339933;">:</span> fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'test/fixtures/keys/agent2-cert.pem'</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
https.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span>options<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  res.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  res.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;hello world<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>All fine and dandy as the sync operation doesn&#8217;t penalize the event loop. It is associated with the server startup cost. However, <a href="http://www.jslint.com/" title="jslint">jslint</a> yells about using sync operations. As the code is part of the boilerplate for testing <a href="https://github.com/SaltwaterC/http-get" title="http-get">http-get</a>, refactoring didn&#8217;t make enough sense. Making jslint to <a href="http://www.jslint.com/lint.html" title="stupidity:true">STFU</a> is usually the last option. The content of the files never changes, therefore it doesn&#8217;t make any sense to read them from the disk either. Inlining is the obvious option.</p>
<p>Couldn&#8217;t find any online tool to play with. Therefore I fired a PHP REPL, then used my PCRE-fu to solve this one. The solution doesn&#8217;t look pretty, but it gets the job done:</p>
<pre>
php > var_dump(preg_replace('/\n/', '\n\\' . "\n", file_get_contents('server.key')));
string(932) "-----BEGIN RSA PRIVATE KEY-----\n\
MIICXAIBAAKBgQCvZg+myk7tW/BLin070Sy23xysNS/e9e5W+fYLmjYe1WW9BEWQ\n\
iDp2V7dpkGfNIuYFTLjwOdNQwEaiqbu5C1/4zk21BreIZY6SiyX8aB3kyDKlAA9w\n\
PvUYgoAD/HlEg9J3A2GHiL/z//xAwNmAs0vVr7k841SesMOlbZSe69DazwIDAQAB\n\
AoGAG+HLhyYN2emNj1Sah9G+m+tnsXBbBcRueOEPXdTL2abun1d4f3tIX9udymgs\n\
OA3eJuWFWJq4ntOR5vW4Y7gNL0p2k3oxdB+DWfwQAaUoV5tb9UQy6n7Q/+sJeTuM\n\
J8EGqkr4kEq+DAt2KzWry9V6MABpkedAOBW/9Yco3ilWLnECQQDlgbC5CM2hv8eG\n\
P0xJXb1tgEg//7hlIo9kx0sdkko1E4/1QEHe6VWMhfyDXsfb+b71aw0wL7bbiEEl\n\
RO994t/NAkEAw6Vjxk/4BpwWRo9c/HJ8Fr0os3nB7qwvFIvYckGSCl+sxv69pSlD\n\
P6g7M4b4swBfTR06vMYSGVjMcaIR9icxCwJAI6c7EfOpJjiJwXQx4K/cTpeAIdkT\n\
BzsQNaK0K5rfRlGMqpfZ48wxywvBh5MAz06D+NIxkUvIR2BqZmTII7FL/QJBAJ+w\n\
OwP++b7LYBMvqQIUn9wfgT0cwIIC4Fqw2nZHtt/ov6mc+0X3rAAlXEzuecgBIchb\n\
dznloZg2toh5dJep3YkCQAIY4EYUA1QRD8KWRJ2tz0LKb2BUriArTf1fglWBjv2z\n\
wdkSgf5QYY1Wz8M14rqgajU5fySN7nRDFz/wFRskcgY=\n\
-----END RSA PRIVATE KEY-----\n\
"
php > var_dump(preg_replace('/\n/', '\n\\' . "\n", file_get_contents('server.cert')));
string(892) "-----BEGIN CERTIFICATE-----\n\
MIICRTCCAa4CCQDTefadG9Mw0TANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJS\n\
TzEOMAwGA1UECBMFU2liaXUxDjAMBgNVBAcTBVNpYml1MSEwHwYDVQQKExhJbnRl\n\
cm5ldCBXaWRnaXRzIFB0eSBMdGQxFDASBgNVBAMTC1N0ZWZhbiBSdXN1MCAXDTEx\n\
MDgwMTE0MjU0N1oYDzIxMTEwNzA4MTQyNTQ3WjBmMQswCQYDVQQGEwJSTzEOMAwG\n\
A1UECBMFU2liaXUxDjAMBgNVBAcTBVNpYml1MSEwHwYDVQQKExhJbnRlcm5ldCBX\n\
aWRnaXRzIFB0eSBMdGQxFDASBgNVBAMTC1N0ZWZhbiBSdXN1MIGfMA0GCSqGSIb3\n\
DQEBAQUAA4GNADCBiQKBgQCvZg+myk7tW/BLin070Sy23xysNS/e9e5W+fYLmjYe\n\
1WW9BEWQiDp2V7dpkGfNIuYFTLjwOdNQwEaiqbu5C1/4zk21BreIZY6SiyX8aB3k\n\
yDKlAA9wPvUYgoAD/HlEg9J3A2GHiL/z//xAwNmAs0vVr7k841SesMOlbZSe69Da\n\
zwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACgdP59N5IvN3yCD7atszTBoeOoK5rEz\n\
5+X8hhcO+H1sEY2bTZK9SP8ctyuHD0Ft8X0vRO7tdt8Tmo6UFD6ysa/q3l0VVMVY\n\
abnKQzWbLt+MHkfPrEJmQfSe2XntEKgUJWrhRCwPomFkXb4LciLjjgYWQSI2G0ez\n\
BfxB907vgNqP\n\
-----END CERTIFICATE-----\n\
"
php >
</pre>
<p>This gave me usable multi line strings that don&#8217;t break the PEM encoding.</p>
<p><strong>Update:</strong> shell one liner with Perl</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> certificate.pem <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/\n/\\n\\\n/'</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/inlining-the-pem-encoded-files-in-node-js.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doing what Dropbox is doing and doing it wrong</title>
		<link>http://www.saltwaterc.eu/doing-what-dropbox-is-doing-and-doing-it-wrong.html</link>
		<comments>http://www.saltwaterc.eu/doing-what-dropbox-is-doing-and-doing-it-wrong.html#comments</comments>
		<pubDate>Thu, 06 Dec 2012 16:35:30 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1436</guid>
		<description><![CDATA[Let&#8217;s take a couple of examples. Switched from an older machine recently, therefore I need to setup all my stuff. As I don&#8217;t like to depend on a single service, for redundancy&#8217;s sake, I also keep a backup for Dropbox. SpiderOak &#8211; backs up stuff, uses client side encryption, has optional sync between your machines. [...]]]></description>
				<content:encoded><![CDATA[<p>Let&#8217;s take a couple of examples. Switched from an older machine recently, therefore I need to setup all my stuff. As I don&#8217;t like to depend on a single service, for redundancy&#8217;s sake, I also keep a backup for Dropbox.</p>
<p><strong>SpiderOak</strong> &#8211; backs up stuff, uses client side encryption, has optional sync between your machines. So far, so good. In the latest OS X client, at least, the possibility to paste the password is missing. Thanks, I&#8217;ll me use my password manager instead with services that don&#8217;t do such a braindead thing. Seriously, there&#8217;s a thing that improves the security of the password authentication. It is called two factor authentication. Dropbox has it. Google has it. In fact, any decent service has it. Disabling the possibility to paste the password, not so much.</p>
<p><strong>Google Drive</strong> &#8211; you wouldn&#8217;t think I&#8217;m letting Google of the hook this time. As I don&#8217;t trust with my data these sync services, I always do client side encryption. Dropbox doesn&#8217;t choke on it, SpiderOak doesn&#8217;t choke on it. Google Drive must be a special kind of breed as it chokes on my encrypted files with &#8220;Upload Error &#8211; An unknown issue has occurred &#8221;. Gee, let me fix the error message for you: &#8220;your piece of shit encrypted files aren&#8217;t of any use for us, there&#8217;s no personal info there&#8221;. Was it that difficult? Thanks, but the market is full of alternatives. Seriously Google, you could do better than this &#8220;not being evil&#8221; thing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/doing-what-dropbox-is-doing-and-doing-it-wrong.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Async frameworks “Hello World” showdown</title>
		<link>http://www.saltwaterc.eu/async-frameworks-hello-world-showdown.html</link>
		<comments>http://www.saltwaterc.eu/async-frameworks-hello-world-showdown.html#comments</comments>
		<pubDate>Sat, 12 May 2012 14:05:35 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1411</guid>
		<description><![CDATA[This is not intended to be a proper comparison between these frameworks. However, since the &#8220;Hello World&#8221; test is the lowest common denominator, it is a pretty clear indicator that an application can&#8217;t exceed in performance these numbers. Also, what Guillermo did not understand from my comment is the fact that 1000 requests at the [...]]]></description>
				<content:encoded><![CDATA[<p>This is not intended to be a proper comparison between these frameworks. However, since the &#8220;Hello World&#8221; test is the lowest common denominator, it is a pretty clear indicator that an application can&#8217;t exceed in performance these numbers. Also, what <a href="http://www.devthought.com/2012/02/08/node-http-hello-world-showdown/">Guillermo did not understand from my comment</a> is the fact that 1000 requests at the concurrency of 10 is way to few for get a proper picture of a &#8220;Hello World&#8221; showdown.</p>
<p>Tested frameworks:</p>
<ul>
<li>node.js &#8211; v0.6.17</li>
<li>vert.x &#8211; v1.0 final + OpenJDK 7 installed from the Ubuntu repository &#8211; using the JavaScript bindings</li>
<li>luanode &#8211; built from the master branch using the Ubuntu provided lua dependencies</li>
<li>luvit &#8211; built from the master branch</li>
<li>react &#8211; cloned the master branch</li>
</ul>
<p>I also wanted to test node.native, but it kept <a href="https://github.com/d5/node.native/issues/4">crashing on me</a>. You can see that it is a pretty old issue. I didn&#8217;t have the patience to make the v0.1.0 branch to work with the previously used code. But I&#8217;d like to give it a run for its money.</p>
<p>The system used for the testing is a modest Athlon II X2 240e (2.8GHz) with 4GB or DDR2 800MHz running the latest Kubuntu 12.04 LTS amd64. Since ab pretty much takes a CPU core for itself, the frameworks ran a single process that occupied a single CPU core. I tried running a node.js HTTP server wrapped with the cluster module. Or passing -instances 2 to the vertx framework. The results were pretty much the same, therefore using just a single CPU core is a fair comparison.</p>
<p>The ab command that I used to hammer the Hello World! output:</p>
<blockquote><p>ab -r -k -n 1000000 -c 1000 http://127.0.0.1:{port_name}/</p></blockquote>
<p>The command ran at least a couple of times before saving the results. Just to make sure that everything is properly warmed up.</p>
<p>The averages graph:</p>
<p><a href="http://www.saltwaterc.eu/wp-content/uploads/graph.png" rel="lightbox-graph"><img class="alignnone  wp-image-1413" title="graph" src="http://www.saltwaterc.eu/wp-content/uploads/graph.png" alt="" width="537" height="422" /></a></p>
<p>The test sources and full ab output is available on <a href="https://gist.github.com/2666633">this gist</a>. There&#8217;s interesting output in the results.txt file for the stats nerds.</p>
<p>PS: I have the impression (but did not test) that vert.x may be a little bit faster, but ab is the actual bottleneck.</p>
<p><strong>Update:</strong> added React (node.php) to comparision. Too lazy to plot another graph. But at 1573.40 req/s, it is harly a match even for luanode. Used the PHP 5.3.10 from the Ubuntu repositories.</p>
<p><strong>Update:</strong> added another React (node.php) to comparision, but with a custom build of PHP 5.4.3. This time, it managed to get 3727.49 req/s.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/async-frameworks-hello-world-showdown.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>When no to use Amazon’s SimpleDB</title>
		<link>http://www.saltwaterc.eu/when-no-to-use-amazons-simpledb.html</link>
		<comments>http://www.saltwaterc.eu/when-no-to-use-amazons-simpledb.html#comments</comments>
		<pubDate>Fri, 11 May 2012 15:18:30 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1311</guid>
		<description><![CDATA[When it turns out that the cost for keeping few gigabytes of data is too fucking much. When it turns out that it is not keeping the most basic promises. The AWS marketing machine did it. Again. When it turns out that the latency is absolutely crap. I mean, SDB vs. RDS, as shown by [...]]]></description>
				<content:encoded><![CDATA[<p>When it turns out that the cost for keeping few gigabytes of data is too fucking much.</p>
<p>When it turns out that it is not keeping the most basic promises. The AWS marketing machine did it. Again.</p>
<p>When it turns out that the latency is absolutely crap. I mean, SDB vs. RDS, as shown by New Relic: 183 ms vs. 1.6 ms. And I&#8217;m only talking about averages. Plotting the whole stuff on a graph along with the standard deviation will drive insane a statistician.</p>
<p>I could go about this all day long. But why bother.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/when-no-to-use-amazons-simpledb.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Poor man’s tail recursion in node.js</title>
		<link>http://www.saltwaterc.eu/poor-mans-tail-recursion-in-node.js.html</link>
		<comments>http://www.saltwaterc.eu/poor-mans-tail-recursion-in-node.js.html#comments</comments>
		<pubDate>Fri, 30 Mar 2012 08:14:15 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1387</guid>
		<description><![CDATA[If you find yourself in the situation of doing recursion over a large-enough input in node.js, you may encounter this: node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ RangeError: Maximum call stack size exceeded Oops, I smashed the stack. You may reproduce it with something like this: var foo = [...]]]></description>
				<content:encoded><![CDATA[<p>If you find yourself in the situation of doing recursion over a large-enough input in node.js, you may encounter this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">node.<span style="color: #660066;">js</span><span style="color: #339933;">:</span><span style="color: #CC0000;">201</span>
        <span style="color: #000066; font-weight: bold;">throw</span> e<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// process.nextTick error, or 'error' event on first tick</span>
              <span style="color: #339933;">^</span>
RangeError<span style="color: #339933;">:</span> Maximum call stack size exceeded</pre></td></tr></table></div>

<p>Oops, I smashed the stack. You may reproduce it with something like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> foo <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">1000000</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    foo.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">var</span> recur <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>bar<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>bar.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">var</span> baz <span style="color: #339933;">=</span> bar.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #006600; font-style: italic;">// do something with baz</span>
        recur<span style="color: #009900;">&#40;</span>bar<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// end of recursion, do your stuff</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
recur<span style="color: #009900;">&#40;</span>foo<span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>&#8220;Thanks, that&#8217;s very thoughtful. But you&#8217;re not helping.&#8221; Bear with me. The solution is the obvious tail call elimination. But JavaScript doesn&#8217;t have that optimization.</p>
<p>However, you may wrap the tail call in order to call the above recur() function in a new stack. The proper recur() implementation is:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> recur <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>bar<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>bar.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">var</span> baz <span style="color: #339933;">=</span> bar.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #006600; font-style: italic;">// do something with baz</span>
        process.<span style="color: #660066;">nextTick</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            recur<span style="color: #009900;">&#40;</span>bar<span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// end of recursion, do your stuff</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>Warning</strong>: please read this carefully. I gave you the solution for recurring over such a large input, but the performance is poor. Using process.nextTick (or a timer function such as setTimeout for that matter, slower BTW) is an expensive operation. Didn&#8217;t test where&#8217;s the actual bottleneck (epoll itself under Linux, libuv | libev, etc).</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">time</span> node recur.js
node recur.js  1.36s user 0.28s system <span style="color: #000000;">101</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">1.610</span> total</pre></td></tr></table></div>

<p>The cost of this method is high. Therefore, don&#8217;t attempt this in a web application. It kills the event loop. For instance, I don&#8217;t use node for writing web applications. It is a difficult task, while the cost of the event loop itself isn&#8217;t that negligible as you may think. It useful as long as the CPU time is negligible compared to the time spent doing IO. Therefore, please, don&#8217;t include me in the group of people that thinks about node as the hammer for all the problems you throw at it.</p>
<p>If you&#8217;re wondering why I won&#8217;t just simply iterate the object, the answer is simple: because that &#8220;do something with baz&#8221; involves some async IO that would kill the second data provider. Sequential calls ensure that everybody in the architecture stays happy. Besides, I don&#8217;t actually use bar.pop(), but something like bar.splice(0, 5000) for packing more data in less remote calls and less events. bar.shift() in a situation like this is as slow as molasses in January. In an async framework, the order of the items from a TODO list is not relevant, therefore use the fastest way.</p>
<p>If you&#8217;re still wondering why I still use a solution like this, the above technique is part of the cost associated with the start-up cost. The application fetches all the required data in RAM. Having the application to kill the event loop for 20-30 seconds before hitting the Internet pipe is negligible for a process that runs for hours or days. After the application hits the Internet, only then I can say that node is in use for the stuff where it shines. I know, before this, I listed all the wrong reasons for using node as a tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/poor-mans-tail-recursion-in-node.js.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Computing file hashes with node.js</title>
		<link>http://www.saltwaterc.eu/computing-file-hashes-with-node.js.html</link>
		<comments>http://www.saltwaterc.eu/computing-file-hashes-with-node.js.html#comments</comments>
		<pubDate>Tue, 01 Nov 2011 10:52:38 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1375</guid>
		<description><![CDATA[Since node.js has the shiny crypto module which binds some stuff to the openssl library, people might be tempted to compute file hashes with node.js. At least the crypto manual page shows how to do a SHA1 for a given file (mimics sha1sum). Should people do this? The answer is: NO. Some may say because [...]]]></description>
				<content:encoded><![CDATA[<p>Since node.js has the shiny crypto module which binds some stuff to the openssl library, people might be tempted to compute file hashes with node.js. At least the crypto manual page shows how to do a SHA1 for a given file (mimics sha1sum). Should people do this? The answer is: <strong>NO</strong>. Some may say because <a href="http://teddziuba.com/2011/10/node-js-is-cancer.html" title="Node.js is Cancer">it blocks the event loop</a>. I say: because it is as slow as molasses in January. At least compared to dedicated tools.</p>
<p>Let&#8217;s have a look:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> filename <span style="color: #339933;">=</span> process.<span style="color: #660066;">argv</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">var</span> crypto <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'crypto'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">var</span> fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">var</span> shasum <span style="color: #339933;">=</span> crypto.<span style="color: #660066;">createHash</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sha256'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> fs.<span style="color: #660066;">ReadStream</span><span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
s.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'data'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>d<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  shasum.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span>d<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
s.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'end'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> shasum.<span style="color: #660066;">digest</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'hex'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>d <span style="color: #339933;">+</span> <span style="color: #3366CC;">'  '</span> <span style="color: #339933;">+</span> filename<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<blockquote><p>time node hash.js ubuntu-10.04.3-desktop-i386.iso<br />
208fb66dddda345aa264f7c85d011d6aeaa5588075eea6eee645fd5307ef3cac  ubuntu-10.04.3-desktop-i386.iso<br />
node hash.js ubuntu-10.04.3-desktop-i386.iso  28.92s user 0.80s system 100% cpu 29.661 total</p>
<p>time sha256sum ubuntu-10.04.3-desktop-i386.iso<br />
208fb66dddda345aa264f7c85d011d6aeaa5588075eea6eee645fd5307ef3cac  ubuntu-10.04.3-desktop-i386.iso<br />
sha256sum ubuntu-10.04.3-desktop-i386.iso  4.86s user 0.21s system 99% cpu 5.093 total</p>
<p>time openssl dgst -sha256 ubuntu-10.04.3-desktop-i386.iso<br />
SHA256(ubuntu-10.04.3-desktop-i386.iso)= 208fb66dddda345aa264f7c85d011d6aeaa5588075eea6eee645fd5307ef3cac<br />
openssl dgst -sha256 ubuntu-10.04.3-desktop-i386.iso  4.40s user 0.17s system 100% cpu 4.567 total</p></blockquote>
<p><strong>Edit</strong>: to sum up for those with little patience:</p>
<blockquote><p>
node hash.js &#8211; 29.661s<br />
sha256sum &#8211; 5.093s<br />
openssl dgst -sha256 &#8211; 4.567s
</p></blockquote>
<p><strong>/Edit</strong></p>
<p>That&#8217;s a ~6.5X speed boost just by invoking openssl alone instead of binding to its library. node.js does something terribly wrong somewhere since the file I/O is not to blame for the slowness:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> filename <span style="color: #339933;">=</span> process.<span style="color: #660066;">argv</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">var</span> fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> fs.<span style="color: #660066;">ReadStream</span><span style="color: #009900;">&#40;</span>filename<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
s.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'data'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>d<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
s.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'end'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<blockquote><p>
time node read.js ubuntu-10.04.3-desktop-i386.iso<br />
node read.js ubuntu-10.04.3-desktop-i386.iso  0.62s user 0.60s system 106% cpu 1.148 total
</p></blockquote>
<p>This little example that I hacked together shows that using child_process.exec is pretty fine:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> exec <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'child_process'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">exec</span><span style="color: #339933;">;</span>
exec<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/usr/bin/env openssl dgst -sha256 '</span> <span style="color: #339933;">+</span> process.<span style="color: #660066;">argv</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> stdout<span style="color: #339933;">,</span> stderr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		process.<span style="color: #660066;">stderr</span>.<span style="color: #660066;">write</span><span style="color: #009900;">&#40;</span>err.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>stdout.<span style="color: #660066;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #CC0000;">65</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">64</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<blockquote><p>
time node hash2.js ubuntu-10.04.3-desktop-i386.iso<br />
208fb66dddda345aa264f7c85d011d6aeaa5588075eea6eee645fd5307ef3cac<br />
node hash2.js ubuntu-10.04.3-desktop-i386.iso  4.44s user 0.19s system 100% cpu 4.630 total
</p></blockquote>
<p>So you can have your cake and eat it too. <a href="http://en.wikipedia.org/wiki/Unix_philosophy#McIlroy:_A_Quarter_Century_of_Unix" title="Unix philosophy">The guys with the philosophy</a> got this one right.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/computing-file-hashes-with-node.js.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Will it recur? Part 2: in depth analysis</title>
		<link>http://www.saltwaterc.eu/will-it-recur-part-2-in-depth-analysis.html</link>
		<comments>http://www.saltwaterc.eu/will-it-recur-part-2-in-depth-analysis.html#comments</comments>
		<pubDate>Wed, 12 Oct 2011 12:54:14 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1357</guid>
		<description><![CDATA[The social experiment This first chapter is not about recursion. One member of the community wrote that certain inflammatory statements that I use may upset people. I replied with: &#8220;buzz marketing&#8221;. Neutral articles, with neutral titles, written by nobodies like me, gain zero traction, although I may write something that&#8217;s technically sound. Cheap journalism has [...]]]></description>
				<content:encoded><![CDATA[<p><strong>The social experiment</strong></p>
<p>This first chapter is not about recursion. One member of the community wrote that certain inflammatory statements that I use may upset people. I replied with: &#8220;buzz marketing&#8221;. Neutral articles, with neutral titles, written by nobodies like me, gain zero traction, although I may write something that&#8217;s technically sound. Cheap journalism has more success. I even have graphs to prove it now.</p>
<p>The second stuff is the usefulness of my little experiment. I don&#8217;t know about others, but the curiosity was the main thing behind my whole benchmark. If it isn&#8217;t useful for some people, it doesn&#8217;t mean that it isn&#8217;t useful for others.</p>
<p>The other thing: the lack of tail recursion. I mean, do you need a &#8220;DUH&#8221; award, or something? The whole point of a &#8220;bad&#8221; algorithm that&#8217;s mathematically correct (well, almost, I stated that fibonacci(0) is wrong) is to prove how smart are specific compilers regarding recursion. The rest, simply do brute force.</p>
<p><strong>Patterns that emerge</strong></p>
<p>The numbers say something if you know how to read the page. There are runtimes that are optimized for doing proper recursion without bothering the programmer with it: C, D, PyPy, V8, LuaJIT, JVM. The rest aren&#8217;t: PHP, CPython, Ruby, Perl, Lua. PyPy and V8 could do better. LuaJIT is already close to the speed of unoptimized C and D. V8 isn&#8217;t the king of the hill if you take Ruby (MRI / KRI), CPython, plain Lua VM, and PHP (Zend Engine) out of the equation. This may be another opportunity to get bashed by the node.js benchmark police with &#8220;this is irrelevant&#8221; statements, although this wasn&#8217;t something that I wanted to prove.</p>
<p>Thing is, that for most of the web development, I rarely needed to actually solve purely recursive problems. At most a fairly simple tree. Sometimes even that simple tree didn&#8217;t actually require recursion. Therefore I get why some don&#8217;t optimize for this specific case, although they refer the thing as being &#8220;a general purpose language&#8221;.</p>
<p>For the &#8220;write better algorithms&#8221; crowd &#8230; WHY? The difference between C&#8217;s 0.6 seconds and Ruby&#8217;s 5 minutes doesn&#8217;t ring any bell that some things are fundamentally flawed regarding recursion?</p>
<p>As for the edge cases, there are 3rd party libraries that solve this issue without bothering the programmer. Or for other edge cases, such as applications that do complicated stuff, operating at Google-like scale, there are better tools that most mere mortals won&#8217;t use. The fact that some implementation do poor recursion is indeed irrelevant when the problems you&#8217;re trying to solve don&#8217;t include this.</p>
<p><strong>In the end</strong></p>
<p>Initially I wanted to try more stuff such as factorial, Euclid&#8217;s GCD, or the Ackermann function, for example. Try them on runtimes that don&#8217;t take longer than the next ice age to return a value. But why bother, except maybe to give the &#8220;one true way of doing recursion in functional languages&#8221; programmers a reason to bash stuff without returning any useful output. Not even an academic paper. It&#8217;s not productive.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/will-it-recur-part-2-in-depth-analysis.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>But the question is: will it recur? Part 1: fibonacci(40)</title>
		<link>http://www.saltwaterc.eu/but-the-question-is-will-it-recur-part-1-fibonacci40.html</link>
		<comments>http://www.saltwaterc.eu/but-the-question-is-will-it-recur-part-1-fibonacci40.html#comments</comments>
		<pubDate>Mon, 10 Oct 2011 14:10:51 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1334</guid>
		<description><![CDATA[A rant, maybe a bad rant due to babbling about philosophical reasons, made me wonder how the programming languages stack up against this stuff: recursion. Or should I say the runtimes, since the programming language itself is nothing but a bunch of text. I know that the algorithm itself is bad, but that&#8217;s the whole [...]]]></description>
				<content:encoded><![CDATA[<p>A <a href="http://teddziuba.com/2011/10/node-js-is-cancer.html" title="Node.js is Cancer">rant</a>, maybe a bad rant due to babbling about philosophical reasons, made me wonder how the programming languages stack up against this stuff: <a href="http://www.google.com/search?q=recursion" title="recursion">recursion</a>. Or should I say the runtimes, since the programming language itself is nothing but a bunch of text. I know that the algorithm itself is bad, but that&#8217;s the whole point. I know that fibonacci(0) yields a wrong result, but for the sake of lazyness, I kept the original algorithm.</p>
<p>The source code of all the tests is available <a href="http://www.saltwaterc.eu/wp-content/uploads/fib.zip">here</a> in order to make the tests to be reproducible. There wasn&#8217;t a high number of runs, particularly for the rutimes that take more than the next ice age. But the results are pretty consistent for specific runtimes. The relevant systems specs are: Ubuntu 10.04 amd64 (up to date), Q9400 CPU.</p>
<p>Now, less talk, more results.</p>
<p><strong>JavaScript (node.js/V8)</strong></p>
<blockquote><p>node -v: v0.4.12<br />
time node fib.js<br />
node fib.js  6.40s user 0.02s system 99% cpu 6.423 total<br />
node fib.js  6.39s user 0.02s system 99% cpu 6.410 total</p></blockquote>
<p>It may seem slow, but for a language with dynamic typing, it puts the rest from the same category to shame. Or most of them. Bear with me.</p>
<p><strong>PHP</strong></p>
<blockquote><p>php -v: PHP 5.3.8 (cli)<br />
time php fib.php<br />
php fib.php  77.57s user 0.06s system 99% cpu 1:17.66 total<br />
php fib.php  78.05s user 0.07s system 99% cpu 1:18.18 total</p></blockquote>
<p>Compared to the V8 runtime, PHP seems to take an eternity. It happens that PHP isn&#8217;t bad at recursion because <a href="https://bugs.php.net/bug.php?id=1901">it uses the stack</a>, but because the lack of speed of the runtime. But we&#8217;re not even halfway there. Stay tuned. PHP isn&#8217;t the only thing that sucks at recursion.</p>
<p><strong>C</strong></p>
<blockquote><p>gcc -v: gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)<br />
make fib<br />
time ./fib<br />
./fib  2.84s user 0.00s system 100% cpu 2.840 total<br />
./fib  2.84s user 0.00s system 100% cpu 2.835 total</p></blockquote>
<p>It wasn&#8217;t a surprise that C came up to this result. Which makes the V8 result even more interesting.</p>
<p><strong>Edit:</strong><br />
Forgot about the compiler optimization. Caught by Jabbles on HN.</p>
<blockquote><p>gcc -O4 fib.c -o fib<br />
time ./fib<br />
./fib  0.65s user 0.01s system 100% cpu 0.657 total<br />
gcc -O3 fib.c -o fib<br />
time ./fib<br />
./fib  0.66s user 0.00s system 100% cpu 0.657 total<br />
gcc -O2 fib.c -o fib<br />
time ./fib<br />
./fib  1.54s user 0.00s system 100% cpu 1.535 total<br />
gcc -O1 fib.c -o fib<br />
time ./fib<br />
./fib  0.00s user 0.00s system 0% cpu 0.001 total<br />
time ./fib<br />
165580141<br />
./fib  2.06s user 0.00s system 99% cpu 2.060 total
</p></blockquote>
<p>For some reason, the O1 flag hates this code. Printing fibonacci(40) yields a result closer to the result without any O flag. This brings it past the Java result, but only for O3+.<br />
<strong>/End Edit.</strong></p>
<p><strong>Lua</strong></p>
<blockquote><p>lua -v: Lua 5.1.4<br />
time lua fib.lua<br />
lua fib.lua  28.02s user 0.03s system 99% cpu 28.081 total<br />
lua fib.lua  28.86s user 0.02s system 99% cpu 28.883 total</p>
<p>./luajit -v: LuaJIT 2.0.0-beta8<br />
time ./luajit fib.lua<br />
./luajit fib.lua  10.59s user 0.00s system 99% cpu 10.591 total<br />
./luajit fib.lua  10.58s user 0.01s system 99% cpu 10.610 total</p></blockquote>
<p>Tested both of the implementations that I know of. I guess this article isn&#8217;t <a href="https://github.com/nddrylliog/blog/blob/master/nodejs-vs-jruby.md" title="node.js vs JRuby">that funny</a> for the generations of Lua coders that laugh about V8 in somebody&#8217;s face. Don&#8217;t get me wrong, I like Lua due to its simplicity, but in the speed realm, I still need to do some tests to verify some of those claims that sometimes appear to be overly inflated.</p>
<p><strong>Edit:</strong></p>
<p>With the following Lua script:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="lua" style="font-family:monospace;"><span style="color: #aa9900; font-weight: bold;">local</span> <span style="color: #aa9900; font-weight: bold;">function</span> fibonacci<span style="color: #66cc66;">&#40;</span>n<span style="color: #66cc66;">&#41;</span>
	<span style="color: #aa9900; font-weight: bold;">if</span> n <span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">2</span> <span style="color: #aa9900; font-weight: bold;">then</span>
		<span style="color: #aa9900; font-weight: bold;">return</span> <span style="color: #cc66cc;">1</span>
	<span style="color: #aa9900; font-weight: bold;">else</span>
		<span style="color: #aa9900; font-weight: bold;">return</span> fibonacci<span style="color: #66cc66;">&#40;</span>n <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> fibonacci<span style="color: #66cc66;">&#40;</span>n <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
	<span style="color: #aa9900; font-weight: bold;">end</span>
<span style="color: #aa9900; font-weight: bold;">end</span>
fibonacci<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>the results are getting better:</p>
<blockquote><p>
time lua fib.lua<br />
lua fib.lua  24.17s user 0.08s system 99% cpu 24.281 total<br />
lua fib.lua  24.24s user 0.01s system 99% cpu 24.307 total</p>
<p>[with LuaJIT v2.0.0-beta8 GIT HEAD]<br />
time ./luajit fib.lua<br />
./luajit fib.lua  2.02s user 0.00s system 99% cpu 2.026 total<br />
./luajit fib.lua  2.02s user 0.00s system 99% cpu 2.023 total
</p></blockquote>
<p>Now, some of the Lua chops can have a lulz about V8. This project is getting more interesting, especially for pairing LuaJIT with <a href="https://github.com/STPeters/luafcgid">luafcgid</a>. I forgot about the local keyword since my Lua experience is limited to basic testing. Nice comeback!</p>
<p><strong>/End Edit.</strong></p>
<p><strong>Python</strong></p>
<blockquote><p>python -V: Python 2.6.5<br />
time python fib.py<br />
python fib.py  59.42s user 0.02s system 99% cpu 59.494 total<br />
python fib.py  59.27s user 0.05s system 99% cpu 59.375 total</p>
<p>./configure<br />
make -j 4<br />
./python -V: Python 2.7.2<br />
time ./python fib.py<br />
./python fib.py  61.29s user 0.03s system 99% cpu 1:01.35 total<br />
./python fib.py  61.38s user 0.06s system 99% cpu 1:01.48 total</p>
<p>./configure<br />
make -j 4<br />
./python -V: Python 3.2.2<br />
./python fib.py  71.23s user 0.08s system 99% cpu 1:11.33 total<br />
./python fib.py  70.31s user 0.06s system 99% cpu 1:10.39 total</p>
<p>./pypy -V<br />
Python 2.7.1 (d8ac7d23d3ec, Aug 17 2011, 11:51:19)<br />
[PyPy 1.6.0 with GCC 4.4.3]<br />
./pypy fib.py  4.61s user 0.07s system 99% cpu 4.708 total<br />
./pypy fib.py  4.81s user 0.01s system 99% cpu 4.853 total</p></blockquote>
<p>Happens to have 2.6.5 around because Ubuntu says so. But in order to make the potential trolls to STFU about not using the latest versions, I made some fresh builds of 2.7.2 and 3.2.2. It gets even suckier with recent versions. In fact, the CPython runtime is struggling to catch up the PHP runtime on the slowness realm. The only Python runtime that is actually very impressive about the recursion stuff is PyPy. Which brings me to the first statement: the language is just a bunch of text. The runtime is the piece that sucks or does not suck. PyPy proves that with talented people shepherding the project, the language of the runtime implementation is quite irrelevant. This is the first implementation of a JIT that passes V8 as well.</p>
<p><strong>Ruby</strong></p>
<blockquote><p>ruby -v: ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]<br />
time ruby fib.rb<br />
ruby fib.rb  233.40s user 66.94s system 99% cpu 5:00.55 total<br />
ruby fib.rb  231.75s user 68.08s system 99% cpu 4:59.99 total</p>
<p>./configure<br />
make -j 4<br />
./miniruby -v: ruby 1.9.3dev (2011-09-23 revision 33323) [x86_64-linux]<br />
time ./miniruby fib.rb<br />
./miniruby fib.rb  36.05s user 0.01s system 99% cpu 36.073 total<br />
./miniruby fib.rb  35.92s user 0.04s system 99% cpu 35.978 total</p></blockquote>
<p>Everytime a Ruby fan says that &#8220;thou shalt not care about the runtime speed&#8221; makes me laugh so hard up to the point of bursting into tears. Seriously, I couldn&#8217;t imagine that MRI sucks that hard at recursion. I barely had the patience to even run this code. KRI washes part of the shame though while it scores closely to the Lua implementation. If you&#8217;re asking why I used the miniruby binary, the reason is that the ruby binary complained about not having rubygems.rb. I am bad at figuring out what&#8217;s missing from a Ruby stack. But it made the fib.rb work.</p>
<p><strong>Perl</strong></p>
<blockquote><p>perl -v: This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi<br />
time perl fib.pl<br />
perl fib.pl  125.60s user 0.17s system 99% cpu 2:05.92 total<br />
perl fib.pl  124.06s user 0.10s system 99% cpu 2:04.20 total</p>
<p>./Configure [accepted all defaults, specifically built without threading]<br />
make<br />
./perl -v: This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux<br />
./perl fib.pl  100.12s user 0.09s system 99% cpu 1:40.29 total<br />
./perl fib.pl  100.38s user 0.05s system 99% cpu 1:40.63 total</p></blockquote>
<p>At first I didn&#8217;t want to bother with Perl, but then I remembered the legions of Perl fans ranting about the PHP recursion. I know that this is an inflammatory statement, but next time, people, please keep up with the facts. I guess you aren&#8217;t that smug now.</p>
<p><strong>D</strong></p>
<blockquote><p>gdc -v: gcc version 4.3.4 (Ubuntu 1:1.046-4.3.4-3ubuntu1)<br />
gdc -o fib fib.c (same source as the C binary)<br />
time ./fib<br />
./fib  2.82s user 0.00s system 100% cpu 2.817 total<br />
./fib  2.82s user 0.00s system 100% cpu 2.814 total</p></blockquote>
<p>Predictable results from a language from the same family as C/C++. Slightly faster binary that the C version (although the same source code), but I guess most people won&#8217;t notice.</p>
<p><strong>Java</strong></p>
<blockquote><p>javac -version: gcj-4.4 (Ubuntu 4.4.3-1ubuntu4.1) 4.4.3<br />
java -version<br />
java version &#8220;1.6.0_20&#8243;<br />
OpenJDK Runtime Environment (IcedTea6 1.9.9) (6b20-1.9.9-0ubuntu1~10.04.2)<br />
OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)<br />
javac fib.java<br />
time java fib<br />
java fib  0.86s user 0.02s system 99% cpu 0.882 total<br />
java fib  0.86s user 0.02s system 100% cpu 0.872 total</p></blockquote>
<p>I admit that sometimes I use to tell this joke: knock! knock!; who&#8217;s there?; [very long pause]; Java. I guess that now is a good time to swallow my own words. Not only that Java puts the other JIT implementations to shame, the rest of the VMs to shame, it also obliterates the statically compiled C and D binaries at their own favorite game aka the runtime speed. My first reaction was: WTF, there&#8217;s got to be a mistake! Printing some junk to STDIO confirmed the same results between C and Java. <em>Newbie warning</em>: this is my first Java application. No, really! Don&#8217;t bash me for the lack of understanding of the usage of the static keyword. I don&#8217;t understand if it actually helps the runtime. I managed to put together the code by reading how to write a simple HelloWorldApp. Experienced Java chops may explain it though.</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/but-the-question-is-will-it-recur-part-1-fibonacci40.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Use the cache, Luke, Part 1: from memcached to Membase memcached buckets</title>
		<link>http://www.saltwaterc.eu/use-the-cache-luke-part-1-from-memcached-to-membase-memcached-buckets.html</link>
		<comments>http://www.saltwaterc.eu/use-the-cache-luke-part-1-from-memcached-to-membase-memcached-buckets.html#comments</comments>
		<pubDate>Wed, 21 Sep 2011 13:07:44 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1321</guid>
		<description><![CDATA[I start with a quote: Matt Ingenthron said internally at Membase Inc they view Memcached as a rabbit. It is fast, but it is pretty dumb and procreates quickly. Before you know it, it will be running wild all over your system. But this post isn&#8217;t about switching from a volatile cache to a persistent [...]]]></description>
				<content:encoded><![CDATA[<p>I start with a <a href="http://www.philwhln.com/de-volatile-your-memcached-upgrade-to-membase">quote</a>:</p>
<blockquote><p>Matt Ingenthron said internally at Membase Inc they view Memcached as a rabbit. It is fast, but it is pretty dumb and procreates quickly. Before you know it, it will be running wild all over your system.</p></blockquote>
<p>But this post isn&#8217;t about switching from a volatile cache to a persistent solution. It is about removing the dumb part from the memcached setup.</p>
<p>We started with memcached as this is the first step. The setup had its quirks since AWS EC2 doesn&#8217;t provide by default a fixed addressing method while the <a href="http://php.net/manual/en/book.memcached.php" title="memcached">memcached</a> client from PHP still has issues with the timeouts. Therefore, the fallback was the plain <a href="http://php.net/manual/en/book.memcache.php" title="memcache">memcache</a> client.</p>
<p>The fixed addressing issue was resolved by deploying Elastic IPs with <a href="http://alestic.com/2009/06/ec2-elastic-ip-internal" title="Using Elastic IP to Identify Internal Instances on Amazon EC2">a little trick for the internal network</a>, as explained by Eric Hammond. This might be unfeasible for large enough deployments, but it wasn&#8217;t our case. Amazon introduced <a href="http://aws.amazon.com/elasticache/" title="Amazon ElastiCache">ElastiCache</a> since then which removes this limitation, but having a bunch of t1.micros with reservation is still way much cheaper. Which makes me wonder why they won&#8217;t introduce machine addresses which internally resolve as internal address. They have this technology for a lot of their services, but it is simply unavailable for plain EC2 instances.</p>
<p>Back to the memcached issues. Having a <a href="http://www.couchbase.org/membase" title="Membase and Couchbase">Membase</a> cluster that provides a memcached bucket is a nice drop-in replacement, if you lower a little bit your memory allocation. Membase over memcached still has some overhead as its services tend to occupy more RAM. The great thing is that the cluster requires fewer machines with fixed addressing. We use a couple for high availability reasons, but this is not the rule. The rest have the EC2 provided dynamic addresses. If a machine happens to go down, another one can take up its place.</p>
<p>But there still is the client issue. memcached for PHP is dumb. memcache for PHP is even dumber. None of these can actually speak the Membase goodies. This is the part where <a href="http://www.couchbase.org/wiki/display/membase/Moxi" title="Moxi">Moxi</a> (Memcached Proxy) kicks in. For memcached buckets, Moxi can discover the newly added machines to the Membase cluster without doing any client configuration. Without any Moxi server configuration as the config is streamed to the servers via the machines that have the fixed addresses. With plain memcached, every time there was a change, we needed to deploy the application. The memcached cluster was basically nullified till it was refilled. Doesn&#8217;t happen with Moxi + Membase. Since there no &#8220;smart client&#8221; for PHP which includes the Moxi logic, we use client side Moxi in order to reduce the network round-trips. There still is a local communication over the loopback interface, but the latency is far smaller than doing server-side Moxi. Basically the memcache for PHP client connects to 127.0.0.1:11211 aka where Moxi lives, then the request hits the appropriate Membase server that holds our cached data. It also uses the binary protocol and SASL authentication which is unsupported by the memcache for PHP client.</p>
<p>The last of the goodies about the Membase cluster: it actually has an interface. I may not be an UI fan, I live most of my time in /bin/bash, but I am a stats junkie. The Membase web console can give you realtime info about how the cluster is doing. With plain memcached you&#8217;re left in the dust with wrapping up your own interface or calling stats over plain TCP. Which is so wrong at so many levels.</p>
<p>PS: v2.0 will be called Couchbase for political reasons. But currently the stable release is still called Membase.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/use-the-cache-luke-part-1-from-memcached-to-membase-memcached-buckets.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why sometimes I hate RFCs</title>
		<link>http://www.saltwaterc.eu/why-sometimes-i-hate-rfcs.html</link>
		<comments>http://www.saltwaterc.eu/why-sometimes-i-hate-rfcs.html#comments</comments>
		<pubDate>Wed, 21 Sep 2011 12:09:37 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Rant]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1319</guid>
		<description><![CDATA[Every time when there&#8217;s a debate about the format of something that floats around the Internets, people go to RFCs in order to figure out who&#8217;s right and who&#8217;s wrong. Which may be a great thing in theory. In practice, the rocket scientists that wrote those papers might squeeze a lot of confusion into a [...]]]></description>
				<content:encoded><![CDATA[<p>Every time when there&#8217;s a debate about the format of something that floats around the Internets, people go to RFCs in order to figure out who&#8217;s right and who&#8217;s wrong. Which may be a great thing  in theory. In practice, the rocket scientists that wrote those papers might squeeze a lot of confusion into a single page of text, as the <a href="http://gwan.com/">G-WAN</a> manual states.</p>
<p>Today&#8217;s case was a debate about the Expires header timestamps as defined by the HTTP/1.1 specs (RFC 2616). If you read the 14.21 section regarding the Expires header, you can see the following statement:</p>
<blockquote><p>The format is an absolute date and time as defined by HTTP-date in section 3.3.1; it MUST be in RFC 1123 date format:</p>
<p>Expires = &#8220;Expires&#8221; &#8220;:&#8221; HTTP-date</p></blockquote>
<p>I made a newb mistake in thinking that the RFC 1123 dates are legal Expires timestamps. Actually, by proof reading 3.3.1 of RFC 2616 you may deduce the following: the dates in use by the HTTP/1.1 protocol are not the dates into the RFC 1123 format, but the actual format is a subset of RFC 1123. The debate started around the GMT specification which in the HTTP/1.1 contexts is actually UTC, but it must be specified as GMT anyway. Even more, +0000 which is valid timezone specifier as defined by RFC 1123 is not valid for Expires timestamps. Although some caches accept +0000 as valid timezone specifier for the HTTP timestamps, some of them don&#8217;t.</p>
<p>It isn&#8217;t that the RFCs are broken per se, but the language they use can be very confusing sometimes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/why-sometimes-i-hate-rfcs.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to rotate the MySQL logs on Amazon RDS</title>
		<link>http://www.saltwaterc.eu/how-to-rotate-the-mysql-logs-on-amazon-rds.html</link>
		<comments>http://www.saltwaterc.eu/how-to-rotate-the-mysql-logs-on-amazon-rds.html#comments</comments>
		<pubDate>Thu, 15 Sep 2011 13:40:44 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1313</guid>
		<description><![CDATA[One day we enabled the MySQL&#8217;s slow_log feature as indicated by the RDS FAQ. That the (mostly) easy part. I say &#8220;mostly&#8221; because you need to add your own DB Parameter Group in order to enable the damn thing. Adding a group is easy. Editing it still requires you to use API calls (either via [...]]]></description>
				<content:encoded><![CDATA[<p>One day we enabled the MySQL&#8217;s slow_log feature as indicated by the <a href="http://aws.amazon.com/rds/faqs/#14" title="Q: What should I do if my queries seem to be running slow?">RDS FAQ</a>. That the (mostly) easy part. I say &#8220;mostly&#8221; because you need to add your own DB Parameter Group in order to enable the damn thing. Adding a group is easy. Editing it still requires you to use API calls (either via rds-api-tools or your own implementation).</p>
<p>Days started to fly, queries started to fill our log, we started to fix the slow points of the application. The thing that didn&#8217;t change is the fact that the mysql.slow_log table kept growing. Then I took some time to apply all my MySQL-fu regarding the cleanup of the mysql.slow_log table. Imagine my surprise when none of it worked. Since the master user of a RDS instance doesn&#8217;t have all the privileges, it wasn&#8217;t quite unexpected though.</p>
<p>For the first time, the AWS Premium Support was actually useful by sending one email that actually provides a solution. Imagine my surprise. The RDS team implemented a couple of stored procedures that can be used for rotating the slow log and the general log.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CALL</span> mysql<span style="color: #66cc66;">.</span>rds_rotate_slow_log;
<span style="color: #993333; font-weight: bold;">CALL</span> mysql<span style="color: #66cc66;">.</span>rds_rotate_general_log;</pre></td></tr></table></div>

<p>Basically they move the content to a *_backup table while the original is replaced by an empty table. The exact quote:</p>
<blockquote><p>When invoked, these procedures move the contents of the corresponding log to a backup table and clear the contents of the log. For example, invoking rds_rotate_slow_log moves the contents of the slow_log table to a new table called slow_log_backup and then clears the contents of the slow_log table. This is done by renaming tables, so no data is actually copied, making this a very light-weight, non-blocking procedure. Invoking the same procedure twice effectively purges the log from the database.</p></blockquote>
<p>They are present since March 22, 2010 but nobody took the time to document them, apparently. All I could find via online searches was utterly useless junk. I hope this saves some time for some poor chop into the same situation as I was.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/how-to-rotate-the-mysql-logs-on-amazon-rds.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>About dumping errors on the screen</title>
		<link>http://www.saltwaterc.eu/about-dumping-errors-on-the-screen.html</link>
		<comments>http://www.saltwaterc.eu/about-dumping-errors-on-the-screen.html#comments</comments>
		<pubDate>Tue, 13 Sep 2011 12:45:31 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1300</guid>
		<description><![CDATA[About a month ago I read an article about the possibility of using XSS vectors via the PHP error reporting. Nothing new under the Sun since the internals team love to dismiss valid concerns with the &#8220;bogus&#8221; status. Happened before, will happen again. The thing that sometimes pisses me off is stuff like this article [...]]]></description>
				<content:encoded><![CDATA[<p>About a month ago I read <a href="https://nealpoole.com/blog/2011/08/cross-site-scripting-via-error-reporting-notices-in-php/" title="Cross-Site Scripting via Error Reporting Notices in PHP">an article</a> about the possibility of using XSS vectors via the PHP error reporting. Nothing new under the Sun since the internals team love to dismiss valid concerns with the &#8220;bogus&#8221; status. Happened before, will happen again.</p>
<p>The thing that sometimes pisses me off is stuff like <a href="http://randomdrake.com/2011/08/18/no-php-errors-and-notices-do-not-need-to-be-encoded/" title="No, PHP Errors and Notices Do Not Need to be Encoded">this article</a> written by somebody who understands little about the web security. Writing the title with upper case letters doesn&#8217;t bring any value to the argument. So let&#8217;s dig a little bit better.</p>
<blockquote><p>a PHP application that has display_errors enabled should never be in production</p></blockquote>
<p>If you don&#8217;t see anything wrong about the quoted sentence, then you&#8217;re into the wrong field. Three of the most basic rules of security are:</p>
<ol>
<li>don&#8217;t rely onto the defaults</li>
<li>all input is evil</li>
<li>don&#8217;t rely onto a single layer of security</li>
</ol>
<p>The <em>application</em> doesn&#8217;t have display_errors turned on. The PHP <em>runtime</em> does. Sometimes this may be onto a shared host that doesn&#8217;t give a crap about <em>your application</em>. Or the sysadmin had a bad day and simply forgot something. Or, even better, somebody defined display_errors = true with php_admin, so the application can&#8217;t do anything about its own security context. &#8220;Should not | never&#8221; is an idiom that should not be used in any text which is security related. In the end, an attacker gain access through that critical piece of code that <em>should not</em> fail.</p>
<p>Which brings us to the next rule: the input validation. People should validate their input but this doesn&#8217;t enforce the fact that mistakes don&#8217;t happen. PHP makes it quite easy to both develop fast an application and shoot yourself in the foot at the same time. Properly developed code takes a lot of effort. If you didn&#8217;t developed code that treats notifications as fatal exceptions, then you don&#8217;t have a clue what I&#8217;m talking about. I am not talking about hello.php applications, but large projects built for scale. Couple of years ago I was working on a project built on top of the Kohana framework that used this specific setup in development mode. The consequence was the fact that much of the errors that usually creep into the production code were discovered during the development phase while my team learned how to properly initialize all the stuff that floats around the application. Few people have the patience to work this way. Some of the stuff can be automatically handled via proper abstractions, some of the stuff can&#8217;t or it&#8217;s simply not practical. If you failed the input validation class, there&#8217;s the next point.</p>
<p>Finally the third rule which says that&#8217;s bad practice to depend onto a single layer of security aka in this case simply turning off the display_errors. If PHP allows you to shoot yourself in the foot by having display_errors = true onto a production machine, doesn&#8217;t mean that it should make a harmless mistake (dumping the error reporting content to the screen) to be more severe (having an XSS in the application). If you regard XSS as harmless, you have much to learn.</p>
<p>The next quote that&#8217;s also goes into the clueless realm is:</p>
<blockquote><p>I don&#8217;t want to see anything to do with HTML if I&#8217;m not doing web-based programming with PHP (such as CLI).</p></blockquote>
<p>Since PHP exposes the PHP_SAPI constant which tells exactly what SAPI is in use, I guess that the runtime itself is smart enough to know exactly where the output goes: down a network pipe as HTML or into STDOUT / STDERR. A smart enough runtime also knows when to encode its output as appropriate and when not to. The argument holds water maybe just for the embed SAPI which is seldom used. I dare you to find proper docs about using the embed SAPI in your C / C++ application.</p>
<blockquote><p>I want my error messages to provide me with precise information. I do not want an error message to arbitrarily encode problematic code. If the user provided <s>test</s> then I want to see <s>test</s>. I do not want to see &lt;s&gt;test&lt;/s&gt; since that is not what was submitted and, possibly, not what the problem is.</p></blockquote>
<p>These sentences enter the realm of self parody. If the user entered &lt;s&gt;test&lt;/s&gt; that&#8217;s what you should see into an error output. That&#8217;s what you can find into an error log. Rendering the HTML markup is a browser feature therefore the output should play by the browser rules. Would you also like to see &lt;script&gt; tags as HTML instead of &#8220;what the user actually entered&#8221;?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/about-dumping-errors-on-the-screen.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snapshots are not backups</title>
		<link>http://www.saltwaterc.eu/snapshots-are-not-backups.html</link>
		<comments>http://www.saltwaterc.eu/snapshots-are-not-backups.html#comments</comments>
		<pubDate>Fri, 27 May 2011 08:07:44 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1268</guid>
		<description><![CDATA[Some people may slip into your head the idea that by doing snapshots, you&#8217;re free from the burden of doing proper backups. While this may sound good in theory, in practice there are a bunch of caveats. There are certain technologies that use the snapshot methodology at the core, but they make sure that your [...]]]></description>
				<content:encoded><![CDATA[<p>Some people may slip into your head the idea that by doing snapshots, you&#8217;re free from the burden of doing proper backups. While this may sound good in theory, in practice there are a bunch of caveats. There are certain technologies that use the snapshot methodology at the core, but they make sure that your data isn&#8217;t corrupted. Some may even provide access to the actual file revisions.</p>
<p>The data corruption is the specific topic that snapshots simply don&#8217;t care about, at least in Amazon&#8217;s way of doing things. This isn&#8217;t exactly Amazon&#8217;s fault for EC2. EBS actually stands for Elastic <strong>Block</strong> Storage. They provide you a block storage, you do whatever you want with it. For RDS they should do a better job though as it&#8217;s a <strong>managed</strong> service where you don&#8217;t have access to the actual instance. The issue is those &#8216;specialists&#8217; that put emphasis onto the &#8216;easy, cloud-ish way&#8217; of doing backups by using snapshots. If you&#8217;re new to the &#8216;cloud&#8217; stuff as I used to be, you may actually believe that crap. As I used to believe.</p>
<p>A couple of real life examples:</p>
<ul>
<li>An EBS-backed instance suffered some filesystem level corruption. Since EXT3 is not as smart as ZFS if we&#8217;re talking about silent data corruption, you may never know until it&#8217;s too late. Going back through revisions in order to find the last good piece of data is a pain. I could fix the filesystem corruption, I could retrieve the lost data, but I had to work quite a lot for that. Luck is an important skill, but I&#8217;d rather not put all my eggs into the luck basket.</li>
<li>An RDS instance ran out of space. There wasn&#8217;t a notification to tell me: &#8216;yo dumbass, ya ran out of space&#8217;. Statistically it wasn&#8217;t the case, but a huge data import proved me wrong. I increased the available storage. Problem solved. A day later, somebody dropped by accident a couple of tables. I had to restore them. How? Take the latest snapshot, spin up a new instance, dig through the data. The latest snapshot contained a couple of corrupted databases due to the space issue, one of them being the database I needed to restore. I had to take a bunch of time in order to repair the database before the restoration process. Fortunately nothing really bad happened. But it was a signal that the RDS snapshot methodology is broken by design.</li>
</ul>
<p>Lesson learned. The current way of doing backups puts the data, not the block storage, first. If you&#8217;re doing EBS snapshots as the sole method, you may need to rethink your strategy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/snapshots-are-not-backups.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boxing on EC2 – Windows Server instances</title>
		<link>http://www.saltwaterc.eu/boxing-on-ec2-windows-server-instances.html</link>
		<comments>http://www.saltwaterc.eu/boxing-on-ec2-windows-server-instances.html#comments</comments>
		<pubDate>Tue, 24 May 2011 13:50:33 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1256</guid>
		<description><![CDATA[> bashing mode on Apparently this ought to be a relative easy task, right? Wrong! I don&#8217;t know if Amazon is to blame. Or Microsoft. Or both. Really don&#8217;t care. The annoying thing is the large pile of fail that destroys the productivity for the most basic tasks. However, besides cookies, we, the sysadmins of [...]]]></description>
				<content:encoded><![CDATA[<p>> bashing mode on</p>
<p>Apparently this ought to be a relative easy task, right? Wrong! I don&#8217;t know if Amazon is to blame. Or Microsoft. Or both. Really don&#8217;t care. The annoying thing is the large pile of fail that destroys the productivity for the most basic tasks. However, besides cookies, we, the sysadmins of the <em>Dark Side</em>, also have solutions. We have to.</p>
<p>Some that know me better may think that I hate MS/Windows. I don&#8217;t, as long I don&#8217;t have to administer those machines. I do have a Windows 7 Pro box at home. While the Windows soft-RAID implementation blows for certain reasons, otherwise than this and some of the small quirks that every OS has, is a pretty dandy setup. Therefore no, I am not a pure Windows hater. Don&#8217;t get started with the wrong impression.</p>
<p>The first thing that&#8217;s really annoying is the long period that takes for the instance to be ready. In order to get the &#8216;Administrator&#8217; password it takes ages. Amazon says it takes between 15-30 minutes. Come on EC2, you take a AMI off the S3 and spin up a new instance, then setup a new password. How hard can it be? A Linux instances is ready almost instantly after the console says it&#8217;s running. Even more, after the password is available via the console or the API (sometimes one of these gets it faster) the RDP still takes a few minutes before being available. Since Amazon &#038; Microsoft don&#8217;t provide this for free, even more, we pay by the hour, STOP WASTING OUR TIME. Sincerely, the EC2 Windows Server users.</p>
<p>The second really annoying thing is the fact that Amazon recommends you to change the default password that they provide. While the recommendation is good, if you do this, you get locked out the instance. If you don&#8217;t have a second account with RDP access, you have one option: terminate the instance. The almost useless AWS Premium support probably will be able to do something about this. But if you&#8217;re in a hurry, going back to square one is probably the best option.</p>
<p>You have a <strong>workaround</strong> though that I discovered during my time boxing with EC2 and Windows Server: add the Administrator to the RDP allowed list, although the window says that &#8216;Administrator already has access&#8217;. If you change the password, the Administrator loses the RDP access, even though the password is valid. The welcome screen will tell you rubbish about using the wrong password, when clearly the input is good. I tried to reproduce this few times. Each time I got locked out. I even validated the new password by running something with runas. What? Wrong password? Listen a&#8217;holes, I asked you to change the f&#8217;ing password, not make me French fries. How hard is not to screw up such a basic task? Initially I though my Terminal Server Client is dumb, but the *nix guys don&#8217;t have any screw ups here. Using a Windows 7 client did the same.</p>
<p>If you want to create a new AMI off the existing instance, boy, more gotchas are waiting around the corner. Even if the Administrator password is successfully changed, the RDP access is preserved, the &#8216;Set Password&#8217; options of the &#8216;Ec2 Service Properties&#8217; application are unchecked, <a href="http://en.wikipedia.org/wiki/Sysprep">sysprep</a> manages to tank the instance and the new AMI. Administrator completely loses the access on <strong>both</strong> instances, the existing and new new one. Tried with the &#8216;Set a random password&#8217; option. Didn&#8217;t work as expected. Didn&#8217;t try the &#8216;SetPassword&#8217; feature after sysprep, but I had enough anyway. I read somewhere around the Interwebs that sysprep somewhat affects the Administrator user, but I didn&#8217;t get any relevant information. Searching for it is a mess.</p>
<p>My <strong>workaround</strong>: create a new user part of the Administrators group. Set a strong password for that user. Amazon sets a joke anyway. I wouldn&#8217;t call that strong. Disable the Administrator account:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">net user Administrator <span style="color: #000000; font-weight: bold;">/</span>active:no</pre></td></tr></table></div>

<p>Enjoy your newly created AMIs without surprises. Didn&#8217;t have any issues with other Administrators besides Administrator. Plus it is available as soon as the RDP service is available, unlike the &#8216;Amazon way&#8217; of keeping you waiting 15 to 30 minutes, for nothing.</p>
<p>The third really annoying thing is the fact that the AMIs are awfully outdated. Since there&#8217;s an official partnership between Amazon and Microsoft I would expect a higher level of support. I know, there&#8217;s Windows Update, but even after all those years, it still doesn&#8217;t manage to do it into a brain dead-free way. I know I&#8217;m biased as I&#8217;m used to Debian and friends, but the OS upgrade could be a little bit faster. OK, a lot more faster. Downloading and installing 54 updates that have around 200MiB takes around a hour and half, on a c1.medium instance which is the best specs you can get from a x86 instance. It takes 3 reboots. It takes 4 times to click the &#8216;Check for updates&#8217; link in order to actually be up to date in the end. I get that there are dependencies, but an OS that claims is &#8216;Datacenter&#8217; grade should handle this properly: download all your junk, deal with it later. Even more, I used c1.medium because m1.small is even slower for the Windows Update part. Even when the update manager claims that it&#8217;s only <strong>downloading</strong> updates, the CPU usage won&#8217;t go under 50%. What? A <strong>download</strong> that <strong>takes a lot of CPU time</strong>? WTF? The actual update doesn&#8217;t do it nicer or faster anyway.</p>
<p>A fellow sysadmin suggested vbscript + AutoIt. Now why the hell should I write a script to fix issues that should not exist in the first place? Don&#8217;t know why, but Windows Server under EC2 still feels like a second class citizen, despite the fact that you pay extra for the privilege of running Windows. Anyway, in the end I managed to bake my own AMI that&#8217;s ready for spinning up new instances for our HA setup. But the experience wasn&#8217;t even remotely close to the advertised level.</p>
<p>> bashing mode off</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/boxing-on-ec2-windows-server-instances.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>nginx + PHP-FPM for high loaded virtual private servers</title>
		<link>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-virtual-private-servers.html</link>
		<comments>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-virtual-private-servers.html#comments</comments>
		<pubDate>Tue, 17 May 2011 13:34:01 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web Server]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1257</guid>
		<description><![CDATA[The VPSes that use the OS level virtualization have some challenges that you won&#8217;t find in setups that use full OS virtualization / paravirtualization. Stuff like OpenVZ doesn&#8217;t provide you a method for tuning OS parameters which may impair certain setups such as the above mentioned into the article title. All the stuff mentioned in [...]]]></description>
				<content:encoded><![CDATA[<p>The VPSes that use the OS level virtualization have some challenges that you won&#8217;t find in setups that use full OS virtualization / paravirtualization. Stuff like OpenVZ doesn&#8217;t provide you a method for tuning OS parameters which may impair certain setups such as the above mentioned into the article title. All the stuff <a href="http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html">mentioned in my previous article</a> applies here as well, except the sysctl tuning part. It would be redundant to mention those tips again.</p>
<p>However, the thing that applies differently is the fact that the maximum connection backlog on a OpenVZ VPS is typically 128, therefore you can not increase the listen.backlog parameter of PHP-FPM over that value. The kernel denies you that. Even more, due to the low memory setups of a lot of VPSes out there in the wild, you may be forced to use a low value for pm.max_children which translates this into a shorter cycle for the process respawn. A process that is respawning, can&#8217;t handle incoming connections, therefore the heavy lifting is done by the kernel backlog. The concurrency may not increase linearly with the number of available processes into the FPM pool because of this consequence.</p>
<p>Since the backlog is kept by the kernel, it is common for all services, therefore it may affect nginx as well if it can not accept() a connection for some reason. Load balancing over UNIX sockets doesn&#8217;t increase the possible concurrency level. It simply adds useless complexity. Using TCP sockets may increase the reliability of the setup, at the cost of added latency and used up system resources, but it would fail in the end. Some measures need to be taken.</p>
<p>I gave a thought about using HAProxy as connections manager since HAProxy has a nice maxconn feature that would pass the connections to an upstream up to a defined number. But that would add another layer of complexity. It has its benefits. But it also means that&#8217;s another point of failure. Having more services to process the same request pipeline is clearly suboptimal if the services composing the request pipeline won&#8217;t add some clear value to the setup, for example the way a proxy cache does.</p>
<p>Then I thought about node.js, but implementing FastCGI on top of node seems a hackish solution at best. <a href="https://github.com/davidcoallier/node-php">One of the Orchestra guys did it</a>, but I wouldn&#8217;t go into production with a node.js HTTP server for static objects and FastCGI response serving, no matter how &#8220;cool&#8221; this may sound. Then the revelation hit me: Ryan Dahl, the author of node.js, wrote a nginx module that adds the maxconn feature to nginx: <a href="https://github.com/ry/nginx-ey-balancer">nginx-ey-balancer</a>. Hopefully, someday this would make it into upstream.</p>
<p>The module adds some boilerplate to the configuration since it requires a fastcgi_pass to an upstream unlike direct fastcgi_pass to an UDS path, but otherwise that this, it works as advertised. Although the module wasn&#8217;t actively maintained, or, at least this is how things look from outside, the v0.8.32 patch works even for nginx v1.0.2. Having nginx to act as connection manager instead of sending all the connections straight to the FPM upstream may have clear benefits from the concurrency point of view. It is recommended to set max_connections to the value of net.core.somaxconn. That guarantees the fact that no connection gets dropped because the FPM pool processes are respawning due to a short cycle policy.</p>
<p>By using this module, nginx could handle easily around 4000 concurrent connections for a 4 worker process setup, but increasing the workers number does not increase linearly the possible concurrency. Anyway, at that concurrency level, most probably the issues caused by the IPC between nginx and PHP-FPM would be your last concern. This setup simply removes an IPC limit which is ridiculously small most of the times.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-virtual-private-servers.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>nginx + PHP-FPM for high loaded websites</title>
		<link>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html</link>
		<comments>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html#comments</comments>
		<pubDate>Sun, 08 May 2011 19:00:35 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web Server]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1228</guid>
		<description><![CDATA[The title of the post is quite obvious. Apache2 + mod_php5 lost the so called &#8220;crown&#8221; for quite a while. The fist eye opener was a thing that got me pretty annoyed back in 2008. Dual-quad machine, 4 GiB of RAM, RAID 5 SAS @ 10k RPM &#8211; the server was looking pretty good, apparently. [...]]]></description>
				<content:encoded><![CDATA[<p>The title of the post is quite obvious. Apache2 + mod_php5 lost the so called &#8220;crown&#8221; for quite a while. The fist eye opener was a thing that got me pretty annoyed back in 2008. Dual-quad machine, 4 GiB of RAM, RAID 5 SAS @ 10k RPM &#8211; the server was looking pretty good, apparently. The only show stopper: Apache2 + mod_php5 that choked at 350 concurrent clients. What? No more free RAM? WTF? LAMP is not my cup of tea for obvious reasons. LEMP seems to be more appropriate while I ditched Apache from all the production servers.</p>
<p>Since then, I keep telling people that Apache2 + mod_php5 + prefork MPM is a memory hog, while most of the stuff comes from the brain-dead client connection management that Apache does. One process per connection is a model that ought to be killed. Probably the best bang for the buck is using nginx as front-end for serving the static objects and buffering the response from Apache in order to spoon-feed the slow clients. But here&#8217;s the kicker: for virtual hosting setups, Apache/prefork/PHP is pretty dull to configure safely aka isolate the virtual hosts. Packing more applications together over a production cluster is an obvious way for doing server consolidation.</p>
<p>There&#8217;s mod_fcgid/FastCGI &#8230; but nginx supports FastCGI as well. Therefore, cutting off the middle man was the obvious solution. By using this setup, you won&#8217;t lose &#8230; <a href="http://www.saltwaterc.eu/how-to-fix-nginx-and-phpfastcgi-path_info-issue.html">much</a>. PHP-FPM was an obvious solution as the default FastCGI manager that used to come as the sole solution from the PHP upstream is pretty dumb. Instead of having a dedicated PHP service for each virtual host, one can have a dedicated process pool for each virtual host. Believe me, this method is much easier to maintain.</p>
<p>While nginx comes pretty well tuned by default, except the <a href="http://wiki.nginx.org/HttpCoreModule#open_file_cache">open file cache</a> settings, for PHP-FPM you need to tune some essential settings. nginx has a predictable memory usage. I can say that most of the time the memory used by nginx is negligible compared to the memory used by the PHP subsystem. However, PHP-FPM has a predictable memory consumption if used properly. The process respawn feature ought to be used in order to keep the memory leaks under control. pm.max_requests is the option that you need to tune properly. One may use 10000 served request before respawning, but under very restricted memory requirements I even had to use 10 (very low memory VPS).</p>
<p>The pm.max_children option may be used to spawn an adaptive number of processes, based onto the server load, but IMHO that might overcommit the system resources into the worse case scenario. Having a fixed number of processes per pool is preferred. Usually I have a rough estimation of the memory consumption in order to keep all the runtime into the RAM. Thrashing the memory is not something you would want onto a loaded web server. For everything else, there&#8217;s Master &#8230; cough! <a href="http://munin-monitoring.org/">munin</a>.</p>
<p>The Inter-Process Communication is preferred over an UNIX Domain Socket. Unlike the TCP sockets, the UDS doesn&#8217;t have the TCP overload that the IPC has even for connections over the loopback interface. For small payloads, UDS might have a 30% performance boost due to lower latency than the TCP stack. Rememer: <a href="http://rescomp.stanford.edu/~cheshire/rants/Latency.html">you can&#8217;t beat the latency</a>. For larger payloads, the TCP latency has a lower impact, but it&#8217;s still there. Another nice thing about the UDS is the namespace. UDS uses the filesystem for defining a new listening socket. Under Linux, classic ACLs may be used for restricting what user can read / write to the UDS. BSD systems may be more permissive for this kind of stuff. The TCP sockets require a numerical port that can&#8217;t be used for something else while the management from an application that generates the configuration files is more difficult for this kind of settings. For UDS the socket name can be derived from the host name. As I said into a previous article, I don&#8217;t write the configuration files by hand. Having a decent way of keeping the IPC namespace is always a plus.</p>
<p>Another thing that you should take care of is the listen.backlog option of PHP-FPM. Using TCP sockets <a href="http://forum.nginx.org/read.php?3,97959,98054">seem to be more reliable</a> for PHP-FPM. However, that&#8217;s untrue if you dig enough. The IPC starts to fail around 500 concurrent connections, while for UDS this happens way faster aka for an 1 process pool, you can serve at most 129 concurrent clients. 129 is not a random number. PHP-FPM can keep 128 connections into its backlog while the 129th connection is the active process. The default listen.backlog for Linux is 128, although the PHP-FPM documentation may state -1 aka the maximum allowed value by the system. Taking a peek at the PHP-FPM source code reveals this (sapi/fpm/fpm/fpm_sockets.h):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/*
  On FreeBSD and OpenBSD, backlog negative values are truncated to SOMAXCONN
*/</span>
<span style="color: #339933;">#if (__FreeBSD__) || (__OpenBSD__)</span>
<span style="color: #339933;">#define FPM_BACKLOG_DEFAULT -1</span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;">#define FPM_BACKLOG_DEFAULT 128</span>
<span style="color: #339933;">#endif</span></pre></td></tr></table></div>

<p>The default configuration file that is distributed with the PHP-FPM source tree states that the value is 128 for Linux. The <a href="http://www.php.net/manual/en/install.fpm.configuration.php">php.net statement that it defaults to -1</a> gave me a lot of grief as I though the manual won&#8217;t give me rubbish instead of usable information. However, since PHP 5.3.5 you may debug the configuration by using the -t flag for the php-fpm binary. You can use it like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">php-fpm <span style="color: #660033;">-tt</span> <span style="color: #660033;">-y</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>php-fpm.conf</pre></td></tr></table></div>

<p>The doube t flag is not a mistake. If you&#8217;re using NOTICE as the debug level, the double t testing level prints the internal values of the PHP-FPM configuration:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">php-fpm <span style="color: #660033;">-tt</span> <span style="color: #660033;">-y</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>php-fpm<span style="color: #000000; font-weight: bold;">/</span>php-fpm.conf
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE: <span style="color: #7a0874; font-weight: bold;">&#91;</span>General<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pid = <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span>php-fpm.pid
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  daemonize = <span style="color: #c20cb9; font-weight: bold;">yes</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  error_log = <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>php-fpm.log
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  log_level = NOTICE
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  process_control_timeout = 0s
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  emergency_restart_interval = 0s
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  emergency_restart_threshold = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE: <span style="color: #7a0874; font-weight: bold;">&#91;</span>www<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  prefix = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  user = www-data
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  group = www-data
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  <span style="color: #c20cb9; font-weight: bold;">chroot</span> = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  chdir = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen = <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span>php-fpm.sock
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen.backlog = <span style="color: #660033;">-1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen.owner = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen.group = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen.mode = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  listen.allowed_clients = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm = static
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.max_children = <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.max_requests = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.start_servers = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.min_spare_servers = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.max_spare_servers = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  pm.status_path = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  ping.path = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  ping.response = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  catch_workers_output = no
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  request_terminate_timeout = 0s
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  request_slowlog_timeout = 0s
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  slowlog = undefined
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  rlimit_files = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:  rlimit_core = <span style="color: #000000;">0</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE:
<span style="color: #7a0874; font-weight: bold;">&#91;</span>08-May-<span style="color: #000000;">2011</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">53</span>:<span style="color: #000000;">26</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> NOTICE: configuration <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>php-fpm<span style="color: #000000; font-weight: bold;">/</span>php-fpm.conf <span style="color: #7a0874; font-weight: bold;">test</span> is successful</pre></td></tr></table></div>

<p>This stuff is not documented properly. I discovered it by having a nice afternoon at work, reading the PHP-FPM sources. That could save me some hours of debugging the internal state of PHP-FPM by other means. Maybe, for the 1st time, saying &#8220;undocumented feature&#8221; doesn&#8217;t sound like marketing crap implying &#8220;undiscovered bug&#8221;.</p>
<p>You may use listen.backlog = -1 for the system to decide, or you may use your own limit. -1 is a valid value as the <a href="http://linux.die.net/man/3/listen">listen(3) man page says</a>. I am planning for <a href="http://bugs.php.net/search.php?cmd=display&#038;search_for=fpm&#038;php_os=&#038;php_os_not=&#038;author_email=&#038;bug_type=&#038;boolean=0&#038;bug_age=0&#038;bug_updated=0&#038;order_by=&#038;direction=DESC&#038;limit=30&#038;phpver=&#038;cve_id=&#038;cve_id_not=&#038;patch=&#038;assign=&#038;package_name[]=FPM+related">opening a new issue</a> as -1 is a more appropriate default for Linux as well. However, please keep in mind that a high backlog value may be truncated by the Linux kernel. For example, under Ubuntu Server this limit is &#8230; 128. The same manual page for listen(3) states that the maximum value for the backlog option is the SOMAXCONN value. While reading the Linux kernel sources is not exactly toilet reading, I could find the exact implementation of the listen syscall (net/socket.c):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/*
 *      Perform a listen. Basically, we allow the protocol to do anything
 *      necessary for a listen, and if that works, we mark the socket as
 *      ready for listening.
 */</span>
&nbsp;
SYSCALL_DEFINE2<span style="color: #009900;">&#40;</span>listen<span style="color: #339933;">,</span> <span style="color: #993333;">int</span><span style="color: #339933;">,</span> fd<span style="color: #339933;">,</span> <span style="color: #993333;">int</span><span style="color: #339933;">,</span> backlog<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">struct</span> socket <span style="color: #339933;">*</span>sock<span style="color: #339933;">;</span>
        <span style="color: #993333;">int</span> err<span style="color: #339933;">,</span> fput_needed<span style="color: #339933;">;</span>
        <span style="color: #993333;">int</span> somaxconn<span style="color: #339933;">;</span>
&nbsp;
        sock <span style="color: #339933;">=</span> sockfd_lookup_light<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>err<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>fput_needed<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>sock<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                somaxconn <span style="color: #339933;">=</span> sock_net<span style="color: #009900;">&#40;</span>sock<span style="color: #339933;">-&gt;</span>sk<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>core.<span style="color: #202020;">sysctl_somaxconn</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span><span style="color: #009900;">&#41;</span>backlog <span style="color: #339933;">&gt;</span> somaxconn<span style="color: #009900;">&#41;</span>
                        backlog <span style="color: #339933;">=</span> somaxconn<span style="color: #339933;">;</span>
&nbsp;
                err <span style="color: #339933;">=</span> security_socket_listen<span style="color: #009900;">&#40;</span>sock<span style="color: #339933;">,</span> backlog<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>err<span style="color: #009900;">&#41;</span>
                        err <span style="color: #339933;">=</span> sock<span style="color: #339933;">-&gt;</span>ops<span style="color: #339933;">-&gt;</span>listen<span style="color: #009900;">&#40;</span>sock<span style="color: #339933;">,</span> backlog<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                fput_light<span style="color: #009900;">&#40;</span>sock<span style="color: #339933;">-&gt;</span>file<span style="color: #339933;">,</span> fput_needed<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> err<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>In plain English: the backlog value can not be higher than net.core.somaxconn. In order to be able to queue more idle connections into the kernel backlog, you ought to inrease the SOMAXCONN value:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">root@localhost~# </span>sysctl net.core.somaxconn=<span style="color: #000000;">1024</span></pre></td></tr></table></div>

<p>The sysctl utility however modifies this value till the system is rebooted. In order to make it persistent, you have to define it as a new file into /etc/sysctl.d/. Or at least, using sysctl.d is recommended as it keeps the configuration to be more structured. I used /etc/sysctl.d/10-unix.conf:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">net.core.somaxconn=<span style="color: #000000;">1024</span></pre></td></tr></table></div>

<p>for having 1024 queued connections per listening UDS + the number of active connections that equals the size of the process pool. Remember that you need to restart the PHP-FPM daemon for the new backlog setting to be enabled. You may increase the limit as the usage model seems fit. Since nginx doesn&#8217;t queue any FastCGI connections, you need to be very careful about this setting. All the requests go straight to the kernel backlog. If there&#8217;s no more room for new connections, a 502 response is returned to the client. I can safely assume that you would like to avoid this.</p>
<p>Another thing that you should take care of for the number of idle connections to the PHP upstream is the fact that nginx opens a file descriptor for each UDS connection. If you increase too much the SOMAXCONN limit without increasing the number of allowed file descriptors per process, you will run into 502 errors as well. By default, a process may open up to 1024 file descriptors. Usually I increase this limit by adding a ulimit -n $fd_value to the init script of a certain service instead of increasing this limit as system wide.</p>
<p>You may want to <a href="http://wiki.nginx.org/HttpFcgiModule#fastcgi_buffer_size">buffer the FastCGI response in nginx</a> as well. Buffering the response doesn&#8217;t tie the upstream PHP process for longer than needed. As nginx properly does the spoon-feeding to slow clients, the system is free to process more requests from the queue. fastcgi_buffer_size and fastcgi_buffers are the couple of options that you need to tune in order to fit your application usage mode.</p>
<p><strong>Update (Aug 24, 2011):</strong></p>
<p>Increasing the SO_SNDBUF also helps. Writes to the socket won&#8217;t block as it would be the kernel&#8217;s job to stream the data to the clients. For a server with enough memory, nginx could be free to do something else. The <a href="http://linux.die.net/man/7/socket">socket(7)</a> man page comes to the rescue in order to demystify the SO_SNDBUF concept. Basically net.core.wmem_max is the one to blame when writes to the socket are blocking. By default the net.core.wmem_max is 128k which is very small for a busy server. If the server has a fat network pipe available, then you can get some more hints here: <a href="http://fasterdata.es.net/fasterdata/host-tuning/linux/">Linux Tuning</a>. It may not be the case for most EC2 scenarios where the networking is shared. Therefore smaller buffers will do just fine. But it may be the case if you&#8217;re playing like me with toys that have dual 1G network interfaces.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>How to fix nginx and PHP/FastCGI PATH_INFO issue</title>
		<link>http://www.saltwaterc.eu/how-to-fix-nginx-and-phpfastcgi-path_info-issue.html</link>
		<comments>http://www.saltwaterc.eu/how-to-fix-nginx-and-phpfastcgi-path_info-issue.html#comments</comments>
		<pubDate>Wed, 04 May 2011 17:08:43 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web Server]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1210</guid>
		<description><![CDATA[You may be disappointed by this statement: you don&#8217;t. nginx has something in it that&#8217;s broken by design, while the author didn&#8217;t bother at least to reply my email, explaining the situation. I can demonstrate this by using some comparisons. Apache (+mod_php5) knows the difference between a script and a PATH_INFO input request that ends [...]]]></description>
				<content:encoded><![CDATA[<p>You may be disappointed by this statement: <strong>you don&#8217;t.</strong> nginx has something in it that&#8217;s broken by design, while <a title="Igor Sysoev" href="http://sysoev.ru/">the author</a> didn&#8217;t bother at least to reply my email, explaining the situation. I can demonstrate this by using some comparisons.</p>
<p>Apache (+mod_php5) knows the difference between a script and a PATH_INFO input request that ends in .php. It would be ridiculous not to do so since the PHP runtime is part of the webserver itself. Didn&#8217;t bother to try various Apache + mod_fcgid configurations since most of the time Apache simply wastes my own time. lighttpd binds the FastCGI proxying to the <strong>file extension</strong>. This is the part where nginx fails: it tries to use a one-size-fits-all configuration logic that actually doesn&#8217;t fits all the usage modes. The FastCGI pass is done into a <strong>location</strong> (not file / file extension!) directive that doesn&#8217;t tell anything about the nature of the input. Let&#8217;s take a look at this example:</p>
<p>/directory.php/file.php/pathinfo.php</p>
<p>Except nginx, both Apache and lighttpd won&#8217;t create a mess out of a path like this. A location directive is a little big vague and no amount of regex will ever fix this. Of course, you can fix it for every single damn virtual host, but then again, can you spell <em>boilerplate</em>? Having different configurations for every virtual host, when clearly for other web servers this isn&#8217;t a bundled &#8220;feature&#8221;, is not fun from the system administration point of view. Usually I generate the virtual host configuration from a bash script I wrote myself. I have configuration templates for all of the applications I administer, thus is all about flags and options, unlike manually writing configuration files. Working around nginx&#8217;s inabilities to tell which stuff is which could only mean that I have to write a whole bunch of configuration boilerplate for each type of application. Doesn&#8217;t sound like one-size-fits-all anymore. Is that fun? Let me rephrase that: that&#8217;s not fun. In case AWS disappears into a black hole, I can recreate everything from scratch in a matter of minutes onto a complete new hosting service while changing <a href="http://www.cotendo.com/">Cotendo</a> origins is a child&#8217;s play.</p>
<p><a title="Setting up PHP-FastCGI and nginx? Don’t trust the tutorials: check your configuration!" href="https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/">Here</a> are a bunch of proposed solutions for something that can turn out into a remote exploit. I&#8217;ve being using for quite a while the same solution as provided by one of the people commenting the article:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span>f <span style="color: #000088;">$request_filename</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    fastcgi_pass php_upstream<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Usually because this is more readable than try_files. I usually tend to understand code blocks better.</p>
<p>Of course, a proper PHP script won&#8217;t save any uploaded junk to a public accessible location, but what sysadmin trust his coders anyway? I usually don&#8217;t. That doesn&#8217;t mean that they don&#8217;t do a good job, but mistakes happen. I can&#8217;t made every living thing to be as paranoid about security as I am. This exploitable situation happens when people validate their upload via the $_FILES array. I have news flash for you: the MIME type defined by the $_FILES array is defined by the browser. The browser does a lousy job at providing a proper MIME. It matches a specific MIME based onto the file extension. PHP file with JPEG extension, anyone? <a title="File Information" href="http://php.net/manual/en/book.fileinfo.php">fileinfo</a> would be the proper alternative. PHP should deal with this junk by design, but that&#8217;s a whole other joke about the <em>design of PHP</em>.</p>
<p>Getting back to PATH_INFO. The juicy part is that basically you can extract the PATH_INFO from an input path by using <a title="fastcgi_split_path_info" href="http://wiki.nginx.org/HttpFcgiModule#fastcgi_split_path_info">fastcgi_split_path_info</a>, but that directive uses &#8230; regex. Which brings us to the above statement: no amount of regex will ever fix this crap. Let&#8217;s take a look at $request_filename by throwing a custom debug logging configuration that places some stuff into the access_log. Guess what, the $request_filename for the above example is &#8230; /directory.php/file.php/pathinfo.php while it&#8217;s pretty clear that the <em>actual</em> request filename is /directory.php/file.php. Which is the other broken-by-design thing that nginx features. Q: What damn server side variable would ever lie to your face that a $request_<strong>filename</strong> is not exactly a file? A: duh!</p>
<p>This doesn&#8217;t mean that you should throw nginx and PHP-FPM away and go back crying to Apache. Just simply avoid the PATH_INFO junk. However, even by using my proposed configuration directive aka check if $request_filename is actually a <strong>file</strong> before doing the FastCGI pass, you can still use fastcgi_split_path_info for a limited amount of work. fastcgi_split_path_info can replace the need for doing URL rewrites by simply using:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!-</span>e <span style="color: #000088;">$request_filename</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    rewrite ^ <span style="color: #339933;">/</span>index<span style="color: #339933;">.</span>php last<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This works for a lot of stull like WordPress, Drupal, or Zend Framework. It works for certain stuff, except the stuff containing .php somewhere. I might want to use /%postname%.php as permalink structure in WordPress. Guess what &#8230; with a <em>properly configured</em> nginx (cough!) + the above rewrite rule replacement simply can&#8217;t. You have to go back to:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!-</span>e <span style="color: #000088;">$request_filename</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    rewrite ^<span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span><span style="color: #009900;">&#41;</span>$ <span style="color: #339933;">/</span>index<span style="color: #339933;">.</span>php?q<span style="color: #339933;">=</span>$<span style="color:#800080;">1</span> last<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Which is exactly what I did. For all my apps. Happens to be more deterministic by nature, while I tend to sleep better when I can predict the request pipeline, no matter which is the input junk.</p>
<p>I guess I could give <a href="http://www.hiawatha-webserver.org/">Hiawatha</a> a run which seems to be lightweight enough to support PHP with a threaded architecture. PHP is process based, doing blocking I/O by design, therefore the web server is rarely the actual bottleneck.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/how-to-fix-nginx-and-phpfastcgi-path_info-issue.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Password Hashing in PHP with bcrypt</title>
		<link>http://www.saltwaterc.eu/password-hashing-in-php-with-bcrypt.html</link>
		<comments>http://www.saltwaterc.eu/password-hashing-in-php-with-bcrypt.html#comments</comments>
		<pubDate>Tue, 19 Apr 2011 10:00:54 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1203</guid>
		<description><![CDATA[I&#8217;ve being doing it wrong for years. Till 5.3, PHP didn&#8217;t help very much either with it&#8217;s broken bcrypt implementation. So here goes the vicious circle. However, there&#8217;s no excuse for getting smarter as the tools I&#8217;m using get smarter. Here&#8217;s a couple of reasons. For quite a while I&#8217;ve being using my own implementation [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve being doing it wrong for years. Till 5.3, PHP didn&#8217;t help very much either with it&#8217;s broken bcrypt implementation. So here goes the vicious circle. However, there&#8217;s no excuse for getting smarter as the tools I&#8217;m using get smarter. Here&#8217;s a <a title="How To Safely Store A Password" href="http://codahale.com/how-to-safely-store-a-password/">couple</a> of <a title="Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes" href="http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html">reasons</a>.</p>
<p>For quite a while I&#8217;ve being using my own implementation of <a title="phpass" href="http://www.openwall.com/phpass/">phpass</a>. There are a couple of reasons for doing my own homework instead of using the already existing solution:</p>
<ul>
<li>The <a title="Suhosin Hardening Patch" href="http://www.hardened-php.net/hardening_patch.14.html">Suhosin patch</a> doesn&#8217;t play nice with PHP extensions available as binary blob only as it breaks the ABI. Therefore a consistent bcrypt implementation lacked before PHP 5.3 since at most I could use just the <a title="Suhosin Extension" href="http://www.hardened-php.net/suhosin/index.html">Suhosin extension</a>.</li>
<li>The random seed generator was quite broken across different platforms. Unices have /dev/random and /dev/urandom. Even more, these devices are not consistently implemented across them. If you aren&#8217;t inspired (/dev/random under Linux is a blocking device), then your random seed generator is screwed till the system gains enough entropy. Under Windows, the used PRNG was something really crappy, if you could use the system implementation, otherwise people used to hack something together. phpass is still a mess, while being backwards compatible with a lot of PHP implementations.</li>
</ul>
<p>openssl_random_pseudo_bytes() is still slow under Windows, although since <a title="PHP 5 Changelog" href="http://php.net/ChangeLog-5.php#5.3.4">PHP 5.3.4 it fixes the blocking behavior</a>. But it&#8217;s still better than the previous mess. My method for generating the bcrypt salts is still about 5.8X faster than the method used by phpass under Ubuntu.</p>
<p>I am not saying that my implementation is <em>the implementation</em>, but I got the feeling that for once I am doing it better that I used to do it before, or doing it better than phpass does.</p>
<p><a title="PasswordHash2" href="https://github.com/saltwaterc/passwordhash2">Grab/fork it from GitHub</a> if you&#8217;re curious.</p>
<p><strong>Update:</strong> I also implemented Ulrich Drepper&#8217;s SHA2-based crypt() scheme, but the v0.2 is incompatible with v0.1 due to the fact that it returns the hashes as base64 string. This is a side effect of using 16 <strong>bytes</strong> of random seed for the SHA2 salts. The PHP manual simply states 16 chars, but that&#8217;s a little bit vague. Except chr(0) and chr(36), any other single byte char is valid for the random seed. bcrypt takes a more cleaner approach for the 16 bytes random seed by using a 22 chars base64-like string that encodes those 16 bytes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/password-hashing-in-php-with-bcrypt.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why I don’t benchmark HTTP static object serving</title>
		<link>http://www.saltwaterc.eu/why-i-dont-benchmark-http-static-object-serving.html</link>
		<comments>http://www.saltwaterc.eu/why-i-dont-benchmark-http-static-object-serving.html#comments</comments>
		<pubDate>Fri, 15 Apr 2011 11:44:47 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Systems Administration]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web Server]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1193</guid>
		<description><![CDATA[﻿Usually I tend to pick a solution based on its features and architecture. That doesn&#8217;t mean that I&#8217;d pick a dog slow application that pushes the network traffic. But here&#8217;s the kicker: in a distributed system, you play by the lowest common denominator aka the real bottleneck. One thing I learned from experience is that [...]]]></description>
				<content:encoded><![CDATA[<p>﻿Usually I tend to pick a solution based on its features and architecture. That doesn&#8217;t mean that I&#8217;d pick a dog slow application that pushes the network traffic. But here&#8217;s the kicker: in a distributed system, you play by the lowest common denominator aka the real bottleneck. One thing I learned from experience is that given the appropriate software, the hardware usually isn&#8217;t the limit. On the other hand, the network pipe is.</p>
<p>Few months ago I had an interesting task: place something in front of Amazon S3 in order to cut down the file distributions costs. While S3 is great for storage, for the actual distribution you&#8217;d see that the traffic counter is spinning fast and the USD counter even faster. Certain web hosting providers have good deals for dedicated servers, therefore something like the S3 traffic could be turned on into a fixed cost, given by the amount of machines and the bandwidth pool specified into the contract.</p>
<p>This is the part where the technology kicks in. As I said earlier, the hardware rarely is the limit. Remember <a title="C10K" href="http://www.kegel.com/c10k.html">the C10K problem</a>? Some servers deal with with this stuff better than others. This means that I wouldn&#8217;t pick Apache, or any other web server that deals with the connections by the same model. The network has a high latency compared to the rest of the hardware, even the local disk. People should stop thinking in blocking mode.</p>
<p>For the above task, nginx did the load balancing, fail-over, and URL protection part really well. squid did the other part aka the proxy cache job. Now you may wonder why the good old squid since I think nginx doesn&#8217;t need introduction.</p>
<p>I tried Varnish as the proxy cache, but the people behind it thought <a href="http://www.mail-archive.com/varnish-misc@varnish-cache.org/msg01037.html">it was funny not to have an unbuffered transfer mode</a>. This might work well sometime, with the &#8220;most of the web traffic&#8221;, as they say, but when you try to push a large file over HTTP this point is somewhat the real world usage for our case:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">HAI, I ARE TEH CLIENT. PLZ GIVE ME <span style="color: #000000; font-weight: bold;">/</span>large-file.zip
LOL, OK, BUT WAI TILL HAZ IT IN ME CACHE</pre></td></tr></table></div>

<p>I considered trying Varnish for all the hype surrounding it. I kept myself for going straight to squid because of so called StackOverflow type of specialist that doesn&#8217;t recommend it since Varnish is &#8220;way faster&#8221;. Got a little news flash for you brother: it doesn&#8217;t matter. The fact that a client needs to wait till the proxy cache buffers all the stuff from the origin server (S3) won&#8217;t count as &#8220;speed&#8221;. It may work great for CDN-like type of traffic where certain patterns emerge, but not here where we have to deal even with hundred of megabytes for a single object.</p>
<p>The next bus stop was Apache Traffic Server. While it looks good on paper, it required rocket scientists to configure a simple usage mode. While I like the <a href="http://trafficserver.apache.org/docs/v2/admin/http.htm">pictures with the baseball bat explaining the concept of a cache hit or miss</a>, it still lacks proper, understandable documentation for a new comer in order to get something up and running in a timely manner. I am not a sysadmin newb, but some things are harder to pick up from scratch than others. Work against a short deadline in order to get my point. My squid configuration file has exactly 18 lines. All human readable and easy to understand. The default Traffic Server installation had as much as configuration files. How am I supposed to figure out this mess?</p>
<p>Things I also considered: nginx &#8211; it is dreadful as proxy cache due to the lack of HTTP 1.1 for the proxy backend, therefore no If-Modify-Since or If-None-Match support for invalidating a cached object. Amazon S3 sends both Last-Modified and ETag. A half-baked product from this side of the story. We have HTTP 1.1 and the 304 status. <a href="http://sysoev.ru/">Igor</a>, are you there?</p>
<p>lighttpd &#8211; also annoyed me with some proxy cache limitations that didn&#8217;t play nice. Don&#8217;t get me wrong, excluding some security record, lighttpd is actually a great web server, performance wise. It pushed our file distribution traffic for almost 4 years from a couple of FreeBSD machines. We changed the hardware every 2 years though. I never saw those machines going over 200MiB of RAM even at &#8220;rush hour&#8221;, while the CPU used to sip power from the socket instead of going like crazy. I didn&#8217;t even install a monitoring system since there was nothing to alert. The hardware load balancer did the fail-over stuff back then. Believe me or not, I actually felt sorry for turning off a web server with almost 600 days of uptime, after moving to EC2. But I still hate to use lighttpd as proxy cache.</p>
<p>I thought about Apache + mod_proxy for 3.14 seconds, but I moved on. Even with <a title="Event MPM" href="http://httpd.apache.org/docs/2.2/mod/event.html">Event MPM</a> it falls behind the competition. While I have a great deal of respect for the Apache Foundation, I still don&#8217;t get how they manage to screw things up with the Apache HTTP Server. I mean, come on, I expect more from the so called market share leader.</p>
<p>I gave a thought to node.js which I think is a terrific piece of technology, if you can ignore some of the <a href="http://sayyouresorryforwhatyouvedone.blogspot.com/2011/04/douglas-crockford-for-javascript-good.html">silliness of JavaScript</a>. But I wanted a piece of software that&#8217;s maintain towards my need by a bunch of people that do this stuff for quite a while, not a home brewed proxy cache.</p>
<p>Which brought me down to squid. A lot of &#8220;expert opinions&#8221; kept me from picking it in the first place, sparing me the pain of installing, configuring, and testing a bunch of alternatives, even though I&#8217;ve being using it as forward proxy for years. It does everything that it needs to do for a proxy cache with more or less configuration. It is an asynchronous server. It isn&#8217;t as slow as advertised, even though it&#8217;s written into that &#8220;slow, modern language&#8221; called C++. The configuration is straight forward. In fact, since the cluster is in production, it didn&#8217;t went even near the hardware limits.</p>
<p>Something bad happened into the first couple of days due to lack of proper production traffic that didn&#8217;t match the theoretical testing: clients who send invalidation headers along with ranged requests, which squid doesn&#8217;t handle very well. This sent the whole cluster into a vicious circle. The solution was simple at the nginx layer: strip down all the headers, pass just the relevant stuff. nginx does the header management way much better than squid that tries to implement some sort of &#8220;standards compliant&#8221; stuff that makes it very stiff. But even then, even though the cluster was working like crazy, the CPU didn&#8217;t even come close to 20% while the RAM was mostly doing nothing. The network pipe on the other hand, was working at full capacity, therefore some high I/O waits started to build up. Same goes for nginx.</p>
<p>Therefore no, I won&#8217;t do the same mistake twice. I stopped doing benchmarks. I don&#8217;t care about faster, but just about fast enough and well enough engineered. Business wise, we don&#8217;t pay less for using less CPU or RAM. Or even for drawing less power from the socket. Even Amazon doesn&#8217;t do that with it&#8217;s pay-as-you-go-only-what-you-use model. We have a bunch of dedicated hardware that we can use at 1% or at 100% load. There&#8217;s a bandwidth pool that&#8217;s the actual interest in saving money. I encourage fellow sysadmins do the same: stop caring about irrelevant stuff like: this web server is 10% faster. Even <strong>if it&#8217;s 200% faster</strong> (made up number), if the network pipe is the limit, it doesn&#8217;t matter overall. That stuff <strong>matters into the application server market</strong> where you have to shuffle data around, instead of taking a bunch of bytes of the disk and push them over the network interface. Today&#8217;s hardware is stupid fast. When 10 Gbps is going to be a standard, then yes, some of the great debates may actually have some ground. Currently they don&#8217;t. People like to argue about anything. Even toiler paper positioning. I fail to see where&#8217;s the productive part.</p>
<p>Don&#8217;t get me wrong. I hate bloat-ware. I love the raw speed. I love the machines that return a fast answer. But sometimes good enough is enough. Don&#8217;t keep &#8220;the religion&#8221; standing in your way of properly doing your job. People should focus on finding solutions instead of <a href="http://nbonvin.wordpress.com/2011/03/14/apache-vs-nginx-vs-varnish-vs-gwan/">fighting religious wars with colorful graphs</a>.</p>
<p>For example, serving 55.000 requests per second for a 2 KiB object over the loopback interface requires higher bandwidth than a 1 Gbps network pipe can provide. 2 KiB is a very small file. Most JavaScript libs, and style-sheets go over that limit, therefore the bandwidth limit is easier to hit. I don&#8217;t have to mention the images or plain large objects. Yes, some tests may be great for the ego of a developer behind a certain product. But most of the time some sort of apple to oranges comparison is involved. Certain features cost CPU time. But most of the time, the lack of specific features costs us time. The time is money. The CPU time, in this case, isn&#8217;t.</p>
<p>PS: we&#8217;re caching hundreds of GiB. We&#8217;re serving at least one TiB of data per day. Not bad for an old, slow, proxy cache running on a couple of machines that nobody wants to use since we have this new cool technology. Do we?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/why-i-dont-benchmark-http-static-object-serving.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>XVE – XVE Various Embed – preview release</title>
		<link>http://www.saltwaterc.eu/xve-xve-various-embed-preview-release.html</link>
		<comments>http://www.saltwaterc.eu/xve-xve-various-embed-preview-release.html#comments</comments>
		<pubDate>Sun, 03 Apr 2011 17:51:07 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1185</guid>
		<description><![CDATA[I kept saying that a new version is coming. Some actually thought about vaporware claims about this plug-in. Wonder no more. The first public BETA is here. The name is changed from XHTML Video Embed to XVE (XVE Various Embed). You can simply call it XVE. Besides the name, the plug-in by itself is also [...]]]></description>
				<content:encoded><![CDATA[<p>I kept saying that a new version is coming. Some actually thought about vaporware claims about this plug-in. Wonder no more. The first public BETA is here. The name is changed from XHTML Video Embed to XVE (XVE Various Embed). You can simply call it XVE. Besides the name, the plug-in by itself is also changed. Some of the old features may work, most of them won&#8217;t. While I still left some core speed hacks for the next version, it can be used in production. Anyway, a caching plug-in for WordPress is always a good recommendation. Also, the plug-in will survive the same as the previous version did, over the next WordPress versions. The tag syntax is there for a reason.</p>
<p>The stuff that works:</p>
<ul>
<li>the plug-in core, end-to-end. This means that I can add / remove functionality without wonder how to fix stuff under the hood. I made my life easier for me or for any hacker that wants to add functionality. XHTML Video Embed uses complicated boilerplate in order to add a new service or edit some core functionality. XVE doesn&#8217;t. This means that everything, even the user interfaces, scale by iterating over configuration array. I can add a new service or media player in minutes. Basically I just need to figure out its syntax. I don&#8217;t have to figure out the plug-in&#8217;s syntax. I know, I shouldn&#8217;t release the old plug-in as such in the first place, but I didn&#8217;t have the current experience while it grew from 50 to over 1000 lines of code. XVE was designed from scratch.</li>
<li>All the currently supported media players for the flv/mp4 content. It supports: <a title="Flowplayer" href="http://flowplayer.org/">Flowplayer</a>, the old <a title="FLV Player" href="http://flv-player.net/">FLV Player</a>, and <a title="JW Player" href="http://www.longtailvideo.com/players/jw-flv-player/">JW Player</a>. I resisted the temptation to use a switch(), therefore I can add any flv player that supports a couple of input options: path to flv/mp4, and optionally a path to a splash image. This feature was requested for quite a while. Now it works seamlessly for all the supported players.</li>
<li>The permissions are more granular. The options are more granular as well. Anything can be controlled from the tag, besides the object size.</li>
<li>new-style embedding tags. This means: video for all the supported video services such as YouTube, Google Video, or College Humor, etc, audio for Trilulilu, and 220, image for Trilulilu. While the legacy support (youtube, google-video, collegehumor, etc. tags) is implemented, it is disabled by default. You can enable it, but &#8230;</li>
</ul>
<p>The stuff that doesn&#8217;t work, yet:</p>
<ul>
<li>&#8230; but the admin UI doesn&#8217;t do anything, yet. Therefore you can&#8217;t enable the legacy support. Since my jQuery FU is not strong, I still have to learn how to do edit in place and other stuff like this that allows you to use your custom settings. Please remember that usually I write backend code. Not so much an user interface guy.</li>
</ul>
<p>The stuff that&#8217;s changed:</p>
<ul>
<li>the attributes w and h won&#8217;t work. The tags support just a single attribute: attrib. attrib=&#8221;width=680&amp;height=440&#8243; &#8211; longer, but more powerful aka for flv I also have img=http://example.com/path/to/splash/image.png, and player=jwplayer if you want to override the default media player (Flowplayer as of this version). The value of attrib is sent to PHP&#8217;s <a title="parse_str()" href="http://php.net/manual/en/function.parse-str.php">parse_str()</a>, therefore you need to be careful about this.</li>
<li>read the CHANGELOG.TXT for all the other geeky details.</li>
</ul>
<p>Download: <a href="http://www.saltwaterc.eu/wp-content/uploads/xve.zip">XVE 1.0 Beta 3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/xve-xve-various-embed-preview-release.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SVN Migration Toolkit</title>
		<link>http://www.saltwaterc.eu/svn-migration-toolkit.html</link>
		<comments>http://www.saltwaterc.eu/svn-migration-toolkit.html#comments</comments>
		<pubDate>Sat, 02 Apr 2011 14:45:00 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[Systems Administration]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1165</guid>
		<description><![CDATA[Since I tend to write about my solutions, or open source my own tools that may save someone some time, here&#8217;s another one: a simple SVN Migration Toolkit. Basically it&#8217;s just a bunch of bash scripts that automates the burden of moving a SVN server from an old machine to a new machine. It wasn&#8217;t [...]]]></description>
				<content:encoded><![CDATA[<p>Since I tend to write about my solutions, or open source my own tools that may save someone some time, here&#8217;s another one: a simple SVN Migration Toolkit.</p>
<p>Basically it&#8217;s just a bunch of bash scripts that automates the burden of moving a SVN server from an old machine to a new machine. It wasn&#8217;t designed for large dumps though, but if requested, I can add the functionality, or you can send a pull request <img src='http://www.saltwaterc.eu/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>You can grab it from GitHub: <a title="svn-migrate" href="https://github.com/saltwaterc/svn-migrate">svn-migrate</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/svn-migration-toolkit.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox, Google Chrome, Opera – Ubuntu Lucid browser JavaScript benchmark</title>
		<link>http://www.saltwaterc.eu/firefox-google-chrome-opera-ubuntu-lucid-browser-javascript-benchmark.html</link>
		<comments>http://www.saltwaterc.eu/firefox-google-chrome-opera-ubuntu-lucid-browser-javascript-benchmark.html#comments</comments>
		<pubDate>Wed, 23 Mar 2011 20:27:10 +0000</pubDate>
		<dc:creator>SaltwaterC</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.saltwaterc.eu/?p=1151</guid>
		<description><![CDATA[Introduction Given the fact that recently Firefox and Google Chrome got an upgrade under Ubuntu, I couldn&#8217;t resist the temptation to run a bunch of benchmarks. Since Opera also got an upgrade almost a couple of months ago, it was a fair fight. However, I didn&#8217;t run any CSS benchmarks since my interest is mainly [...]]]></description>
				<content:encoded><![CDATA[<p><strong>Introduction</strong></p>
<p>Given the fact that recently Firefox and Google Chrome got an upgrade under Ubuntu, I couldn&#8217;t resist the temptation to run a bunch of benchmarks. Since Opera also got an upgrade almost a couple of months ago, it was a fair fight. However, I didn&#8217;t run any CSS benchmarks since my interest is mainly into the JavaScript area. I used: <a title="V8 Benchmark Suite - version 6" href="http://v8.googlecode.com/svn/data/benchmarks/v6/run.html">V8 Benchmark Suite v6</a>, <a title="Kraken JavaScript Benchmark 1.0" href="http://krakenbenchmark.mozilla.org/kraken-1.0/driver.html">Kraken JavaScript Benchmark v1.0</a>, and <a title="SunSpider 0.9.1 JavaScript Benchmark" href="http://www.webkit.org/perf/sunspider-0.9.1/sunspider-0.9.1/driver.html">SunSpider Javascript Benchmark v0.9.1</a>.</p>
<p><strong>V8 Benchmark Suite</strong></p>
<p>The V8 Benchmark suite is Google&#8217;s tool for load testing the JavaScript performance. While it was expected that Google Chrome would take the crown of this test, I didn&#8217;t expect Opera falling behind by such noticeable margin. Below, the higher results are better.</p>
<p><img src="http://chart.apis.google.com/chart?&amp;cht=bhg&amp;chs=532x125&amp;chco=D96012,1473AD,DC0D0D&amp;chdl=Firefox|Google+Chrome|Opera&amp;chds=0,5000&amp;chxt=x&amp;chxr=0,0,5000&amp;chg=10,100,4,1,0,0&amp;chf=c,lg,0,F7F7F7,0,E5E5E5,1&amp;chm=N,2f2f2f,0,-1,12,,lv:3:|N,2f2f2f,1,-1,12,,lv:3:|N,2f2f2f,2,-1,12,,lv:3:&amp;chtt=V8+Benchmark+Suite&amp;chd=t:3783|4097|2895" alt="V8 Benchmark Suite: Firefox, Google Chrome, Opera" /></p>
<p><strong>Kraken JavaScript Benchmark</strong></p>
<p>This is Mozilla&#8217;s answer to the SunSpider JavaScript Benchmark. While they do somehow look alike, their results are very different. This one really took me by surprise. It is a pretty heavy benchmark, taking way much more time than SunSpider. It was expected that Firefox would take this one since it plays onto the home field, but I didn&#8217;t expect such decisive victory. While Opera also falls behind for almost 50% of the Firefox score, this test looks more like an anti-Chrome benchmark. Ouch Google, that hurt. The results are in milliseconds, lower is better.</p>
<p><img src="http://chart.apis.google.com/chart?&amp;cht=bhg&amp;chs=532x125&amp;chco=D96012,1473AD,DC0D0D&amp;chdl=Firefox|Google+Chrome|Opera&amp;chds=0,20000&amp;chxt=x&amp;chxr=0,0,20000&amp;chg=10,100,4,1,0,0&amp;chf=c,lg,0,F7F7F7,0,E5E5E5,1&amp;chm=N,2f2f2f,0,-1,12,,lv:3:|N,2f2f2f,1,-1,12,,lv:3:|N,2f2f2f,2,-1,12,,lv:3:&amp;chtt=Kraken+JavaScript+Benchmark&amp;chd=t:10814.2|17588.8|15731.7" alt="Kraken JavaScript Benchmark: Firefox, Google Chrome, Opera" /></p>
<p><strong>SunSpider JavaScript Benchmark</strong></p>
<p>SunSpider is almost a classic in this field. While being created by the WebKit guys, Google Chrome also plays onto the home field since it is a WebKit based browser, but with a different JavaScript engine. While it was expected to see Firefox coming near Google Chrome, I didn&#8217;t expect it overtaking Chrome. Actually, at work (different hardware configuration, Core 2 Quad Q9400 + 8 GiB RAM, same OS) Chrome was slight faster. Well, I can say that this falls into the negligible area. However, I didn&#8217;t expect &#8220;the fastest browser on the planet&#8221; falling behind these two by a noticeable margin. The results are in milliseconds, lower is better.</p>
<p><img src="http://chart.apis.google.com/chart?&amp;cht=bhg&amp;chs=532x125&amp;chco=D96012,1473AD,DC0D0D&amp;chdl=Firefox|Google+Chrome|Opera&amp;chds=0,500&amp;chxt=x&amp;chxr=0,0,500&amp;chg=10,100,4,1,0,0&amp;chf=c,lg,0,F7F7F7,0,E5E5E5,1&amp;chm=N,2f2f2f,0,-1,12,,lv:3:|N,2f2f2f,1,-1,12,,lv:3:|N,2f2f2f,2,-1,12,,lv:3:&amp;chtt=SunSpider+JavaScript+Benchmark&amp;chd=t:294.2|303.2|420.1" alt="SunSpider JavaScript Benchmark: Firefox, Google Chrome, Opera" /></p>
<p><strong>Configuration: OS, Hardware, Software</strong></p>
<p>I ran the tests under Ubuntu Lucid (10.04.02 LTS, amd64) with kernel 2.6.32-30-generic. The OS was upgraded before the tests. All the browsers ran their latest published versions into the (semi-)official repositores, without any add-ons, except Firefox that had Ubuntu Firefox Modifications. That means: Firefox 4.0, Google Chrome 10.0.648.151, and Opera 11.01. While Firefox 3.6.15 ships with Ubuntu Lucid, <a title="Install Firefox 4 In Ubuntu 10.04 / 10.10 Via PPA Repository - The Proper Way" href="http://www.webupd8.org/2011/03/install-firefox-4-in-ubuntu-1004-1010.html">Mozilla provides a semi-official Firefox 4.0 PPA</a>.</p>
<p>My hardware is a pretty modest Athlon II X2 240e @ 2.8GHz + 4GiB of RAM.</p>
<p><strong>Conclusions</strong></p>
<p>While I switched to Google Chrome since Google started to provide stable releases and public repositories for Debian &amp; Friends, going with Firefox from 0.8 to 3.6 is not an easy to forget experience. I tested every Firefox release since 4.0 Beta 1 and all I can say I&#8217;m glad the browser is finally back into the top area of the charts. Given the fact that Chrome still lacks certain features that I still like to see, while Chrome doesn&#8217;t come anywhere near a decent memory management given the appropriate number of extensions and tabs, I might give Firefox another change. Nice come back Mozilla.</p>
<p>Here are the screenshots that I took after the benchmarks: <a href="http://www.saltwaterc.eu/wp-content/uploads/ubuntu-lucid-browser-javascript-benchmark.zip">download</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.saltwaterc.eu/firefox-google-chrome-opera-ubuntu-lucid-browser-javascript-benchmark.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

 Served from: www.saltwaterc.eu @ 2013-05-23 21:29:37 by W3 Total Cache -->
