tag:blogger.com,1999:blog-73699176953918806452024-03-17T00:13:38.098-07:00Online VillageGeoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.comBlogger42125tag:blogger.com,1999:blog-7369917695391880645.post-11247081298210786822012-01-05T10:45:00.001-08:002012-01-16T08:25:42.830-08:00Install Graphite On A SmartMachine (SmartOS Zone)I've been hearing a lot of good things about Graphite lately. So I thought I'd give it a try on a SmartOS Zone (SmartMachine?). I had one heck of a time installing it. Here's how I did it. <br /><br />First, for some reason I had to use the 32bit version SmartOS 1.4.7. If you try the 64bit version, the first error you get:<br /><br /><pre><br />Checking for header Python.h : Could not find the python development headers<br /></pre><br /><br />But this appears to be a red herring and the real issue is related to 32 vs 64bit issues. Investigating this helped me understand why people don't like waf. Just use the 32bit zone and safe some pain.<br /><br /><br />Install all the dependencies that are available via pkgin:<br /><br />pkgin install apache gcc-compiler scmgit python27 pkg-config cairo xproto renderproto-0.11 kbproto py27-setuptools py27-django py27-twisted ap22-py27-wsgi<br /><br />I ran into a problem where it said apache was missing when I tried to download it. This was fixed by doing 'pkgin -f update'. The '-f' was necessary. <br /><br />Dependency - pycairo<br /><br />Install pycairo, we need py2cairo as its for python 2.7:<br /><br /><pre><br />git clone git://git.cairographics.org/git/py2cairo<br />cd py2cairo<br />PREFIX="/opt/local" ./waf configure<br />./waf build <br />./waf install<br /></pre><br /><br />Install Graphite components 'by hand'. Download, untar and run 'python setup.py install' in each of the resulting directories:<br /><br />http://pypi.python.org/pypi/carbon<br />http://pypi.python.org/pypi/graphite-web<br />http://pypi.python.org/pypi/whisper<br /><br />Install django-tagging by hand. Download, untar and run 'python setup.py install'.<br />http://code.google.com/p/django-tagging/downloads/list<br /><br /><br />Inside graphite-web run:<br /><br /><pre><br />./check-dependencies.py<br /></pre><br /><br />You might see warning, but there shouldn't see any FATAL messages.<br /><br />(Under Construction) You still need to: <br />- copy and edit the apache config<br />- copy the .wsgi example into place<br />- copy the carbon.conf.example and the storage-schemas.conf.example<br />- patch the settings.py file so that it doesn't prepend the third party pathGeoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com3tag:blogger.com,1999:blog-7369917695391880645.post-8243984203026538592011-11-05T19:10:00.000-07:002011-11-05T19:46:25.423-07:00How Node.js Multiprocess Load Balancing WorksAs of version 0.6.0 of node, load multiple process load balancing is available for node. The concept of forking and child processes isn't new to me. Yet, it wasn't obvious to me how this was implemented at first. It's quite <a href="http://nodejs.org/docs/v0.6.0/api/cluster.html">easy to use</a> however:<div><span class="Apple-style-span" style="background-color: rgb(248, 248, 248); "><br /><pre><code>var cluster = require('cluster');<br />var http = require('http');<br />var numCPUs = require('os').cpus().length;<br /><br />if (cluster.isMaster) {<br /> // Fork workers.<br /> for (var i = 0; i < numCPUs; i++) {<br /> cluster.fork();<br /> }<br /><br /> cluster.on('death', function(worker) {<br /> console.log('worker ' + worker.pid + ' died');<br /> });<br />} else {<br /> // Worker processes have a http server.<br /> http.Server(function(req, res) {<br /> res.writeHead(200);<br /> res.end("hello world\n");<br /> }).listen(8000);<br />}</code></pre><br /></span></div><div><span class="Apple-style-span" style="background-color: rgb(248, 248, 248); ">This is quite a beautiful api, but it hides some clever details. For instance, how is possible for all child processes to each open up port 8000 and start listening?</span></div><div><div><div><div><br /></div><div>The answer is that the cluster module is just a wrapper around child_process.fork and net.Server.listen is aware of the cluster module. Specifically, cluster.fork uses child_process.fork to create child processes with special variable set in their environments to indicate cluster was used. Specifically process.env.NODE_WORKER_ID is non-zero for such children. </div><div><br /></div><div><pre style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 1.4; text-align: -webkit-auto; background-color: rgb(255, 255, 255); "><div class="line" id="LC157" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">envCopy</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">[</span><span class="s1" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(221, 17, 68); ">'NODE_WORKER_ID'</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">]</span> <span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">=</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">id</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">;</span></div><div class="line" id="LC158" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="kd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">var</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">worker</span> <span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">=</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">fork</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">workerFilename</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">workerArgs</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">{</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">env</span><span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">:</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">envCopy</span> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">});</span></div></pre></div><div><div><br /></div><div>Then net.Server.listen checks to see if process.env.NODE_WORKER_ID is set. If so, then the current process is a child created cluster. Instead of trying to start accepting connections on this port, a file handle is requested from the parent process:</div></div></div></div><div><br /></div><div><div><div class="line" id="LC717" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; "><br /><br /></div><div class="line" id="LC717" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; ">//inside net.js<br /><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">require</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="s1" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(221, 17, 68); ">'cluster'</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">).</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">_getServer</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">address</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">port</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">addressType</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="kd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">function</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">handle</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">)</span> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">{</span></div><div class="line" id="LC718" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">self</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">.</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">_handle</span> <span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">=</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">handle</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">;</span></div><div class="line" id="LC719" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">self</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">.</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">_listen2</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">address</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">port</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">addressType</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">);</span></div><div class="line" id="LC720" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; "> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">});</span></div><div class="line" id="LC720" style="font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; text-align: -webkit-auto; white-space: pre; background-color: rgb(255, 255, 255); line-height: 1.4; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; "><span class="Apple-style-span" style="font-family: Georgia, serif; font-size: 16px; line-height: normal; white-space: normal; "><br /></span></div></div><div><pre style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font: normal normal normal 12px/normal 'Bitstream Vera Sans Mono', Courier, monospace; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font-size: 12px; line-height: 1.4; text-align: -webkit-auto; background-color: rgb(255, 255, 255); "><div class="line" id="LC217" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">//inside cluster.js<br />cluster</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">.</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">_getServer</span> <span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">=</span> <span class="kd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">function</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">address</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">port</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">addressType</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">cb</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">)</span> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">{</span></div><div class="line" id="LC218" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">assert</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">cluster</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">.</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">isWorker</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">);</span></div><div class="line" id="LC219" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "><br /></div><div class="line" id="LC220" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">queryMaster</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">({</span></div><div class="line" id="LC221" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">cmd</span><span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">:</span> <span class="s2" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(221, 17, 68); ">"queryServer"</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span></div><div class="line" id="LC222" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">address</span><span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">:</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">address</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span></div><div class="line" id="LC223" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">port</span><span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">:</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">port</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span></div><div class="line" id="LC224" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">addressType</span><span class="o" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">:</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">addressType</span></div><div class="line" id="LC225" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">},</span> <span class="kd" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; ">function</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">msg</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">,</span> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">handle</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">)</span> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">{</span></div><div class="line" id="LC226" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">cb</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">(</span><span class="nx" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">handle</span><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">);</span></div><div class="line" id="LC227" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "> <span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">});</span></div><div class="line" id="LC228" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; background-color: transparent; "><span class="p" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">};</span></div></pre></div></div><div><br /></div><div>Finally, this handle is listened on instead of creating a new handle. At which point you have another process that is listening on the same port. Quite clever, though I think the beauty of the api comes at the cost of some not so hideous hacks inside the api. </div></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com4tag:blogger.com,1999:blog-7369917695391880645.post-10701251116704085972011-10-23T11:32:00.000-07:002011-10-23T14:53:30.213-07:00Why KVM on Illumos matters - ZFS<div>When Joyent first <a href="http://dtrace.org/blogs/bmc/2011/08/15/kvm-on-illumos/">announced</a> they had ported KVM to Illumos, the value proposition didn't occur to me right away. Both KVM and Xen under Linux have been around for while and you if want/need to run a Linux guest, why not use a linux Host? One reason is a feature of ZFS known as a zvol.</div><div><br /></div><div>To understand what a zvol is, you must first understand what a zpool is. In short its an abstraction on top of one or many disks turning it all into a logical unit on which filesystems can be created. Multiple disks can be used for both redunancy and performance. In particular, you can create a zpool that uses a pair of super fast state of the art SSDs for the ZIL, or intent log. This makes random writes blazingly fast. You can add a couple of fast SSDs as a read caching layer (l2arc). Finally, use those boring old -but relatively high capacity- magnetic disks for raw storage. The result is a hybrid storage system that provides performance and redundancy at a terrific price.</div><div><br /></div><div>The zpool is where the zfs filesystems live. So once you create a pool you can create a bunch of different file systems in there. You can also create and export block devices from a zpool, these are called zvols. These block devices can now be passed to qemu running on top of kvm inside Illumos, providing the underlying VM's with potentially blazingly fast redundant storage. A Linux VM will use this block device as if were a raw disk.</div><div><br /></div><div>More generally, by using a zvol for a guest disk you can use all the <a href="http://en.wikipedia.org/wiki/ZFS#Features">ZFS features</a> that are below the zfs filesystem layer. For instance it's possible to snapshot a live/attached zvol then export that snapshot to a file which can be used to create backups and clones. The implications for cloud/cluster management are clear. </div><div><br /></div><div>Here's some other posts on zvols I found interesting:</div><div><br /></div><div><a href="http://www.markround.com/archives/37-ZFS-as-a-volume-manager.html">http://www.markround.com/archives/37-ZFS-as-a-volume-manager.html</a></div><div><div><a href="http://blogs.oracle.com/scottdickson/entry/fun_with_zvols_-_ufs">http://blogs.oracle.com/scottdickson/entry/fun_with_zvols_-_ufs</a></div></div><div><br /></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com3tag:blogger.com,1999:blog-7369917695391880645.post-78888813477869461882011-10-20T12:06:00.000-07:002011-10-23T09:40:58.181-07:00OpenSource Drobo replacement - UpdateAfter over two years of faithful service, I've upgraded <a href="http://onlinevillage.blogspot.com/2009_09_01_archive.html">my OpenSource Drobo replacement</a>. I thought it fitting to write an update post as my new setup is even better though mostly the same.<br /><br />For perspective, not long after I setup this system, Apple discontinued work on the ZFS port to OS X. Thankfully the work they had done was solid. During the last 2 years I lost 2 drives and was easily able to replace them and get back to full speed within 24 hours of purchasing a new disk.<br /><br />My new system consists of the same Mediasonic 4 bay ProBox headed by a Zotac ATOM based NetTop I purchased for around $300. You can buy a <a href="http://www.newegg.ca/Product/Product.aspx?Item=N82E16856173016">similar model</a> now without ram or disk for under $150. I'd go for this one if I could go back in time. You can use a cheap USB stick and two gigs of ram for under $100 these days.<br /><br />For the new head operating system I tried a couple of different Open Solaris/Illumos based distrobutions such as Smart OS, Open Indiana and Nextenta Core Platform. Unfortunately but unsurprisingly, these didn't seem to like my cheap hardware. I finally stumbled upon <a href="http://www.freenas.org/">FreeNas</a>, a FreeBSD based NAS appliance distribution complete with Web UI . Because it's FreeBSD based, support for ZFS is included. It's also designed to run from a USB stick in order to free up space for another drive which is a great idea.<br /><br />Migrating to FreeNAS was a breeze once I learned to trust the Web UI. I still had to manually chown and chmod everything from a shell. Chown fixed the ownership for sharing everything properly in the FreeNas way. Chmod was required to fix an ACL problem with the filesystem caused my the OS X port. I also elected to upgrade to version 15 of ZFS which took all of two seconds (literally). It's possible I could have easily accomplished all this in the FreeNAS UI but old habits die hard.<br /><br />Setuping up sharing was as easy as following the directions in the documentation. In short, create user, add user to group, configure the volume to be owned by that group with appropriate perms, create share, start/restart CIFS service. All in all it took about an hour!<div><br /></div><div>Here's an update to the caveat's section from first post:</div><div><br /></div><div><span class="Apple-style-span" style="font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; font-size: 13px; line-height: 18px; background-color: rgb(255, 255, 255); ">- you don't really need to know how to use a command line to get up and running with FreeNAS unless you're migrating coming from OS X ZFS<br />-esata does improve performance, at least it seems to though I've done no rigorous tests<br />-reboot the system, everything will come back online<pool><br />- the green drive problem doesn't seem to be an issue anymore</pool></span></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com6tag:blogger.com,1999:blog-7369917695391880645.post-88219175954218725702011-10-17T16:04:00.000-07:002011-10-20T13:58:00.689-07:00Mobile HTML5/JavaScript Apps Part II<span style="font-weight:bold;">Challenges Throttling Adoption</span><br /><br />In my previous article I outlined 10 reasons why the HTML5/JavaScript platform was the future of mobile app development. Adopting HTML5/JavaScript as a mobile development platform isn’t without it’s challenges however. In this article I outline the problems that are throttling the adoption of this platform.<br /><br /><span style="font-weight:bold;">The App Store Model</span><br /><br />Presently there is no standard format for bundling HTML5/JavaScript apps for inclusion into app stores. This is disadvantageous for a number of reasons. Foremost, app stores help your customer’s find your app. They provide a platform integrated place where people can rank and recommend your app. It can help you grow your business.<br /><br />Secondly, an app store also provides an integrated payment processing solution, often through cell phone billing. Sure they all take their cut and you could go the ad-supported route instead. But having a choice of models is one advantage the native app developers have. The seamless experience of well designed apps store is important.<br /><br /><span style="font-weight:bold;">Offline Support</span><br /><br />Your customer’s expect to keep working when they enter the subway or fly on airplane. Native applications are bundled in to discrete packages and so capability typically comes for free. Traditional web applications host application logic remotely. As such, logic is transferred across the internet each time the app gets started or it even worse it remains on the server entirely.<br /><br />In either case your customer is at the mercy of their mobile network which is bad for two reasons. The first is that the user experience will probably be slow or unusable, at least occasionally. The second is this architectural model causes a lot more data to be transferred. Mobile bandwidth isn’t cheap now that carriers are moving to plans with quotas.<br /><br />HTML5 does provide a offline web app solution in the form of offline manifests. Anyone who’s ever tried to use it knows how rough around the edges it still is. Eventually they’ll smooth out those edges, but the in the meantime it’s painful to use.<br /><b><br /></b><br /><span style="font-weight:bold;">The Solutions</span><br /><br />In my next post I’ll describe the new technologies that are emerging to solve these problems. A perfect storm is converging to make HTML5/JavaScript the dominant platform for mobile applications. The future is bright and open source software is leading the way.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-56127896480567543652011-10-17T16:01:00.000-07:002011-10-17T16:04:23.632-07:00Mobile HTML5/JavaScript Apps Part II'm convinced that HTML5+JavaScript is the future of mobile development. That’s not to say there aren’t challenges throttling the adoption of this technology in the mobile space. But suffice it to say we feel the advantages of JavaScript are so compelling that critical mass has been achieved. <br /><br />In my next article I’ll highlight the challenges facing mobile HTML5/JavaScript adoption. But first, here are the top 10 reasons why I believes HTML5+JavaScript is the future of mobile app development:<br /><br /><span style="font-weight:bold;">1) iOS (Apple)<br /><br />2) Android ( Google )<br /><br />3) BlackBerryOS ( RIM )<br /><br />4) Windows Phone 7 ( Microsoft )<br /><br /><span style="font-weight:bold;">5) WebOS ( HP formerly Palm )</span></span><br /><br />The first three mobile platforms each have close to a third of the market share. Yet their ‘native’ application platforms are all different. All of these devices have modern HTML5 browsers.<br /><br />As a Mobile App Developer, you want to target as many different platforms and customers as you possibly can. At the same time, your app needs to look GOOD and it needs to be consistent across platforms. Finding the talent to target all these native platforms would be expensive.<br /><br /><span style="font-weight:bold;">6) JavaScript Is The Most Widely Available Development Platform, Ever.</span><br /><br />There are over 2,000,000,000 internet users in the world now. Each uses a web browser, and that browser runs JavaScript. Eventually HTML5/JavaScript will work on every phone, laptop and desktop in the world.<br /><br /><span style="font-weight:bold;">7) You Can Still Sell HTML5/JavaScript Apps Through Regular App Stores</span><br /><br />Great things are happening at fellow Canadian startup Nitobi. They’ve created an open source HTML5 app platform that allows you to author native applications with web technologies and get access to APIs and app stores. With PhoneGap it’s possible to write your application in HTML5/JavaScript, package it in a native wrapper, then distribute it through traditional app store channels.<br /><br /><span style="font-weight:bold;">8) JavaScript Is F A S T, Fast.</span><br /><br />Google, Apple, Microsoft and Mozilla are all throwing cash and talent at making JavaScript faster. Techniques like JIT Compilation and Inline Caching are raising the bar on JavaScript performance. JavaScript is already fast and it will only get faster.<br /><br /><span style="font-weight:bold;">9) There Are *A Lot* Of JavaScript Developers Out There And The Number Is Growing</span><br /><br />Chances are if you do Web development in PHP, Ruby, Python, Perl, Java etc, you’ve also implemented client side logic in JavaScript. That is, almost every web developer out there has at least dabbled in JavaScript. As the Web as a platform continues to gain traction, so does JavaScript. There’s a large pool of talent waiting to code in this language.<br /><br /><span style="font-weight:bold;">10) Windows 8</span><br /><br />Even Microsoft is committed to supporting HTML/JavaScript as a core development technology. In a recent press release they describe Windows 8 as a re-imagining of the operating system. Here’s the part that stands out:<br /><br />“Windows 8 apps use the power of HTML5, tapping into the native capabilities of Windows using standard JavaScript and HTML to deliver new kinds of experiences. These new Windows 8 apps are full-screen and touch-optimized, and they easily integrate with the capabilities of the new Windows user interface.”<br /><br />No where in the press release do they mention .NET or Silverlight, technologies that Microsoft developed which compete directly with HTML5. So it seems that Microsoft is acknowledging that HTML5/JavaScript is platform to back if they’re going to retain developer mind-share.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com7tag:blogger.com,1999:blog-7369917695391880645.post-13446946487783296762011-10-17T15:58:00.000-07:002011-10-17T16:00:30.740-07:00A Fragmented Future United By Web TechnologiesThis post is in reponse to Peter Bright’s <a href="http://arstechnica.com/microsoft/news/2011/06/html5-centric-windows-8-leaves-microsoft-developers-horrified.ars">article</a> on arstechnica. <br /><br />Microsoft shocked many of it’s developer community when at D9 it announced HTML5/JavaScript would form the basis of Window’s 8 developer platform. Peter argues that saying nothing about the future of these technologies can only hurt Microsoft. However, I’m not sure Microsoft has much to lose and quite a bit to gain by spinning it this way. Here’s why.<br /><br />Microsoft may rule the desktop now, but the future is mobile and they know it. Windows Phone 7 may be great and it’s apps may be excellent but they’re playing some serious catch up to iOS, Android and even Blackberry. Remember, Microsoft makes more off Android royalties than it does on Windows Phone 7. So while it’s true that Microsoft risks alienating their developer community, at present course that community will become smaller and more marginalized as time goes on anyways. <br /><br />The truth is that if Microsoft wants be more than niche player in the mobile/tablet market, it needs to embrace HTML5. It’s just to far behind to expect to act as if it were Apple and try to force a proprietary platform. You can look towards the Financial Times launch of an HTML5 ‘iPhone’ app as model for the future here. Developing multiple high quality native applications is expensive and becoming increasingly unneccessary. <br /><br />Now microsoft hasn’t said they won’t support their traditional platforms. No, far from it. Chances are there’ll be support for Silverlight as well. So while windows developers might be afraid right now, they’ve invested too much hold a serious grudge. Once Microsoft finally placates their fears they’ll suck it up and leverage the skills they’ve invested so much in. <br /><br />By focusing the spotlight on their ‘choice’ of the only truly open cross-device app platform, Microsoft can been seen to be taking Windows in a bold new direction. Perhaps even buying themselves some creditability from the much larger web development community, many of whom still hold a grudge over IE 6. Microsoft has much to gain by spinning this decision as a bold and re-invention rather than reactionary concession. If that means temporarily upsetting their development community. They’ll get over it.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com19tag:blogger.com,1999:blog-7369917695391880645.post-14842564865106148762011-03-16T05:10:00.000-07:002011-04-04T12:48:34.723-07:00Is JavaScript Faster Than C?There's been a lot great work happening in the VM performance space over the last few years. The problems of performance are beginning to be well understood as even dynamic languages begin to challenge the incumbents. This article reviews a project which aims to bring more empirical testing to the language/runtime performance debate. Rather than argue about the theorectical, we let the code speak for itself. You may be suprised by what it says.<br /><br /><h3>Stop!</h3><br />The author of this article is well aware of its provocative nature. This is just one test and readers should take care when extrapolating these results to dissimilar use cases. The C code provided by the project being reviewed follows an Object Oriented style. It is certainly possible to optimize the C code further, for instance by using a more procedural style with less memory allocation. But then a similar approach should be used by the other versions (languages) presented as well. I whole heartedly encourge you to submit pull requests with these new versions in separate directories based on the style/technique used.<br /><br />My intention is to challenge readers to question their assumptions regarding language/runtime performance. I also hope to highlight the fact that server side JavaScript has become a viable platform choice when performance is a consideration. That said, this is one test and I can only encourage more work in this area. If you're interested in such things, check out <a href="http://shootout.alioth.debian.org/">The Computer Language Benchmarks Game</a>. Let's discuss results rather than argue fanatically about predictions.<br /><br /><h3>The Problem</h3><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORcV-81wsJjpEd515wLI5lVlVBSx-GSuUN-8QjXdoTnmmGVJnYRlZGWjvJ_205ZiMospNbZe2jvYPR58YhfNPT4qe0qgmHDyq0DLiLrAAdzGY5nwB0wfPT_aRPd7kVZesye16K_HrXzM/s1600/15-peg.jpg"><img style="float:none; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 264px; height: 207px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORcV-81wsJjpEd515wLI5lVlVBSx-GSuUN-8QjXdoTnmmGVJnYRlZGWjvJ_205ZiMospNbZe2jvYPR58YhfNPT4qe0qgmHDyq0DLiLrAAdzGY5nwB0wfPT_aRPd7kVZesye16K_HrXzM/s320/15-peg.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5584650554131337394" /></a><br />Solving 137846 games of the 15-Hole Peg Soltaire by calculating every possible move using an Object Oriented style. Solutions are provided in C, C#, Java, JavaScript, PHP, Python and Ruby (more submissions encouraged!). Most of the code was written by <a href="http://jonathan.fuerth.ca/">Jonathan Fuerth</a> his <a href="https://sites.google.com/site/torontojava/2010-slides-and-notes-1/2010-02-21slides-javaperformance.pdf?attredirects=0&d=1">presentation</a> on Java/HotSpot performance. I've updated the JavaScript so that it uses prototypical method inheritance. You can find my 'fork' on github.<br /><br /><h3>The Code</h3><br /><pre> git clone git://github.com/gflarity/peg-performance.git</pre><br /><br /><h3>Pre-requisites</h3><br />This was all developed and tested under OS X however there shouldn't be any platform dependencies. You'll need a number of things for the test itself. I've put the version I'm using in brackets: gcc (4.2.1), Mono (2.10.1), Java (1.6.0_24), node.js (0.4.2), PHP (5.3.3), Python (2.7.1), Ruby (1.8.7).<br /><br /><h3>Run the tests!</h3><br />Note this will take a few minutes as some platforms are definitely faster than others.<br /><pre> cd src/main<br /> make test</pre> <br />For each of the languages the test is run 10 times. I throw out the best and worst result then compute an average. A chart is created to show the results.<br /><br /><h3>Results</h3><br />Results can be viewed by opening .reports/report.html.<br /><br />Here is the graph produced by this test on my MacBook Air:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmcEDN_j-rabvyA_q8w6GGilaqBjhN8kSug2NqQGGRcGzxd-zxKpEcBY0JNWyLgEmrxIHH_fNFIfL3k2zkBLDWopXGG_iAalhOp1SqunC3xkAEXNw2JFdaVQsAUwa2o-cbnEnvrfdqEhc/s1600/results.png"><img style="cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmcEDN_j-rabvyA_q8w6GGilaqBjhN8kSug2NqQGGRcGzxd-zxKpEcBY0JNWyLgEmrxIHH_fNFIfL3k2zkBLDWopXGG_iAalhOp1SqunC3xkAEXNw2JFdaVQsAUwa2o-cbnEnvrfdqEhc/s320/results.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5584651136044803330" /></a><br /><h3>Analysis</h3><br />Here's what I find interesting about these results:<br /><br />0) The JavaScript implementation is even faster if you load the browser version in Chrome 10. It clocks in around 2300ms on my mba.<br /><br />1) HotSpot Java is F.A.S.T., FAST. I'd really like to see a C++ version for comparison in this test. But given the ecosystem out there and the fact that it's automatically cross platform, I'd have hard time justifying the use of C++ for many things these days... Well, maybe a kickass JavaScript engine ;)<br /><br />2) I'd also like to see the results of this test if this problem was solved in a non object oriented style. That said, there are distinct advantages to using OOP.<br /><br />3) Much respect to the Mono project. While I'm sure Microsoft's .NET runtime approaches the HotSpot VM in terms of performance, Mono is hanging in there.<br /><br />4) JavaScript is a dynamically typed language. We must consider this when comparing its performance vs a statically typed Java. While some might argue that static typing is 'safer', performance is its only virtue in my opinion. (Edit: Static typing also helps IDEs with code complete and other useful features, this is also a virtue :) Typically I trade reduced performance for increased development efficiency every time I choose Perl, Python or Ruby. So despite its quirks, it appears that JavaScript can offer the best of both worlds in terms of performance and development efficiency. Not bad for the language that's in every browser and hence is the most widely deployed language/runtime in the world.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com329tag:blogger.com,1999:blog-7369917695391880645.post-62176585183188346662011-02-26T12:41:00.000-08:002011-02-26T12:54:39.374-08:00Understanding Inheritance In JavaScriptIn this article I will present the JavaScript inerhitence model in a concise, and I hope, easy to understand manner. The intended audience consists of developers with some previous experience with dynamically typed languages. It is my opinion that any difficulty associated with understanding the JavaScript inheritance model can be attributed to the difficulty teaching recursive definitions in general. It's sometimes hard to know where to start, when your definition is circular. <br /><br />That said, let's boil JavaScript inheritance down into 5 key points in the following order:<br /><br />1) In JavaScript, everything is an 'object' and all variables simply hold references to them. The other 'primitive' or basic types (of objects) are functions, booleans, strings, numbers and arrays. <br /><br />2) Objects are collections of properties keyed by a reference. Most often, references to string objects are used as keys as they are immutable. This means that if foo and bar reference string types which contain the same data they are in fact the same object. This essentially makes Objects equivalent to hashes or dictionaries in other languages. <br /><br />3) In JavaScript functions are special objects. Not only can they be called or applied, they have a special 'prototype' property which holds an object that can be accessed and modified. When a function is used as a constructor with the 'new' key word, the resulting object that is created will *dynamically* inherit from the object referenced by the constructor function's 'prototype' property. <br /><br />Example:<br /><pre> Constructor = function() { };<br /> Constructor.prototype.name = 'alpha';<br /> Constructor.prototype.say_name = function() { console.log("my name is: " + this.name) };<br /> object = new Constructor();<br /> object.say_name();</pre><br /><br />4) Upon initial definition, the prototype property of every new function can be thought of like this:<br /><pre> func = function() {}<br /> func.prototype = { 'constructor': func };</pre><br />That is, the value referenced by func.prototype is an object contains a reference to func itself. This recursive definition is a bit eye-crossing but actually very beautiful in that way that only recursion can be.<br /><br />5) Here's where the recursive definitions start to get difficult to visualize. In JavaScript, every object (including functions) dynamically inherit from the special 'Object.prototype' object. In other words, 'Object' is THE constructor function of ALL objects in the JavaScript universe. The corollary being that Object.prototype.constructor == Object. <br /><br />Try it:<br /><pre> > Object.prototype.constructor == Object<br /> true</pre><H2>Implications</H2><br />These 4 points form the foundation of inheritance in JavaScript. Let's make use what we've learned:<H3>Corollary 1:</H3><br />Object types, or 'classes' can be (and generally are) referred to by their contructor function. Examples: Object, Function, String, Boolean, Array etc. <H3>Corollary 2:</H3><br />If you want to add a method to every object in the javascript universe (even after it is constructed!), mess with Object.prototype. <br />Example:<br />> Object.prototype.foo = 'bar'<br />> func = function() {}<br />> func.foo<br />"bar"<br />> Object.prototype.foo = 'baz'<br />> func.foo<br />"baz"<H3>Corollary 3:</H3><br />There's no such thing as multiple inheritance in JavaScript. That is class 'Foo' can not inherit from both 'String' and 'Array' directly. Though, you can use some clever tricks to hack multiple inheritance into the language. For examples, see <a href ="http://www.amirharel.com/2010/06/11/implementing-multiple-inheritance-in-javascript">http://www.amirharel.com/2010/06/11/implementing-multiple-inheritance-in-javascript</a> and <a href="http://code.google.com/p/joose-js/">http://code.google.com/p/joose-js/</a>.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com5tag:blogger.com,1999:blog-7369917695391880645.post-77032081392523896392011-02-26T06:47:00.000-08:002011-02-26T08:40:03.481-08:00Ubunt+Node+cluster on Amazon EC2 Quickstart<H2>Just Show Me The Scripts</H2><br />If you're just looking for a script to setup nodejs under ubuntu quickly, check out this <a href='https://github.com/gflarity/ec2-nodejs-setup'>set of scripts</a>.<br /><br /><H2>Walk Through</H2><br />First you'll need to Signup for AWS/EC2 and generate a key pair. Google it, there should be plenty of tutorials. <br /><br />Next, create an instance using the AWS Management Console and log into it using your key pair. You can find the AMI's <a href="https://help.ubuntu.com/community/EC2StartersGuide">here</a>. I picked a 32bit 10.04 LTS AMI in US-East.<br /><br />Install node's perquisites (or those that aren't the default ubuntu LTS ami):<br /><pre> sudo apt-get update<br /> sudo apt-get -y install build-essential libssl-dev</pre><br />Now let's create a nodejs system user:<br /><pre> sudo adduser --home /home/nodejs --shell /bin/bash --disabled-password --disabled-login --system nodejs</pre><br />Now login as that user:<br /><pre> sudo su nodejs</pre><br />For the heavy lifting we use the excllent 'nvm' from creationix<br /><pre> git clone git://github.com/creationix/nvm.git ~/.nvm<br /> . ~/.nvm/nvm.sh</pre><br />Install nodejs:<br /><pre> nvm sync<br /> time nvm install latest <br /> nvm use latest</pre><br />Setup the nodejs user's enviroment to have that latest nodejs in it's path<br /><pre> echo -e -n "\n. ~/.nvm/nvm.sh\n" >> ~/.bashrc<br /> echo -e -n "\nnvm use latest\n" >> ~/.bashrc</pre><br />Setup npm, this makes life much easier:<br /><pre> mkdir ~/git<br /> cd ~/git<br /> git clone https://github.com/isaacs/npm.git<br /> cd npm/<br /> make install</pre><br /><H2>Taking Full Advantage Multiple Cores/CPUs</H2><br />Assuming you want to take full advantage ec2's multiple cores then install 'cluster' - https://github.com/LearnBoost/cluster<br /><pre> npm install cluster</pre><br />Setup hello world example:<br /><pre> mkdir ~/git/sandbox<br /> cd ~/git/sandbox</pre><br />Edit cluster.js to contain cluster example:<br /><pre> var cluster = require('cluster')<br /> , http = require('http');<br /><br /> var server = http.createServer(function(req, res){<br /> console.log('%s %s', req.method, req.url);<br /> var body = 'Hello World';<br /> res.writeHead(200, { 'Content-Length': body.length });<br /> res.end(body);<br /> });<br /><br /> cluster(server)<br /> .use(cluster.logger('logs'))<br /> .use(cluster.stats())<br /> .use(cluster.pidfiles('pids'))<br /> .use(cluster.cli())<br /> .use(cluster.repl(8888))<br /> .listen(3000);</pre><br />Test it! <br /><pre> node cluster.js</pre><br />Using the domain you ssh'd into earlier, browse to http://<domain>:3000, you should see hello world.<br /><br />From the EC2 instance, login into the cluster admin interface:<br /><pre> telnet 0 8888<br /> Type help()</pre>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com1tag:blogger.com,1999:blog-7369917695391880645.post-79315327974462027182011-02-12T06:49:00.000-08:002011-02-14T17:21:38.001-08:00Realtime Performance Visualizations using Node.js<h3>Preamble</h3><br />This article outlines how to create a realtime heatmap of your syscall latency using HTML5, some great node modules, and DTrace. It was inspired by talk that Bryan Cantrill and Brendan Greg gave on Joyent's cool cloud analytics tools. While specific, the code provided could easily be adapted to provide a heatmap of any type of aggregation Dtrace is capable of providing.<br /><br /><H3>System Requirements</H3><br /><br />First thing's first, you're going to need a system with DTrace. This likely means Solaris (or one of its decedents), OS X, or a BSD variant. There doesn't appear to be Dtrace available for Linux.<br /><br /><H3> Security </H3><br />Secondly, please be aware that at the time of writing the demo code contains a fairly substantial secruity vulnerabilty. Namely the d script is sent from the client with no authentication what so ever. If you bind to localhost this shouldn't be a big deal for a demo. Time permitting I intend to clean up the code.<br /><br /><h3>Dependencies</h3><br />For this tutorial you'll also need:<br /><br />node - http://nodejs.org/#download (duh)<br />npm - https://github.com/isaacs/npm (makes installing modules a breeze)<br />node-libdtrace - https://github.com/bcantrill/node-libdtrace (provides dtrace functionality)<br />Socket.IO - 'npm install socket.io' (websockets made easy)<br /><br /><h3>Server</h3><br />Now we're ready to start writing our web server:<br /><br /><a href="https://github.com/gflarity/Heat-Tracer/blob/master/heat_tracer.js">heat_tracer.js</a><br /><br /><h3>Client</h3><br />In order to display our heatmap, we're going to need some basic HTML with a canvas element:<br /><br /><a href="https://github.com/gflarity/Heat-Tracer/blob/master/public/heat_tracer.html">heat_tracer.html</a><br /><br />Finally the JavaScript client which translates the raw streaming data into pretty picture:<br /><br /><a href="https://github.com/gflarity/Heat-Tracer/blob/master/public/heat_tracer_client.js">heat_tracer_client.js</a><br /><br /><h3>Run It!</h3><br />Run Heat Tacer with the following. Note, sudo is required by dtrace as it does kernal magic.<br /><br />sudo node heat_tracer.js<br /><br />If all goes well you should see a moving version of something like the image below.<br /><br /><div><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJDwiLflfKlmUtDPCKGX8NPhyphenhyphentySlnmKpwJwmfbxhJXnxOUWIkgb3UjNn2Mmyw4KGNZhbTKztX1MzQ-_ZJsy2u4I8-t2vuK6LnuypRMRTRr86ehaMVDDkACIs-ZVvr0WY7p16eaBLipUg/s320/heat_tracer.png" id="BLOGGER_PHOTO_ID_5572826457015342226" /></div><br /><br /><h3> Contribute </h3><br />You can find the latest version of Heat Tracer <a href="https://github.com/gflarity/Heat-Tracer">here</a>. It is my hope that this article will provide the ground work for a much more abitious performance analytics project. If you're interested in contributing please let me know.<br /><br /><h3> Further Research </h3><br />More information about Bryan and Brendan's demo can be found <a href="http://dtrace.org/blogs/brendan/2011/01/24/cloud-analytics-first-video/">here</a><br />Socket.IO can be found <a href="http://socket.io/">here</a>.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com2tag:blogger.com,1999:blog-7369917695391880645.post-70425773328245252812010-11-21T17:36:00.000-08:002011-02-12T06:48:35.999-08:00JavaScript is the future... wait wha?<div><span class="Apple-style-span" >1) JavaScript engines have become ridiculously fast thanks to corporate investment from the likes of Apple, Google, Mozilla etc.</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >2) There are a lot of JavaScript developers out there, the number is growing.</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >3) Browser based JavaScript is the most widely available programming platform, ever.<span class="Apple-tab-span" style="white-space:pre"> </span></span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >3) JavaScript development is non-blocking (event driven), and closure intensive (Ruby and Perl fans rejoice).</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >4) Node.js uses Chrome's V8 to make non-blocking event based service development easy and performant. The community momentum is truly astounding. </span></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com1tag:blogger.com,1999:blog-7369917695391880645.post-8702021481895235892010-07-30T07:09:00.000-07:002010-11-21T17:30:11.870-08:00Telus FAIL<div>Update: Somewhere around the middle of November the Telus HTC Hero was updated to Android 2.1. The battery life has decreased but at least they released it before Android 2.3 is out. </div><div><br /></div><div>I love the Android platform for a whole host of reasons, including the fact that it's so open. I accept that this sort of openness can lead ( has ) to fragmentation. This fragmentation means that when the core operating system is updated, it will inevitably take longer for the version specific to my phone, the Telus HTC Hero, to be released.</div><div><br /></div><div>I've been waiting for months to receive the Android 2.1 (Eclair) release for my Telus HTC Hero. At this time, I still haven't received it. It was ported to the HTC Hero months ago, but has yet to be released for Telus. Meanwhile, Android development has moved forward and Android 2.2 (Froyo) has been released. </div><div><br /></div><div>The HTC Hero will never see Froyo, and this pisses me off. But not as much as the fact that I've entered into a 3 year contract for a phone that has yet to receive a single software update. If you're going to lock user's in, you have a responsibility to keep the software on the phone reasonably updated. I understand hardware requirements might preclude certain releases, but that's the only excuse. </div><div><br /></div><div>In any event, I've learned my lesson, my next phone will be an official dev phone, as I always want to run the latest and greatest. In the meantime I'm going to be rooting my phone and installing a third party rom. Here's the info:</div><div><br /></div><div><br /></div><a href="http://b2basiks.com/?p=701">http://b2basiks.com/?p=701</a><div><a href="http://forum.xda-developers.com/showthread.php?t=581981">http://forum.xda-developers.com/showthread.php?t=581981</a></div><div><a href="http://www.villainrom.co.uk/viewforum.php?f=95">http://www.villainrom.co.uk/viewforum.php?f=95</a></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-86010723556819025332010-06-13T08:46:00.000-07:002010-06-13T16:42:41.682-07:00Grails & App Engine is just not there yetJust a quick follow up to my <a href="http://onlinevillage.blogspot.com/2010/05/while-html-5-holds-tremendous-promise.html">previous post</a>; I've unsuccessfully tried to get the 'Hello, World' application running on App Engine. The java script pop-up never works and I run into timeout's far too frequently once deployed. There also doesn't seem to be much in the way of support for this combination yet.<div><br /><div>For those interested, there was a brief mention of the problem during a <a href="http://code.google.com/events/io/2010/sessions/fireside-chat-app-engine.html">fireside chat </a> at Google IO. <a href="https://wave.google.com/wave/#restored:wave:googlewave.com!w%252B9PNCdLZkBuX">Here</a>'s the wave which summarizes the Q/A. If you haven't yet, I highly recommend the <a href="http://code.google.com/events/io/2010/sessions.html">Google IO videos</a>. </div><div><br /></div><div><br /></div></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-35287619690604749742010-05-30T08:40:00.000-07:002010-06-01T16:09:57.430-07:00Groovy, Grails and GWT (G3WT) TutorialWhile HTML 5 holds tremendous promise, my days of fiddling with CSS are over. Fortunately GWT offers an alternative to the traditional Web Application paradigm; by cross compiling Java into Javascript you only need one language for both your server and your client. Back to the future.<div><br /><div>Being a big believer in rapid prototyping, I'd much prefer having a Groovy -> Javascript compiler. Unfortunately Groovy isn't supported in the Client side GWT code since it's the .java files themselves that get cross compiled , not the bytecode. Still, it <i>is</i> possible to use Groovy ( Grails ) on the server side. using Grails and the GWT plugin. This provides the utility of Grails helper/scaffolding scripts and if you know Groovy it may save you time. Groovy's close coupling with Java also means that we need to not depart to far from the GWT paradigm either.</div><div><br /></div><div>In order to learn Grails/GWT I decided to create a 'Hello World' application which uses RPC. Here's the step by step instructions I used to make it for those who are curious:</div><div><br /></div><div><div>First make sure Groovy, Grails, and GWT are installed. Then we can create our Grails app:<br /></div><div>>grails create-app g3wt</div><div><br /></div><div>Now let's install the gwt plugin:</div><div>>cd g3wt</div><div>>grails install-plugin gwt</div><div><br /></div><div>Create a GWT to provide the server side logic:</div><div>><b>grails create-gwt-module g3wt.Application</b></div><div><br /></div><div>Create the client facing page which exposes the module we just created:</div><div>><b>grails create-gwt-page main/index.gsp g3wt.Application</b></div><div><br /></div><div>It will (may?) prompt to ask if you want to create the main controller. Choose y for yes.<br /><br />Now, lets git rid of the default grails page in favour of our new gwt page. You can do so by editing <b>grails-app/conf/UrlMappings.groovy</b>. Change <b>"/"(view:"/index")</b> to <b>"/"(view:"/main/index")</b> so that it picks up our newly created gwt page.<br /><br />Now you're ready to try it. From a terminal the following to start up your development web server:<br />><b>grails run-app</b><br /></div><div><br /></div><div>Now start up GWT's "Development Mode" tool by running the following in another terminal:<br />><b>grails run-gwt-client</b><br /><br /></div><div>Click on the <span style="font-weight: bold;">launch default browser</span> button. Your new GWT should open and establish a connection with the Development Mode tool. At this point there's not really much here, so let's add a hello world rpc service.<br /><br />First we create our Grails service:<br />> <b>grails create-service Data</b><br /><br />Edit the file <span style="font-weight: bold;">grails-app/services/g3wt/DataService.groovy</span>. Remove the empty serviceMethod method. Then add the following below "static transactional = true":<br /><pre class="brush:groovy"><br />static expose = [ 'gwt:g3wt.client' ]</pre>This line tells the grails helper script where to put the Java interfaces for the RPC calls.</div><div><br /></div><div>Next replace serviceMethod with:<br /><pre class="brush:groovy"><br />String helloWorld() {<br />return "Hello, World!"<br />}<br /></pre><br />Then we create the required normal and asynchronous interfaces under the <code>src/java</code> directory:<br />><b>grails generate-gwt-rpc</b><br /><br />That's it for the server side. Now we edit the client scaffolding that was generated for us in </div><div><b>src/gwt/g3wt/client/Application.java</b>. </div><div><br /></div><div>Add the following import statements:</div><br /><pre class="brush:groovy"><br />import com.google.gwt.core.client.GWT;<br />import com.google.gwt.user.client.rpc.ServiceDefTarget;<br />import com.google.gwt.user.client.rpc.AsyncCallback;<br />import com.google.gwt.user.client.Window;</pre><pre><br /></pre>Place the following in the <b>onLoad</b> method:</div><div><pre class="brush:groovy"><br />DataServiceAsync myService = (DataServiceAsync) GWT.create(DataService.class);<br /><br />ServiceDefTarget endpoint = (ServiceDefTarget) myService;<br /><br />// Note the URL where the RPC service is located! <br />String moduleRelativeURL = GWT.getModuleBaseURL() + "rpc";<br />endpoint.setServiceEntryPoint(moduleRelativeURL);<br /><br />// Call a method on the service! <br />myService.helloWorld( new AsyncCallback() {<br /> public void onSuccess(Object result) {<br /> // It's always safe to downcast to the known return type. <br /> String resultString = ( String ) result;<br /> Window.alert( resultString );<br /> }<br /><br /> public void onFailure(Throwable caught) {<br /> }<br /><br />}<br />);<br /></pre>There's a lot of GWT magic here. My understanding is that the GWT looks at this entire line when it cross compiles and generates the right javascript object for our rpc calls. Then we can perform an rpc call using anonymous call that implements the AsyncCallback interface.</div><div><br /></div><div><div>Run it again:</div><div>><b>grails run-app</b><br /></div><div><br /></div><div>Start up GWT's "Development Mode" tool by running the following in another terminal:<br />><b>grails run-gwt-client</b></div></div><div><b><br /></b></div><div>You should see our "Hello, World!" alert box. </div><div><br /></div><div>In the next installment I'm going demonstrate how to run our example under Google App Engine. </div></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com16tag:blogger.com,1999:blog-7369917695391880645.post-62810082430166755142010-05-16T19:06:00.000-07:002010-05-16T19:14:17.196-07:00Groovy++ Sources<div>It seems as though my cynicism was unfounded. You can find the Groovy++ source <a href="http://code.google.com/p/groovypptest/downloads/list">here</a>. </div><div><br /></div><div>My apologies to the author(s?). In my defence browsing the source tree through google code only yields the demo examples and last I checked the downloads only provided the examples as well. </div><div><br /></div><div><br /></div><div><br /></div><div><br /></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-6103186518225519672010-05-15T10:32:00.000-07:002010-05-16T19:06:25.439-07:00Groovy++? Ok, so where's the beef?<div>Update: You can find the sources at http://code.google.com/p/groovypptest/downloads/list</div><div><br /></div>If you're a software professional who uses Groovy, you or your colleagues greatest concern about it is likely to be performance. Groovy++, while having a horrible name, provides a jar which apparently provides some <a href="http://groovy.dzone.com/articles/how-come-groovy-overperform">mag</a>-i-c<a href="http://code.google.com/p/groovypptest/wiki/HowDoesItWork">al</a> Groovy performance <a href="ttp://stronglytypedblog.blogspot.com/2010/02/groovy-performance-now-were-talkin.html">gains</a>. According to its authors', this new 'Groovy-ness' will be <a href="http://groups.google.com/group/groovyplusplus/browse_thread/thread/c839e7cce4c89bf7?pli=1">released under the Apache Public License</a>. Terrific! Wonderful! Hurray! <div><br /></div><div>So where's the fracking code?</div><div><br /></div><div> I can understand a need for control. I can understand the author's desire to turn this into something significant for themselves financially. A man's got to eat. But until the code is open and can be inspected by some experts, I remain skeptical of Groovy++. I am hopeful however that performance improvements can be made given enough manpower and talent. Too bad we all have day jobs ;)</div><div><br /></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com4tag:blogger.com,1999:blog-7369917695391880645.post-13633718781347187432010-04-29T18:34:00.000-07:002010-04-29T20:03:28.522-07:00Go adds JSON-RPC to core libRecently I started looking for a small but useful project to serve as a vehicle for learning Go. After mulling on a few ideas I decided to create a <a href="http://en.wikipedia.org/wiki/JSON-RPC">JSON-RPC</a> library. I generally appreciate the concept of RESTful webservices, but in my opinion this technology needs a simple common RPC protocol. JSON-RPC is exactly that. I find it particularly useful in protocols for controlling Daemon's remotely. <div><br /></div><div>Well... I'm glad that I hadn't gotten very far in my implementation; as of 27/04/2010 JSON-RPC <a href="http://blog.golang.org/2010/04/json-rpc-tale-of-interfaces.html">has been</a> <a href="http://golang.org/pkg/rpc/jsonrpc/">included</a> in the core Go packages. Great minds thing a like I guess... :)</div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com1tag:blogger.com,1999:blog-7369917695391880645.post-6891115395102736682010-04-26T19:23:00.000-07:002010-04-26T20:16:59.899-07:00Playing with Go Memory Synchronization<div><span class="Apple-style-span" style="font-family:Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size:medium;">Go has its own model of process/threads/light-weight processes/coroutines, these are called goroutines. </span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size:medium;">Channel communication is the main method of synchronization between goroutines. There are buffered and unbuffered channels. Both types of channels block on receive. Unbuffered channels block on send, buffered channels block on send once the buffer is full. </span></span></span></div><div><span class="Apple-style-span" style="font-family:Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size:medium;"><br /></span></span></div><div><span class="Apple-style-span" style="font-family:Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size:medium;">I</span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size:medium;">'ve created some test code based on the sample </span><a href="http://golang.org/doc/go_mem.html"><span class="Apple-style-span" style="font-size:medium;">provided</span></a><span class="Apple-style-span" style="font-size:medium;"> in the documentation in case someone else want's to play poke black-box-style at the memory model. Channel 'events' cause memory synchronization to occur. But as the documentation describes you need to be careful with buffered channels, the synchronization occurs during receive not send. If you play around with it a bit you'll see the importance of using </span></span><a href="http://golang.org/doc/go_mem.html"><span class="Apple-style-span" style="font-size:medium;">Locks</span></a><span class="Apple-style-span"><span class="Apple-style-span" style="font-size:medium;">, although you'd probably want to rely on the flexibility, safety and abstraction offered by Channels.</span></span></span></div><div><span class="Apple-style-span" style="font-family:Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size:medium;"><br /></span></span></div><div><span class="Apple-style-span" style="font-family:Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size:medium;"><a href="http://github.com/gflarity/GoMemoryModelTest">Enjoy</a>.</span></span></div><div><span class="Apple-style-span" style=" ;font-family:Helvetica, Arial, sans-serif;font-size:9.02778px;"><span class="Apple-style-span" style=" ;font-size:9.02778px;"><br /></span></span></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-40143299172538456112010-04-03T18:40:00.000-07:002010-04-07T16:43:37.424-07:00Go Go Gadget-ConcurrencyPremature optimization may be the root of all evil, but timely optimization is often required. When optimization becomes necessary, coding in Groovy can make refactoring in Java painless. However, Java is a less than ideal "systems programming" language for a number reasons, the least not being that it wasn't designed to be such. Yet if you've ever spent significant time using a dynamically typed language such as Groovy or even a statically typed yet garbaged collected like Java, you'll find having to go back to C, or C++ to be onerous to say the least. .<br /><br />Enter Go. Taken from the Go <a href="http://golang.org/doc/go_lang_faq.html">Language Design FAQ</a>:<br />"Go is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language. It also aims to be modern, with support for networked and multicore computing. Finally, it is intended to be fast: it should take at most a few seconds to build a large executable on a single computer. "<br /><br />This sounds almost too good to be true, mainly because it's been a long time coming. There hasn't been much inovation- at least that which has received popular traction- in the systems programming space since C/C++. Indeed, Go looks much like C itself with some of the syntax reversed. Digging a little deeper there are number of features that a programmer used to dynamic typing would consider must have. Namely maps, foreach-like loops and minimizing the type declcaration necessary for variable instantiation.<br /><br />At the same time, Go offers some impressive concurrency features: light-weight 'threads' or goroutines, segmented stacks and channels as first class objects. Go multiplexes independently executing functions. When a function blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked. Combined these features make high performance concurrent applications conceptually simple. <div><br /></div><div>If you haven't already, take a <a href="http://www.youtube.com/watch?v=rKnDgT73v8s">look</a> at <a href="http://golang.org/">Go</a>.<br /><br /></div>Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com6tag:blogger.com,1999:blog-7369917695391880645.post-43353948222718570002009-12-25T17:12:00.000-08:002009-12-25T17:16:36.900-08:00Transcoding Videos Using VLCI found this <a href="http://tom.zickel.org/vlcmp4/">great how-to for using VLC to converter/shrink/transcode videos</a>. This is so you can shrink them to play on your ipod, iphone, Android device, whatever. <br /><br />Its a bit slow as I think it actually plays the file normally as it saves the output file. Regardless, It was simple and I got it working on my Mac although the preferences menu entry is in a different spot (under the VLC menu entry ).Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-54407510028306035232009-12-22T14:49:00.000-08:002009-12-23T15:38:53.875-08:00Easy Hex SHA-1/MD5 Hashes with GroovyThe Java API has included support for a number of cryptographic hash functions ( MD5, SHA-1, etc) since Java 1.4 via the java.security.MessageDigest class. If you ever tried to use these in a web-centric context you've probably been a bit annoyed by the fact that it only provides hash results as byte arrays. Here's a quick and easy solution using Groovy that I thought I'd share:<br /><br /><pre class='brush:groovy'><br />def messageDigest = MessageDigest.getInstance("SHA1")<br />messageDigest.update( stringToHash.getBytes() );<br />def sha1Hex = new BigInteger(1, messageDigest.digest()).toString(16).padLeft( 40, '0' )<br /></pre><br /><br />Notice the padding of zeros since the length of the SHA-1 hex needs to be 40 characters. If you're using a different hashing hex string length will change.<br /><br />Note: Code updated to reflect an improvement submitted in the comments.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com2tag:blogger.com,1999:blog-7369917695391880645.post-53701836481133343382009-12-16T19:51:00.000-08:002009-12-16T21:09:38.778-08:00Production Groovy Part I: The trouble with GrapeLike Perl, Groovy's utility is most evident while <a href="http://groovy.codehaus.org/Grape">leveraging</a> the <a href="http://repo1.maven.org/maven2/">work of others</a>. In Groovy 1.7, Grape makes doing so intuitive with the addition of annotations on import statements:<br /><br /><pre class='brush:groovy'><br /><br />@Grab( group = 'com.sun.jersey', module='jersey-core', version = '1.1.2-ea' )<br />import com.sun.jersey.api.core.DefaultResourceConfig<br />@Grab( group = 'com.sun.jersey', module='jersey-server', version = '1.1.2-ea' )<br />import com.sun.jersey.api.container.httpserver.HttpServerFactory<br /><br /></pre><br /><br />The trouble with Grape is that by default it resolves dependencies by contacting or attempting to contact certain Maven2 repositories. Now, this isn't a problem if you're a web startup looking to bring a product to market as quickly and cheaply as possible. But it is a problem if you're looking to start deploying Groovy to a secure production environment. Fortunately, Groovy's close coupling with Java provides a clean and elegant solution. <br /><br />The key is that Maven2 remote repository caching and local repository hosting has been made easy by <a href="http://www.jfrog.org/products.php">Artifactory</a>. It can be configured to dynamically dial out and cache artifacts on demand from remote repositories. It can also more simply be used to manually manage artifact deployment. Thus provinding both flexibility and control. <br /><br />In order to take advantage of Artifactory you'll want to modify the default Grape/Ivy configuration so it points to your internal Artifactory repository by default. The bad news is that you'll need to modify the an xml file and rebuild the the jar. The good news is that the groovy source itself uses Ivy so modifying the xml and building Groovy is really easy. <br /><br />Simply download the latest <a href="http://groovy.codehaus.org/Download">Groovy source zip</a>. Then modify '/src/main/groovy/grape/defaultGrapeConfig.xml'. You can then build yourselve a new zip distribution by running 'ant createJars -DskipTests=true'. <br />Skipping the tests is optional, of course. <br /><br />Thats it. Once you explore Artifactory a bit you'll discover that it can provide as little or as much control of the artifacts available to Grape as you desire.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com3tag:blogger.com,1999:blog-7369917695391880645.post-20254343942139595512009-12-11T06:45:00.001-08:002009-12-11T06:50:31.769-08:00Fido iPhone Roaming FraudHere's an interesting post which underscores why Canadians need more wireless broadband competition. Click on the lick to read about how <a href="http://k4t3.org/2009/12/09/why-data-roaming-will-cost-you-way-too-much-even-when-you-dont-use-it/">Fido's data roaming screws over a customer</a>.Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com0tag:blogger.com,1999:blog-7369917695391880645.post-54285197648891494682009-12-02T18:19:00.001-08:002009-12-02T19:01:44.432-08:00Groovy Serialization - Part 2 - ObjectsIn my previous post I discussed the <a href="http://onlinevillage.blogspot.com/2009/12/groovy-serialization.html">serialization of simple Groovy data structures</a>. Arbitrary objects can also be serialized using ConfigObject and ConfigSluper and a little trickery. The fact Groovy config files may also contain code makes this all possible. <br /><br />In order to instantiate objects inside a Groovy config file, you need import the referenced objects. You also need to override the toString to create the proper instantiation string.<br /><br /><pre class='brush:groovy'><br />package MyPackage<br />class MyObject {<br /> def data;<br /> String toString() {<br /> def serializedString = "new MyObject( data : '${data}' )"<br /> return serializedString<br /> } <br />}<br /><br />//create the datastructure<br />def myObject = new MyObject( data: 'wtf')<br />def configObj = new ConfigObject()<br />configObj.testing = [1, 2, 3]<br />configObj.nested = [ objects : myObject ]<br /><br />//serialize it<br />new File( 'newout.groovy' ).withWriter{ writer -><br /> writer.write( "import ${myObject.getClass().getName()}\n" )<br /> configObj.writeTo( writer )<br />}<br /></pre><br /><br />Parsing it is simple:<br /><pre class="brush:groovy"><br />def config = new ConfigSlurper().parse(new File('newout.groovy').toURL())<br />println config<br /></pre><br /><br />Finally one could use .metaClass to override the toString of any Java object and make it work with this serialization technique. Be careful not to shoot yourself in the foot by doing this, as other code might expect the regular toString().Geoff Flarityhttp://www.blogger.com/profile/01239564240519036467noreply@blogger.com2