<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7741860926133428681</id><updated>2012-01-20T14:15:54.278-08:00</updated><category term='ruby'/><category term='acts_as_paranoid'/><category term='engines'/><category term='Nice'/><category term='DotNetOpenID'/><category term='ActiveRecord'/><category term='Pro'/><category term='quote'/><category term='Patrick Rothfuss'/><category term='Apple'/><category term='lirc'/><category term='agile'/><category term='JExample'/><category term='git'/><category term='configuration'/><category term='software engineering'/><category term='rails'/><category term='TextMate'/><category term='Paris'/><category term='Mac'/><category term='mini'/><category term='rubinius'/><category term='JUnit'/><category term='Spring'/><category term='Ruby on Rails'/><category term='rake'/><category term='patch'/><category term='nfs-kernel-server'/><category term='MythTV'/><category term='imon'/><category term='login'/><category term='LCDproc'/><category term='vacation'/><category term='Cory Doctorow'/><category term='Neil Gaiman'/><category term='Intrepid Ibex'/><category term='Java'/><category term='Sinatra'/><category term='book'/><category term='OpenID'/><category term='Little Brother'/><category term='NFS'/><category term='nfs-user-server'/><category term='Rack'/><category term='Maven'/><category term='garbage collection'/><category term='Rails 3'/><category term='Ubuntu'/><category term='testing'/><category term='plugins'/><category term='bleak_house'/><title type='text'>Engineering Code</title><subtitle type='html'>while for switch and case break class package import continue if do module and def end begin in or self unless next rescue then when else retry alias elsif return undef yield</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>29</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-6158839575707351668</id><published>2010-06-21T17:12:00.000-07:00</published><updated>2010-06-21T17:12:19.282-07:00</updated><title type='text'>User Interface ambiguity - never good</title><content type='html'>This browser dialog was produced as part of the flow of stopping gas service. The text and buttons combine for almost perfect ambiguity. Continue to stop the service? Continue the service? Cancel stopping the service or Cancel the service?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;You have elected to stop your NSTAR service.&amp;nbsp; Do you wish to continue?&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: large;"&gt;Cancel&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: large;"&gt;OK&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Much clearer would be text and button labels such as: &lt;/span&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;You have elected to stop your NSTAR service. Please confirm that choice:&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&amp;nbsp;&amp;nbsp; Yes - please stop my service&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&amp;nbsp;&amp;nbsp; No - I have changed my mind&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Even a simple yes / no would be so much better.&lt;/span&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-6158839575707351668?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/6158839575707351668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=6158839575707351668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6158839575707351668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6158839575707351668'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/user-interface-ambiguity-never-good.html' title='User Interface ambiguity - never good'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-2945543769547261123</id><published>2010-06-09T08:39:00.000-07:00</published><updated>2010-06-09T08:39:44.932-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rubinius'/><title type='text'>Rubinius 1.0 at RailsConf</title><content type='html'>&lt;b&gt;Rubinus&lt;/b&gt; is currently at 1.0.1 as of last week.&lt;br /&gt;&lt;br /&gt;No continuations but otherwise &lt;b&gt;Ruby&lt;/b&gt; 1.8.7 compatibility.&lt;br /&gt;&lt;br /&gt;Faster string method performance through better algorithms than MRI and the just-in-time compiler.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;DataMapper&lt;/b&gt; 1.0 was demonstrated with Rubinius 1.0 at RailsConf.&lt;br /&gt;&lt;br /&gt;Rubinius has a built-in profiler &lt;i&gt;-Xprofile&lt;/i&gt;. Also a sampling profiler which will show a high-level view of where your code spends its time - but with a negligible CPU overhead.&lt;br /&gt;&lt;br /&gt;The Debugger is targeted to be fixed for 1.1. There is a Ruby API which can be used to integrate another debugger into Rubinius' debug support.&lt;br /&gt;&lt;br /&gt;A new Query Agent API which can provide information about the state of the VM even when it is otherwise unresponsive. To be used with a control console (&lt;i&gt;bin/rbx -Xagent.start&lt;/i&gt; and &lt;i&gt;bin/rbx console&lt;/i&gt;) a port file is produced which the console reads to find how to communicate with the query agent. The console has commands such as &lt;i&gt;pid&lt;/i&gt;, &lt;i&gt;mem, set, threads, name&lt;/i&gt; and &lt;i&gt;get&lt;/i&gt;. The latter gets variable values e.g. &lt;i&gt;get system.backtrace&lt;/i&gt; produces the stack trace of the thread which is waiting for user input or whatever else the VM happens to be doing. This interface is very basic but has a lot of potential with future debugger/console integration.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-2945543769547261123?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/2945543769547261123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=2945543769547261123' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2945543769547261123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2945543769547261123'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/rubinius-10-at-railsconf.html' title='Rubinius 1.0 at RailsConf'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-7356763526053718855</id><published>2010-06-08T07:59:00.000-07:00</published><updated>2010-06-08T10:46:15.681-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><title type='text'>Real Software Engineering (at RailsConf)</title><content type='html'>&lt;font size="4"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-weight: bold;"&gt;Glenn Vanderburg&lt;/span&gt; is analyzing how software engineering was defined by in the late 1960s and how we got to where we are today.  If software engineering is not defined by the waterfall development process or other denigrated process then how is it defined?&lt;br /&gt;&lt;br /&gt;"Cost is always an object." - there is a price to 'do things right' and sometimes it is too high.&lt;br /&gt;&lt;br /&gt;"Software engineering will be different from other engineering."&lt;br /&gt;&lt;br /&gt;Traditional engineering produces a design which a manufacturing group turns into a product. In software engineering a similar process has not been very successful (Software Architects passing off designs to Programmers for implementation).&lt;br /&gt;&lt;br /&gt;Reeves suggests that, with the cost of prototyping so low, that testing models to verify that they meet requirements is practical (and much cheaper than the example of testing the wings of a Boeing 777 until they broke).&lt;br /&gt;&lt;br /&gt;Vanderburg mentions that Agile practices are criticized by some for being bad engineering - cowboy coding because of the flexibility of the process.&lt;br /&gt;&lt;br /&gt;Software engineering assumptions which are now invalid: code is hard to read, to change, and that testing is expensive.&lt;br /&gt;&lt;br /&gt;His thesis is that Real Software Engineering  is unlike creating bridge designs but retains a process which delivers a product which meets requirements where the key engineering document is the source code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-7356763526053718855?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/7356763526053718855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=7356763526053718855' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/7356763526053718855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/7356763526053718855'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/real-software-engineering-at-railsconf.html' title='Real Software Engineering (at RailsConf)'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-1589110493031291066</id><published>2010-06-07T12:39:00.000-07:00</published><updated>2010-06-07T13:31:00.373-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='engines'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails 3'/><title type='text'>Rails 3 Deep Dive - part 2</title><content type='html'>&lt;span style="font-weight: bold;font-size:130%;" &gt;Plugins&lt;/span&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Rails 3&lt;/span&gt; uses &lt;span style="font-weight: bold;"&gt;Railties&lt;/span&gt; to integrate your plugin/gem more cleanly. Having your plugins be gems is a goal.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Engines&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Lots of configuration possibilities. There is now much more fine-grained support for hooks into the Rails startup process. You now inherit from &lt;span style="font-style: italic;"&gt;Rails::Engine&lt;/span&gt; to initiate the integration.&lt;br /&gt;&lt;br /&gt;Jeremy adds a small sample engine very quickly. Interestingly he appears to be running on Rails 3 on &lt;span style="font-weight: bold;"&gt;ruby 1.9.2-head&lt;/span&gt; - a vote of confidence in the recently attained support.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Generators&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Now generators have simpler syntax but all the public methods are generator tasks, so make other code private.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Thor&lt;/span&gt; is behind the generators and has a lot of built-in support for file system and other operations.&lt;br /&gt;&lt;br /&gt;It is easy to configure the components which you want to be used with your custom generators:&lt;br /&gt;&lt;br /&gt;view template - say :haml&lt;br /&gt;test framework - say :rspec&lt;br /&gt;fixture replacement - say :factory_girl&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;The generators use this configuration to create appropriate files (e.g. unit tests with the correct testing framework when a new model is generated).&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-1589110493031291066?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/1589110493031291066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=1589110493031291066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1589110493031291066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1589110493031291066'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/rails-3-deep-dive-part-2.html' title='Rails 3 Deep Dive - part 2'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-2569225763329864222</id><published>2010-06-07T11:46:00.000-07:00</published><updated>2010-06-07T12:30:25.280-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rack'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Sinatra'/><title type='text'>Rails 3 Deep Dive</title><content type='html'>Surprisingly, &lt;span style="font-weight: bold;"&gt;Sinatra&lt;/span&gt; was a major part of the first lab in the &lt;span style="font-weight: bold;"&gt;Rails 3 Deep Dive&lt;/span&gt;. The idea was to understand how to use &lt;span style="font-weight: bold;"&gt;Rack&lt;/span&gt; with middleware and Rails, using Sinatra as an easy introduction. I love to learn new stuff but, if you want to teach Rack this way, please give us a heads-up so that ignorance of Sinatra won't slow us down.&lt;br /&gt;&lt;br /&gt;The takeaway: Rails 3 uses Rack much more than Rails 2. A lot of Rails filters may or have become Rack middleware.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-2569225763329864222?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/2569225763329864222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=2569225763329864222' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2569225763329864222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2569225763329864222'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/rails-3-deep-dive.html' title='Rails 3 Deep Dive'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-6545506231124878733</id><published>2010-06-07T10:27:00.000-07:00</published><updated>2010-06-07T10:35:28.024-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='Rails 3'/><title type='text'>Git Immersion</title><content type='html'>The tutorial was good for people who had never used &lt;span style="font-weight: bold;"&gt;git&lt;/span&gt; before. It also gave a good background on the implementation strategy. However, everyone there had used &lt;span style="font-weight: bold;"&gt;git&lt;/span&gt; before so I think a lot of the introductory material about &lt;span style="font-style: italic;"&gt;add&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;commit&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;status&lt;/span&gt; etc would have been too familiar for most.&lt;br /&gt;&lt;br /&gt;I zipped through the lab exercises and moved to Brian's Rails 3 Ropes tutorial during the mid-morning break. Over there, I had to race to catch up but got some fun experience upgrading a &lt;span style="font-weight: bold;"&gt;Rails 2&lt;/span&gt; application to &lt;span style="font-weight: bold;"&gt;Rails 3&lt;/span&gt;. The second half was well-presented (and I will assume the first half was too) by the Envy Labs folks with Gregg Pollack doing the speaking and the rest of the team assisting people as they had problems with the exercises.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-6545506231124878733?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/6545506231124878733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=6545506231124878733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6545506231124878733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6545506231124878733'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/git-immersion.html' title='Git Immersion'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-4930526688862727174</id><published>2010-06-07T03:54:00.000-07:00</published><updated>2010-06-07T04:19:54.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>RailsConf Baltimore</title><content type='html'>I have been using &lt;b&gt;Ruby on Rails&lt;/b&gt; since just before 1.0 and yet now is the first time I have been able to get to &lt;b&gt;RailsConf&lt;/b&gt;. It is also my first visit to Baltimore and my first trip on Amtrak's Acela brought us down here from Boston. &lt;b&gt;RBM&lt;/b&gt; sent Brian and myself down here and, given the very productive rail journey, we are already off to a good start.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have tried to split a lot of the conference content between us. Monday is tutorial day and while Brian is getting an introduction to Rails 3 via &lt;b&gt;Rails 3 Ropes&lt;/b&gt;, I am going to a &lt;b&gt;Git Immersion tutorial&lt;/b&gt;. This afternoon there is a deep dive into &lt;b&gt;Rails 3&lt;/b&gt; which I am looking forward to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have using git for a couple of months now and, while we are very confident in how we are using it, git has far more options that Subversion and I really want to understand more of the possible ways to use it.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-4930526688862727174?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/4930526688862727174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=4930526688862727174' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4930526688862727174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4930526688862727174'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/06/railsconf-baltimore.html' title='RailsConf Baltimore'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-6214101914183682556</id><published>2010-05-15T11:19:00.000-07:00</published><updated>2010-05-16T07:31:23.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'></title><content type='html'>Today I helped out at a Cambridge Rails Bugmash. Along the way I noted some changes...&lt;br /&gt;&lt;br /&gt;Within Rails the bin directory has moved from &lt;span style="font-style: italic;"&gt;vendor/rails/railties/bin/&lt;/span&gt; to &lt;span style="font-style: italic;"&gt;vendor/rails/bin&lt;/span&gt;. There are plenty of online references to the old location.&lt;br /&gt;&lt;br /&gt;I had some problems with instructions which included references to using &lt;span style="font-style: italic;"&gt;sudo&lt;/span&gt; to install gems. Since I was using &lt;span style="font-style: italic;"&gt;rvm&lt;/span&gt;, I needed to &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; use &lt;span style="font-style: italic;"&gt;sudo&lt;/span&gt; in each case.&lt;br /&gt;&lt;br /&gt;If planning to do some bug mashing on Rails I would recommend ensuring that you had Postgresql, sqlite and mysql set up correctly in advance. Also some familiarity with &lt;span style="font-style: italic;"&gt;gems&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;bundler&lt;/span&gt; will help.&lt;br /&gt;&lt;br /&gt;Craig Krigsman and Dan Pickett were there too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-6214101914183682556?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/6214101914183682556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=6214101914183682556' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6214101914183682556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6214101914183682556'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2010/05/today-i-helped-out-at-cambridge-rails.html' title=''/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-4264936403991688923</id><published>2009-12-31T23:53:00.000-08:00</published><updated>2010-01-01T00:37:43.964-08:00</updated><title type='text'>A Happy New Year</title><content type='html'>In a departure from my normal silence - a post about New Year's Eve.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Amanda Fucking Palmer&lt;/span&gt; lured William and Samantha and I to Symphony Hall in Boston for her  gig with the &lt;span style="font-weight: bold;"&gt;Boston Pops&lt;/span&gt;. Plenty of other entertainment (&lt;span style="font-weight: bold;"&gt;Sxip Shirey&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;Miss Tess and the Bon Ton Parade &lt;/span&gt;were ones I heard) before the Pops started the first half of their performance with pieces requested by AFP fans.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Imperial March, from Star Wars Episode V (Williams)&lt;/li&gt;&lt;li&gt;All That Jazz, from Chicago (Kander.Ebb-Besterman)&lt;/li&gt;&lt;li&gt;It Don't Mean a Thing (If It Ain't Got That Swing) (Ellington-Nestico)&lt;/li&gt;&lt;li&gt;Mack the Knife (Weill/Brecht-Mason)&lt;/li&gt;&lt;/ul&gt;Followed by a world premiere of a piece by &lt;span style="font-weight: bold;"&gt;Sxip Shirey&lt;/span&gt; called Melody for Lizzie. And then:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Overture from Selmasongs: Dancer in the Dark (Björk)&lt;/li&gt;&lt;/ul&gt;The world premiere of a short film by &lt;span style="font-weight: bold;"&gt;Michael Pope&lt;/span&gt; commisioned by the Pops for the event. And then:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Suite from Carmen (Bizet)&lt;/li&gt;&lt;/ul&gt;And then &lt;span style="font-weight: bold;"&gt;Neil Gaimen&lt;/span&gt;'s Statuesque - a short film created for televison in the UK - having its U.S. premiere.&lt;br /&gt;&lt;br /&gt;Last, but certainly not least was Amanda. She sang quite a few songs from her repertioire but what made it memorable was the performance. Cabaret? Burlesque in parts? Entertaining throughout. The highlight for me was the first number - 'Missed Me' - as she wound through the audience coming upon various musicians who all start hidden under large cloths and then persued her with their instruments when revealed. One of those musicians was Neil Gaiman, playing the chain saw - it was that kind of a performance - memorable.&lt;br /&gt;&lt;br /&gt;While Samantha went off to party with Michael Pope and friends and then, later, AFP and company, William and I met Valerie, Patrick Rothfuss's assistant. You may have heard of the Fabulous Lorrain or Beth of All Trades. You need to meet The Fabulous Valerie of All Trades - sweet, charming and so much fun! Clearly just what Patrick needs to become an even more efficent writing machine!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-4264936403991688923?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/4264936403991688923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=4264936403991688923' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4264936403991688923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4264936403991688923'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2009/12/happy-new-year.html' title='A Happy New Year'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-1880333124405090126</id><published>2009-02-06T08:52:00.000-08:00</published><updated>2009-02-06T09:00:23.687-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='rake'/><title type='text'>Rake and class variables</title><content type='html'>I wrote a set of &lt;span style="font-weight: bold;"&gt;Rake&lt;/span&gt; task recently. To allow them to form a basis for future expansion, I broke them down into parts and used a class variable to hold state, since I could not pass parameters between them.&lt;br /&gt;&lt;br /&gt;It appears that in moving to the version of &lt;span style="font-weight: bold;"&gt;Rake&lt;/span&gt; with &lt;span style="font-weight: bold;"&gt;Rails&lt;/span&gt; 2.1 that the global variables are lost at the end of each task.&lt;br /&gt;&lt;br /&gt;I was able to re-factor the code to use a common method for re-use. However, the re-use is limited. I can call the common method from each task. However the tasks can not depend on one another since the state cannot be persisted between them.&lt;br /&gt;&lt;br /&gt;This change made &lt;span style="font-weight: bold;"&gt;Rake&lt;/span&gt; tasks less useful - to me at least.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-1880333124405090126?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/1880333124405090126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=1880333124405090126' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1880333124405090126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1880333124405090126'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2009/02/rake-and-class-variables.html' title='Rake and class variables'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-3967177230748217293</id><published>2009-01-22T07:25:00.000-08:00</published><updated>2009-01-22T08:19:45.218-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='bleak_house'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collection'/><category scheme='http://www.blogger.com/atom/ns#' term='patch'/><title type='text'>Patching ruby 1.8.6-p287 for memory profiling</title><content type='html'>We use ruby 1.8.6. The current patch level is 287.&lt;br /&gt;&lt;br /&gt;This &lt;a href="http://blog.pluron.com/2008/02/memory-profilin.html"&gt;post&lt;/a&gt; about memory profiling claims that the ruby patch provided will apply to 1.8.6. It did not work for me - three of the changes to gc.c failed to apply. Manual editing was straightforward.&lt;br /&gt;&lt;br /&gt;This command should patch gc.c:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;patch -p0 &lt; ../ruby186gc.patch&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For lack of a better place to put it, here is the patch file (ruby186gc.patch):&lt;br /&gt;--- gc.c    2008-08-03 23:16:55.000000000 -0400&lt;br /&gt;+++ gc.c    2009-01-22 09:05:26.000000000 -0500&lt;br /&gt;@@ -22,8 +22,16 @@&lt;br /&gt; #include &lt;setjmp.h&gt;&lt;br /&gt; #include &lt;sys/types.h&gt;&lt;br /&gt;&lt;br /&gt;+#ifdef _WIN32&lt;br /&gt;+#include &lt;string.h&gt;&lt;br /&gt;+#else&lt;br /&gt;+#include &lt;strings.h&gt;&lt;br /&gt;+#endif&lt;br /&gt;+&lt;br /&gt; #ifdef HAVE_SYS_TIME_H&lt;br /&gt; #include &lt;sys/time.h&gt;&lt;br /&gt;+#elif defined(_WIN32)&lt;br /&gt;+#include &lt;time.h&gt;&lt;br /&gt; #endif&lt;br /&gt;&lt;br /&gt; #ifdef HAVE_SYS_RESOURCE_H&lt;br /&gt;@@ -40,7 +48,6 @@&lt;br /&gt; #if !defined(setjmp) &amp;amp;&amp;amp; defined(HAVE__SETJMP)&lt;br /&gt; #define setjmp(env) _setjmp(env)&lt;br /&gt; #endif&lt;br /&gt;-&lt;br /&gt; /* Make alloca work the best possible way.  */&lt;br /&gt; #ifdef __GNUC__&lt;br /&gt; # ifndef atarist&lt;br /&gt;@@ -76,6 +83,20 @@&lt;br /&gt;&lt;br /&gt; NORETURN(void rb_exc_jump _((VALUE)));&lt;br /&gt;&lt;br /&gt;+static unsigned long live_objects = 0;&lt;br /&gt;+unsigned long rb_os_live_objects()&lt;br /&gt;+{ return live_objects; }&lt;br /&gt;+&lt;br /&gt;+#if defined(HAVE_LONG_LONG)&lt;br /&gt;+static unsigned long long allocated_objects = 0;&lt;br /&gt;+unsigned long long rb_os_allocated_objects()&lt;br /&gt;+{ return allocated_objects; }&lt;br /&gt;+#else&lt;br /&gt;+static unsigned long allocated_objects = 0;&lt;br /&gt;+unsigned long rb_os_allocated_objects()&lt;br /&gt;+{ return allocated_objects; }&lt;br /&gt;+#endif&lt;br /&gt;+&lt;br /&gt; void&lt;br /&gt; rb_memerror()&lt;br /&gt; {&lt;br /&gt;@@ -93,6 +114,10 @@&lt;br /&gt;     rb_exc_raise(nomem_error);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;+long gc_allocated_size = 0;&lt;br /&gt;+long gc_num_allocations = 0;&lt;br /&gt;+static int gc_statistics = 0;&lt;br /&gt;+&lt;br /&gt; void *&lt;br /&gt; ruby_xmalloc(size)&lt;br /&gt;     long size;&lt;br /&gt;@@ -115,6 +140,11 @@&lt;br /&gt;         rb_memerror();&lt;br /&gt;     }&lt;br /&gt;     }&lt;br /&gt;+    if (gc_statistics) {&lt;br /&gt;+        gc_allocated_size += size;&lt;br /&gt;+    gc_num_allocations += 1;&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;     malloc_increase += size;&lt;br /&gt;&lt;br /&gt;     return mem;&lt;br /&gt;@@ -165,8 +195,16 @@&lt;br /&gt;     RUBY_CRITICAL(free(x));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;+#if HAVE_LONG_LONG&lt;br /&gt;+#define GC_TIME_TYPE LONG_LONG&lt;br /&gt;+#else&lt;br /&gt;+#define GC_TIME_TYPE long&lt;br /&gt;+#endif&lt;br /&gt;+&lt;br /&gt; extern int ruby_in_compile;&lt;br /&gt; static int dont_gc;&lt;br /&gt;+static GC_TIME_TYPE gc_time = 0;&lt;br /&gt;+static int gc_collections = 0;&lt;br /&gt; static int during_gc;&lt;br /&gt; static int need_call_final = 0;&lt;br /&gt; static st_table *finalizer_table = 0;&lt;br /&gt;@@ -179,7 +217,7 @@&lt;br /&gt;  *  Enables garbage collection, returning &lt;code&gt;true&lt;/code&gt; if garbage&lt;br /&gt;  *  collection was previously disabled.&lt;br /&gt;  *&lt;br /&gt;- *     GC.disable   #=&gt; false&lt;br /&gt;+ *     GC.disable   #=&gt; false or true&lt;br /&gt;  *     GC.enable    #=&gt; true&lt;br /&gt;  *     GC.enable    #=&gt; false&lt;br /&gt;  *&lt;br /&gt;@@ -215,6 +253,140 @@&lt;br /&gt;     return old;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.enable_stats    =&gt; true or false&lt;br /&gt;+ *&lt;br /&gt;+ *  Enables garbage collection statistics, returning &lt;code&gt;true&lt;/code&gt; if garbage&lt;br /&gt;+ *  collection statistics was already enabled.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.enable_stats   #=&gt; false or true&lt;br /&gt;+ *     GC.enable_stats   #=&gt; true&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_enable_stats()&lt;br /&gt;+{&lt;br /&gt;+    int old = gc_statistics;&lt;br /&gt;+    gc_statistics = Qtrue;&lt;br /&gt;+    return old;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.disable_stats    =&gt; true or false&lt;br /&gt;+ *&lt;br /&gt;+ *  Disables garbage collection statistics, returning &lt;code&gt;true&lt;/code&gt; if garbage&lt;br /&gt;+ *  collection statistics was already disabled.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.disable_stats   #=&gt; false or true&lt;br /&gt;+ *     GC.disable_stats   #=&gt; true&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_disable_stats()&lt;br /&gt;+{&lt;br /&gt;+    int old = gc_statistics;&lt;br /&gt;+    gc_statistics = Qfalse;&lt;br /&gt;+    gc_allocated_size = 0;&lt;br /&gt;+    gc_num_allocations = 0;&lt;br /&gt;+    return old;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.clear_stats    =&gt; nil&lt;br /&gt;+ *&lt;br /&gt;+ *  Clears garbage collection statistics, returning nil. This resets the number&lt;br /&gt;+ *  of collections (GC.collections) and the time used (GC.time) to 0.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.clear_stats    #=&gt; nil&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_clear_stats()&lt;br /&gt;+{&lt;br /&gt;+    gc_collections = 0;&lt;br /&gt;+    gc_time = 0;&lt;br /&gt;+    gc_allocated_size = 0;&lt;br /&gt;+    gc_num_allocations = 0;&lt;br /&gt;+    return Qnil;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.allocated_size    =&gt; Integer&lt;br /&gt;+ *&lt;br /&gt;+ *  Returns the size of memory (in bytes) allocated since GC statistics collection&lt;br /&gt;+ *  was enabled.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.allocated_size    #=&gt; 35&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_allocated_size()&lt;br /&gt;+{&lt;br /&gt;+    return INT2NUM(gc_allocated_size);&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.num_allocations    =&gt; Integer&lt;br /&gt;+ *&lt;br /&gt;+ *  Returns the number of memory allocations since GC statistics collection&lt;br /&gt;+ *  was enabled.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.num_allocations    #=&gt; 150&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_num_allocations()&lt;br /&gt;+{&lt;br /&gt;+    return INT2NUM(gc_num_allocations);&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.collections    =&gt; Integer&lt;br /&gt;+ *&lt;br /&gt;+ *  Returns the number of garbage collections performed while GC statistics collection&lt;br /&gt;+ *  was enabled.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.collections    #=&gt; 35&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_collections()&lt;br /&gt;+{&lt;br /&gt;+    return INT2NUM(gc_collections);&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.time    =&gt; Integer&lt;br /&gt;+ *&lt;br /&gt;+ *  Returns the time spent during garbage collection while GC statistics collection&lt;br /&gt;+ *  was enabled (in micro seconds).&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.time    #=&gt; 20000&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_time()&lt;br /&gt;+{&lt;br /&gt;+#if HAVE_LONG_LONG&lt;br /&gt;+    return LL2NUM(gc_time);&lt;br /&gt;+#else&lt;br /&gt;+    return LONG2NUM(gc_time);&lt;br /&gt;+#endif&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+&lt;br /&gt; VALUE rb_mGC;&lt;br /&gt;&lt;br /&gt; static struct gc_list {&lt;br /&gt;@@ -306,7 +478,7 @@&lt;br /&gt; static RVALUE *freelist = 0;&lt;br /&gt; static RVALUE *deferred_final_list = 0;&lt;br /&gt;&lt;br /&gt;-#define HEAPS_INCREMENT 10&lt;br /&gt;+static int heaps_increment = 10;&lt;br /&gt; static struct heaps_slot {&lt;br /&gt;     void *membase;&lt;br /&gt;     RVALUE *slot;&lt;br /&gt;@@ -315,13 +487,165 @@&lt;br /&gt; static int heaps_length = 0;&lt;br /&gt; static int heaps_used   = 0;&lt;br /&gt;&lt;br /&gt;-#define HEAP_MIN_SLOTS 10000&lt;br /&gt;-static int heap_slots = HEAP_MIN_SLOTS;&lt;br /&gt;+static int heap_min_slots = 10000;&lt;br /&gt;+static int heap_slots = 10000;&lt;br /&gt;+&lt;br /&gt;+static int heap_free_min = 4096;&lt;br /&gt;+static int heap_slots_increment = 10000;&lt;br /&gt;+static double heap_slots_growth_factor = 1.8;&lt;br /&gt;&lt;br /&gt;-#define FREE_MIN  4096&lt;br /&gt;+static long initial_malloc_limit = GC_MALLOC_LIMIT;&lt;br /&gt;+&lt;br /&gt;+static int verbose_gc_stats = Qfalse;&lt;br /&gt;+&lt;br /&gt;+static FILE* gc_data_file = NULL;&lt;br /&gt;&lt;br /&gt; static RVALUE *himem, *lomem;&lt;br /&gt;&lt;br /&gt;+static void set_gc_parameters()&lt;br /&gt;+{&lt;br /&gt;+    char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr,&lt;br /&gt;+      *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr;&lt;br /&gt;+&lt;br /&gt;+    gc_data_file = stderr;&lt;br /&gt;+&lt;br /&gt;+    gc_stats_ptr = getenv("RUBY_GC_STATS");&lt;br /&gt;+    if (gc_stats_ptr != NULL) {&lt;br /&gt;+    int gc_stats_i = atoi(gc_stats_ptr);&lt;br /&gt;+    if (gc_stats_i &gt; 0) {&lt;br /&gt;+        verbose_gc_stats = Qtrue;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE");&lt;br /&gt;+    if (gc_heap_file_ptr != NULL) {&lt;br /&gt;+    FILE* data_file = fopen(gc_heap_file_ptr, "w");&lt;br /&gt;+    if (data_file != NULL) {&lt;br /&gt;+        gc_data_file = data_file;&lt;br /&gt;+    }&lt;br /&gt;+    else {&lt;br /&gt;+        fprintf(stderr,&lt;br /&gt;+            "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");&lt;br /&gt;+    if (min_slots_ptr != NULL) {&lt;br /&gt;+    int min_slots_i = atoi(min_slots_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr);&lt;br /&gt;+        }&lt;br /&gt;+    if (min_slots_i &gt; 0) {&lt;br /&gt;+        heap_slots = min_slots_i;&lt;br /&gt;+        heap_min_slots = min_slots_i;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    free_min_ptr = getenv("RUBY_HEAP_FREE_MIN");&lt;br /&gt;+    if (free_min_ptr != NULL) {&lt;br /&gt;+    int free_min_i = atoi(free_min_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    if (free_min_i &gt; 0) {&lt;br /&gt;+        heap_free_min = free_min_i;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT");&lt;br /&gt;+    if (heap_incr_ptr != NULL) {&lt;br /&gt;+    int heap_incr_i = atoi(heap_incr_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    if (heap_incr_i &gt; 0) {&lt;br /&gt;+        heaps_increment = heap_incr_i;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT");&lt;br /&gt;+    if (heap_slots_incr_ptr != NULL) {&lt;br /&gt;+    int heap_slots_incr_i = atoi(heap_slots_incr_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    if (heap_slots_incr_i &gt; 0) {&lt;br /&gt;+        heap_slots_increment = heap_slots_incr_i;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR");&lt;br /&gt;+    if (heap_slots_growth_factor_ptr != NULL) {&lt;br /&gt;+    double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    if (heap_slots_growth_factor_d &gt; 0) {&lt;br /&gt;+        heap_slots_growth_factor = heap_slots_growth_factor_d;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");&lt;br /&gt;+    if (malloc_limit_ptr != NULL) {&lt;br /&gt;+    int malloc_limit_i = atol(malloc_limit_ptr);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr);&lt;br /&gt;+    }&lt;br /&gt;+    if (malloc_limit_i &gt; 0) {&lt;br /&gt;+        initial_malloc_limit = malloc_limit_i;&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.dump    =&gt; nil&lt;br /&gt;+ *&lt;br /&gt;+ *  dumps information about the current GC data structures to the GC log file&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.dump    #=&gt; nil&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_dump()&lt;br /&gt;+{&lt;br /&gt;+    int i;&lt;br /&gt;+&lt;br /&gt;+    for (i = 0; i &lt; heaps_used; i++) {&lt;br /&gt;+    int heap_size = heaps[i].limit;&lt;br /&gt;+    fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size);&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;+    return Qnil;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+/*&lt;br /&gt;+ *  call-seq:&lt;br /&gt;+ *     GC.log String  =&gt; String&lt;br /&gt;+ *&lt;br /&gt;+ *  Logs string to the GC data file and returns it.&lt;br /&gt;+ *&lt;br /&gt;+ *     GC.log "manual GC call"    #=&gt; "manual GC call"&lt;br /&gt;+ *&lt;br /&gt;+ */&lt;br /&gt;+&lt;br /&gt;+VALUE&lt;br /&gt;+rb_gc_log(self, original_str)&lt;br /&gt;+     VALUE self, original_str;&lt;br /&gt;+{&lt;br /&gt;+    if (original_str == Qnil) {&lt;br /&gt;+        fprintf(gc_data_file, "\n");&lt;br /&gt;+    }&lt;br /&gt;+    else {&lt;br /&gt;+        VALUE str = StringValue(original_str);&lt;br /&gt;+        char *p = RSTRING(str)-&gt;ptr;&lt;br /&gt;+        fprintf(gc_data_file, "%s\n", p);&lt;br /&gt;+    }&lt;br /&gt;+    return original_str;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+&lt;br /&gt; static void&lt;br /&gt; add_heap()&lt;br /&gt; {&lt;br /&gt;@@ -332,7 +656,7 @@&lt;br /&gt;     struct heaps_slot *p;&lt;br /&gt;     int length;&lt;br /&gt;&lt;br /&gt;-    heaps_length += HEAPS_INCREMENT;&lt;br /&gt;+    heaps_length += heaps_increment;&lt;br /&gt;     length = heaps_length*sizeof(struct heaps_slot);&lt;br /&gt;     RUBY_CRITICAL(&lt;br /&gt;         if (heaps_used &gt; 0) {&lt;br /&gt;@@ -348,10 +672,10 @@&lt;br /&gt;     for (;;) {&lt;br /&gt;     RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1)));&lt;br /&gt;     if (p == 0) {&lt;br /&gt;-        if (heap_slots == HEAP_MIN_SLOTS) {&lt;br /&gt;+        if (heap_slots == heap_min_slots) {&lt;br /&gt;         rb_memerror();&lt;br /&gt;         }&lt;br /&gt;-        heap_slots = HEAP_MIN_SLOTS;&lt;br /&gt;+        heap_slots = heap_min_slots;&lt;br /&gt;         continue;&lt;br /&gt;     }&lt;br /&gt;         heaps[heaps_used].membase = p;&lt;br /&gt;@@ -367,8 +691,9 @@&lt;br /&gt;     if (lomem == 0 || lomem &gt; p) lomem = p;&lt;br /&gt;     if (himem &lt; pend) himem = pend;&lt;br /&gt;     heaps_used++;&lt;br /&gt;-    heap_slots *= 1.8;&lt;br /&gt;-    if (heap_slots &lt;= 0) heap_slots = HEAP_MIN_SLOTS;&lt;br /&gt;+    heap_slots += heap_slots_increment;&lt;br /&gt;+    heap_slots_increment *= heap_slots_growth_factor;&lt;br /&gt;+    if (heap_slots &lt;= 0) heap_slots = heap_min_slots;&lt;br /&gt;&lt;br /&gt;     while (p &lt; pend) {&lt;br /&gt;     p-&gt;as.free.flags = 0;&lt;br /&gt;@@ -402,6 +727,8 @@&lt;br /&gt;     RANY(obj)-&gt;file = ruby_sourcefile;&lt;br /&gt;     RANY(obj)-&gt;line = ruby_sourceline;&lt;br /&gt; #endif&lt;br /&gt;+    live_objects++;&lt;br /&gt;+    allocated_objects++;&lt;br /&gt;     return obj;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;@@ -1030,6 +1357,39 @@&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;+static char* obj_type(int tp)&lt;br /&gt;+{&lt;br /&gt;+    switch (tp) {&lt;br /&gt;+    case T_NIL    : return "NIL";  &lt;br /&gt;+    case T_OBJECT : return "OBJECT";&lt;br /&gt;+    case T_CLASS  : return "CLASS";&lt;br /&gt;+    case T_ICLASS : return "ICLASS";&lt;br /&gt;+    case T_MODULE : return "MODULE";&lt;br /&gt;+    case T_FLOAT  : return "FLOAT";&lt;br /&gt;+    case T_STRING : return "STRING";&lt;br /&gt;+    case T_REGEXP : return "REGEXP";&lt;br /&gt;+    case T_ARRAY  : return "ARRAY";&lt;br /&gt;+    case T_FIXNUM : return "FIXNUM";&lt;br /&gt;+    case T_HASH   : return "HASH";&lt;br /&gt;+    case T_STRUCT : return "STRUCT";&lt;br /&gt;+    case T_BIGNUM : return "BIGNUM";&lt;br /&gt;+    case T_FILE   : return "FILE";&lt;br /&gt;+       &lt;br /&gt;+    case T_TRUE   : return "TRUE";&lt;br /&gt;+    case T_FALSE  : return "FALSE";&lt;br /&gt;+    case T_DATA   : return "DATA";&lt;br /&gt;+    case T_MATCH  : return "MATCH";&lt;br /&gt;+    case T_SYMBOL : return "SYMBOL";&lt;br /&gt;+       &lt;br /&gt;+    case T_BLKTAG : return "BLKTAG";&lt;br /&gt;+    case T_UNDEF  : return "UNDEF";&lt;br /&gt;+    case T_VARMAP : return "VARMAP";&lt;br /&gt;+    case T_SCOPE  : return "SCOPE";&lt;br /&gt;+    case T_NODE   : return "NODE";&lt;br /&gt;+    default: return "____";&lt;br /&gt;+    }&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt; static void&lt;br /&gt; free_unused_heaps()&lt;br /&gt; {&lt;br /&gt;@@ -1059,13 +1419,23 @@&lt;br /&gt;     int i;&lt;br /&gt;     unsigned long live = 0;&lt;br /&gt;     unsigned long free_min = 0;&lt;br /&gt;+    live_objects = 0;&lt;br /&gt;+&lt;br /&gt;+    unsigned long really_freed = 0;&lt;br /&gt;+    int free_counts[256];&lt;br /&gt;+    int live_counts[256];&lt;br /&gt;+    int do_gc_stats = gc_statistics &amp;amp; verbose_gc_stats;&lt;br /&gt;&lt;br /&gt;     for (i = 0; i &lt; heaps_used; i++) {&lt;br /&gt;         free_min += heaps[i].limit;&lt;br /&gt;     }&lt;br /&gt;     free_min = free_min * 0.2;&lt;br /&gt;-    if (free_min &lt; FREE_MIN)&lt;br /&gt;-        free_min = FREE_MIN;&lt;br /&gt;+    if (free_min &lt; heap_free_min)&lt;br /&gt;+        free_min = heap_free_min;&lt;br /&gt;+&lt;br /&gt;+    if (do_gc_stats) {&lt;br /&gt;+    for (i = 0 ; i&lt; 256; i++) { free_counts[i] = live_counts[i] = 0; }&lt;br /&gt;+    }&lt;br /&gt;&lt;br /&gt;     if (ruby_in_compile &amp;amp;&amp;amp; ruby_parser_stack_on_heap()) {&lt;br /&gt;     /* should not reclaim nodes during compilation&lt;br /&gt;@@ -1098,6 +1468,9 @@&lt;br /&gt;         if (!(p-&gt;as.basic.flags &amp;amp; FL_MARK)) {&lt;br /&gt;         if (p-&gt;as.basic.flags) {&lt;br /&gt;             obj_free((VALUE)p);&lt;br /&gt;+            if (do_gc_stats) {&lt;br /&gt;+            really_freed++;&lt;br /&gt;+            }&lt;br /&gt;         }&lt;br /&gt;         if (need_call_final &amp;amp;&amp;amp; FL_TEST(p, FL_FINALIZE)) {&lt;br /&gt;             p-&gt;as.free.flags = FL_MARK; /* remain marked */&lt;br /&gt;@@ -1105,6 +1478,12 @@&lt;br /&gt;             final_list = p;&lt;br /&gt;         }&lt;br /&gt;         else {&lt;br /&gt;+            if (do_gc_stats) {&lt;br /&gt;+            int obt = p-&gt;as.basic.flags &amp;amp; T_MASK;&lt;br /&gt;+            if (obt) {&lt;br /&gt;+                free_counts[obt]++;&lt;br /&gt;+            }&lt;br /&gt;+            }&lt;br /&gt;             p-&gt;as.free.flags = 0;&lt;br /&gt;             p-&gt;as.free.next = freelist;&lt;br /&gt;             freelist = p;&lt;br /&gt;@@ -1117,7 +1496,10 @@&lt;br /&gt;         }&lt;br /&gt;         else {&lt;br /&gt;         RBASIC(p)-&gt;flags &amp;amp;= ~FL_MARK;&lt;br /&gt;-        live++;&lt;br /&gt;+        live_objects++;&lt;br /&gt;+        if (do_gc_stats) {&lt;br /&gt;+             live_counts[RANY((VALUE)p)-&gt;as.basic.flags &amp;amp; T_MASK]++;&lt;br /&gt;+         }&lt;br /&gt;         }&lt;br /&gt;         p++;&lt;br /&gt;     }&lt;br /&gt;@@ -1135,8 +1517,8 @@&lt;br /&gt;     }&lt;br /&gt;     }&lt;br /&gt;     if (malloc_increase &gt; malloc_limit) {&lt;br /&gt;-    malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);&lt;br /&gt;-    if (malloc_limit &lt; GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;&lt;br /&gt;+    malloc_limit += (malloc_increase - malloc_limit) * (double)live_objects / (live_objects + freed);&lt;br /&gt;+    if (malloc_limit &lt; initial_malloc_limit) malloc_limit = initial_malloc_limit;&lt;br /&gt;     }&lt;br /&gt;     malloc_increase = 0;&lt;br /&gt;     if (freed &lt; free_min) {&lt;br /&gt;@@ -1144,6 +1526,20 @@&lt;br /&gt;     }&lt;br /&gt;     during_gc = 0;&lt;br /&gt;&lt;br /&gt;+    if (do_gc_stats) {&lt;br /&gt;+    fprintf(gc_data_file, "objects processed: %.7d\n", live+freed);&lt;br /&gt;+    fprintf(gc_data_file, "live objects    : %.7d\n", live);&lt;br /&gt;+    fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed);&lt;br /&gt;+    fprintf(gc_data_file, "freed objects    : %.7d\n", really_freed);&lt;br /&gt;+    for(i=0; i&lt;256; i++) {&lt;br /&gt;+        if (free_counts[i]&gt;0) {&lt;br /&gt;+        fprintf(gc_data_file,&lt;br /&gt;+            "kept %.7d / freed %.7d objects of type %s\n",&lt;br /&gt;+            live_counts[i], free_counts[i], obj_type(i));&lt;br /&gt;+        }&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;     /* clear finalization list */&lt;br /&gt;     if (final_list) {&lt;br /&gt;     deferred_final_list = final_list;&lt;br /&gt;@@ -1338,6 +1734,7 @@&lt;br /&gt;     struct gc_list *list;&lt;br /&gt;     struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */&lt;br /&gt;     jmp_buf save_regs_gc_mark;&lt;br /&gt;+    struct timeval gctv1, gctv2;&lt;br /&gt;     SET_STACK_END;&lt;br /&gt;&lt;br /&gt; #ifdef HAVE_NATIVETHREAD&lt;br /&gt;@@ -1354,6 +1751,14 @@&lt;br /&gt;     if (during_gc) return;&lt;br /&gt;     during_gc++;&lt;br /&gt;&lt;br /&gt;+    if (gc_statistics) {&lt;br /&gt;+        gc_collections++;&lt;br /&gt;+    gettimeofday(&amp;amp;gctv1, NULL);&lt;br /&gt;+        if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "Garbage collection started\n");&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt;+&lt;br /&gt;     init_mark_stack();&lt;br /&gt;&lt;br /&gt;     gc_mark((VALUE)ruby_current_node, 0);&lt;br /&gt;@@ -1429,6 +1834,17 @@&lt;br /&gt;     } while (!MARK_STACK_EMPTY);&lt;br /&gt;&lt;br /&gt;     gc_sweep();&lt;br /&gt;+&lt;br /&gt;+    if (gc_statistics) {&lt;br /&gt;+        GC_TIME_TYPE musecs_used;&lt;br /&gt;+    gettimeofday(&amp;amp;gctv2, NULL);&lt;br /&gt;+    musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec);&lt;br /&gt;+    gc_time += musecs_used;&lt;br /&gt;+&lt;br /&gt;+    if (verbose_gc_stats) {&lt;br /&gt;+        fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000);&lt;br /&gt;+    }&lt;br /&gt;+    }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; void&lt;br /&gt;@@ -1610,6 +2026,7 @@&lt;br /&gt;     if (!rb_gc_stack_start) {&lt;br /&gt;     Init_stack(0);&lt;br /&gt;     }&lt;br /&gt;+    set_gc_parameters();&lt;br /&gt;     add_heap();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;@@ -2031,6 +2448,35 @@&lt;br /&gt;     return (VALUE)((long)obj|FIXNUM_FLAG);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;+/* call-seq:&lt;br /&gt;+ *  ObjectSpace.live_objects =&gt; number&lt;br /&gt;+ *&lt;br /&gt;+ * Returns the count of objects currently allocated in the system. This goes&lt;br /&gt;+ * down after the garbage collector runs.&lt;br /&gt;+ */&lt;br /&gt;+static&lt;br /&gt;+VALUE os_live_objects(VALUE self)&lt;br /&gt;+{ return ULONG2NUM(live_objects); }&lt;br /&gt;+&lt;br /&gt;+/* call-seq:&lt;br /&gt;+ *  ObjectSpace.allocated_objects =&gt; number&lt;br /&gt;+ *&lt;br /&gt;+ * Returns the count of objects allocated since the Ruby interpreter has&lt;br /&gt;+ * started.  This number can only increase. To know how many objects are&lt;br /&gt;+ * currently allocated, use ObjectSpace::live_objects&lt;br /&gt;+ */&lt;br /&gt;+static&lt;br /&gt;+VALUE os_allocated_objects(VALUE self)&lt;br /&gt;+{&lt;br /&gt;+#if defined(HAVE_LONG_LONG)&lt;br /&gt;+    return ULL2NUM(allocated_objects);&lt;br /&gt;+#else&lt;br /&gt;+    return ULONG2NUM(allocated_objects);&lt;br /&gt;+#endif&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt;+&lt;br /&gt;+&lt;br /&gt; /*&lt;br /&gt;  *  The &lt;code&gt;GC&lt;/code&gt; module provides an interface to Ruby's mark and&lt;br /&gt;  *  sweep garbage collection mechanism. Some of the underlying methods&lt;br /&gt;@@ -2048,6 +2494,16 @@&lt;br /&gt;     rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);&lt;br /&gt;     rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);&lt;br /&gt;&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0);&lt;br /&gt;+    rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1);&lt;br /&gt;+&lt;br /&gt;     rb_mObSpace = rb_define_module("ObjectSpace");&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);&lt;br /&gt;@@ -2055,6 +2511,8 @@&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "finalizers", finals, 0);&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);&lt;br /&gt;+    rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0);&lt;br /&gt;+    rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0);&lt;br /&gt;&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);&lt;br /&gt;     rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-3967177230748217293?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/3967177230748217293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=3967177230748217293' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/3967177230748217293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/3967177230748217293'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2009/01/patching-ruby-186-p287-for-memory.html' title='Patching ruby 1.8.6-p287 for memory profiling'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-6735111258442093792</id><published>2009-01-13T17:02:00.000-08:00</published><updated>2009-01-22T07:25:01.506-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='bleak_house'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>BleakHouse - memory leaks</title><content type='html'>As of writing the current version of &lt;span style="font-style: italic;"&gt;BleakHouse&lt;/span&gt; is 4.1.1.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;BleakHouse&lt;/span&gt; patches &lt;span style="font-style: italic;"&gt;ruby&lt;/span&gt; to insert the memory monitoring code. Version 4.1.1 bundles &lt;span style="font-style: italic;"&gt;ruby&lt;/span&gt; 1.8.6 patch level 230. Unfortunately, attempting to install the gem fails because of a patch failure. Fixing the patching problem leads to double-deallocation and other problems at run-time.&lt;br /&gt;&lt;br /&gt;We applied the patches to ruby 1.8.6 patch level 114. The &lt;span style="font-style: italic;"&gt;BleakHouse&lt;/span&gt; patches change the patchlevel in the version number to be 901.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-6735111258442093792?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/6735111258442093792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=6735111258442093792' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6735111258442093792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6735111258442093792'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2009/01/bleakhouse-memory-leaks.html' title='BleakHouse - memory leaks'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-1371454472272307937</id><published>2008-12-10T10:05:00.000-08:00</published><updated>2008-12-10T10:21:22.545-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='quote'/><category scheme='http://www.blogger.com/atom/ns#' term='acts_as_paranoid'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Quote from acts_as_paranoid not found</title><content type='html'>We have been using the &lt;span style="font-style: italic;"&gt;acts_as_paranoid&lt;/span&gt; plugin and our move to &lt;span style="font-weight: bold;"&gt;Rails 2.1&lt;/span&gt; (eventually) woke us up to the need to update it.&lt;br /&gt;&lt;br /&gt;In case anyone else should wonder why calling delete on their &lt;span style="font-style: italic;"&gt;ActiveRecord&lt;/span&gt; model instance - which uses &lt;span style="font-style: italic;"&gt;acts_as_paranoid&lt;/span&gt; - caused a &lt;span style="font-style: italic;"&gt;NoMethodFound&lt;/span&gt; error on '&lt;span style="font-weight: bold;"&gt;quote&lt;/span&gt;', it is because your PostGres (or possibly other) database adapter no longer has such a method - although it used to.&lt;br /&gt;&lt;br /&gt;The latest version of the plugin fixes the problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-1371454472272307937?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/1371454472272307937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=1371454472272307937' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1371454472272307937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1371454472272307937'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/12/quote-from-actsasparanoid-not-found.html' title='Quote from acts_as_paranoid not found'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-5740292925638290485</id><published>2008-11-17T18:07:00.000-08:00</published><updated>2008-11-17T18:13:45.256-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='login'/><category scheme='http://www.blogger.com/atom/ns#' term='DotNetOpenID'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenID'/><title type='text'>OpenID</title><content type='html'>We see real value to our company in supporting &lt;span style="font-weight: bold;"&gt;OpenID&lt;/span&gt; for our users. Implementation of support as a Relying Party has proved straightforward - thanks to &lt;span style="font-weight: bold;"&gt;DotNetOpenID&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;By supporting registration, as well as login, using &lt;span style="font-weight: bold;"&gt;OpenID&lt;/span&gt; (and only &lt;span style="font-weight: bold;"&gt;OpenID&lt;/span&gt;), we have moved from a typical registration page with many fields to a trivial one. We do have special needs that made this easier but when we realized the simplification this would allow our code and our users we quickly convinced ourselves.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-5740292925638290485?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/5740292925638290485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=5740292925638290485' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5740292925638290485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5740292925638290485'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/11/openid.html' title='OpenID'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-4781522444168598760</id><published>2008-11-17T17:56:00.000-08:00</published><updated>2008-11-17T18:06:50.624-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Intrepid Ibex'/><category scheme='http://www.blogger.com/atom/ns#' term='MythTV'/><category scheme='http://www.blogger.com/atom/ns#' term='lirc'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>MythTV under Ubuntu Intrepid Ibex</title><content type='html'>We have two interesting issues since Intrepid Ibex was released. My updates were tied to the development version but I believe these were observed after the release was final:&lt;br /&gt;&lt;br /&gt;MythTV playback sound is higher-pitched in almost every case whether recorded months ago or hours ago. So does live TV.&lt;br /&gt;&lt;br /&gt;Lirc was failing to run because it did not see the right lirc device. A soft link in /dev fixed that.&lt;br /&gt;&lt;br /&gt;Unrelated to Ubuntu, our remote that came with the multimedia PC case is very flaky with the left and down directions on the keypad. It allows far more than the four compass points. It is possible to recognize the other remote signals but tricky to get the right responsiveness - recognizing all of them produces far too many key presses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-4781522444168598760?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/4781522444168598760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=4781522444168598760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4781522444168598760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4781522444168598760'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/11/mythtv-under-ubuntu-intrepid-ibex.html' title='MythTV under Ubuntu Intrepid Ibex'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-3372838028694622900</id><published>2008-08-25T12:32:00.000-07:00</published><updated>2008-08-25T21:03:13.246-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='imon'/><category scheme='http://www.blogger.com/atom/ns#' term='LCDproc'/><category scheme='http://www.blogger.com/atom/ns#' term='MythTV'/><category scheme='http://www.blogger.com/atom/ns#' term='lirc'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>lirc and imon LCD under Ubuntu</title><content type='html'>If you have a &lt;span style="font-weight: bold;"&gt;MythTV&lt;/span&gt; installation you will want to control it via a remote control since keyboards and mice rarely fit the decor of a family room.&lt;br /&gt;&lt;br /&gt;I chose a Silverstone case with their nice LCD display. It has a potentially rich display. However such sophistication is not supported by the &lt;span style="font-weight: bold;"&gt;Ubuntu Hardy&lt;/span&gt; &lt;span style="font-style: italic;"&gt;LCDproc&lt;/span&gt; package.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight: bold;"&gt;Ubuntu 8.04&lt;/span&gt; &lt;span style="font-style: italic;"&gt;lirc&lt;/span&gt; support for the pad on the remote is incomplete also. There is a patch which is targeted for &lt;span style="font-weight: bold;"&gt;Intrepid Ibex&lt;/span&gt;. So I could build from source, add the patch and install. Or I could fetch the &lt;span style="font-weight: bold;"&gt;Intrepid&lt;/span&gt; package and install that. The latter seemed the simpler case but, since it is aiming to be part of &lt;span style="font-weight: bold;"&gt;Intrepid&lt;/span&gt;, its dependencies could be a problem.&lt;br /&gt;&lt;br /&gt;Using &lt;span style="font-weight: bold;"&gt;Intrepid&lt;/span&gt;'s package as a base fails interacting with &lt;span style="font-style: italic;"&gt;udev&lt;/span&gt; each time. I suspect that the direct cause is the lack of the &lt;span style="font-style: italic;"&gt;lirc_imon&lt;/span&gt; driver despite a reference to it in &lt;span style="font-style: italic;"&gt;hardware.conf&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;dkms&lt;/span&gt; is used to manage the &lt;span style="font-style: italic;"&gt;lirc&lt;/span&gt; support. Unfortunately it believes I have an empty &lt;span style="font-style: italic;"&gt;dkms.conf&lt;/span&gt; which is causing all the &lt;span style="font-style: italic;"&gt;dkms&lt;/span&gt; commands to fail.&lt;br /&gt;&lt;br /&gt;I commented out the reference to the missing &lt;span style="font-style: italic;"&gt;lirc_imon&lt;/span&gt; driver and rebooted to see if the poor interaction with &lt;span style="font-style: italic;"&gt;udev&lt;/span&gt; as fixed.&lt;br /&gt;&lt;br /&gt;Rebooting brought up a repair menu, so I chose the option to repair packages. Since I have &lt;span style="font-weight: bold;"&gt;Intrepid&lt;/span&gt; in my &lt;span style="font-style: italic;"&gt;sources.list&lt;/span&gt; file, it is now downloading 100s of megabytes of updated and new packages for &lt;span style="font-weight: bold;"&gt;Intrepid alpha 4&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This may take a while to finish... The only upside I can see so far is the chance to become an &lt;span style="font-weight: bold;"&gt;Ubuntu&lt;/span&gt; package maintainer...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-3372838028694622900?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/3372838028694622900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=3372838028694622900' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/3372838028694622900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/3372838028694622900'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/08/lirc-and-imon-lcd-under-ubuntu.html' title='lirc and imon LCD under Ubuntu'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-8321813601380797221</id><published>2008-06-24T12:35:00.000-07:00</published><updated>2008-06-25T10:23:28.730-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NFS'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='nfs-kernel-server'/><category scheme='http://www.blogger.com/atom/ns#' term='nfs-user-server'/><title type='text'>Mounting NFS shares on OS X Leopard</title><content type='html'>A lot of the information about doing this on Mac OS X refers to the &lt;span style="font-weight:bold;"&gt;NetInfo&lt;/span&gt; database and related utilities, but pre-dates changes which came with &lt;span style="font-weight:bold;"&gt;Leopard&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;On &lt;span style="font-weight:bold;"&gt;Debian&lt;/span&gt; - &lt;span style="font-weight:bold;"&gt;Ubuntu&lt;/span&gt; in my case - most of the information refers to &lt;span style="font-weight:bold;"&gt;nfs-kernel-server&lt;/span&gt; for &lt;span style="font-weight:bold;"&gt;NFS&lt;/span&gt;. Unforntunately nfs-kernel-server requires the uid and gid to be the same on both server and client in the general case. While there is information on how to change your OS X uid/gid it is a pain in the neck and gets worse with more systems.&lt;br /&gt;&lt;br /&gt;The best resource I found to address these issues securely is on the &lt;a href="http://ubuntuforums.org/showthread.php?p=4387032#post4387032"&gt;Ubuntu forums&lt;/a&gt; written by &lt;span style="font-style:italic;"&gt;Eiríkr&lt;/span&gt;, and uses &lt;span style="font-weight:bold;"&gt;nfs-user-server&lt;/span&gt; to map between the client and server uids and gids - instead of &lt;span style="font-weight:bold;"&gt;nfs-kernel-server&lt;/span&gt;. Install &lt;span style="font-weight:bold;"&gt;nfs-user-server&lt;/span&gt; using your favorite package manager and configure it according to Eirikr.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-8321813601380797221?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/8321813601380797221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=8321813601380797221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8321813601380797221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8321813601380797221'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/06/mounting-nfs-shares-on-os-x-leopard.html' title='Mounting NFS shares on OS X Leopard'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-8449724879928586977</id><published>2008-06-21T08:12:00.000-07:00</published><updated>2008-06-25T10:21:03.811-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pro'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='mini'/><category scheme='http://www.blogger.com/atom/ns#' term='TextMate'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>The Mac mini</title><content type='html'>My windows laptop is on it's last legs. I need a machine for development and I loved the &lt;span style="font-weight:bold;"&gt;MacBook Pro&lt;/span&gt; I chose for development at Jackpot Rewards. The only problem I have with the Pro is it's price - it is a premium-priced product.&lt;br /&gt;&lt;br /&gt;I have a great 24" monitor on my desk at home and plenty of keyboards and mice. Having a very portable machine is not very important right now. These factors led me to the &lt;span style="font-weight:bold;"&gt;Mac mini&lt;/span&gt;. My current work from home is using &lt;span style="font-weight:bold;"&gt;Ruby on Rails&lt;/span&gt; and my development environment is centered on &lt;span style="font-weight:bold;"&gt;TextMate&lt;/span&gt; so my performance requirements are quite low.&lt;br /&gt;&lt;br /&gt;Sure, I would have loved to buy a &lt;span style="font-weight:bold;"&gt;Mac Pro&lt;/span&gt; but the price difference is huge for the extra capabilities. If we get to the point of running an office with a few people I will definitely consider it.&lt;br /&gt;&lt;br /&gt;I will write again when i have spent more time using it as a personal system and a development system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-8449724879928586977?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/8449724879928586977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=8449724879928586977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8449724879928586977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8449724879928586977'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/06/mac-mini.html' title='The Mac mini'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-6388903672461112749</id><published>2008-06-03T13:21:00.000-07:00</published><updated>2008-06-03T13:42:59.088-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrick Rothfuss'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>"The Name of the Wind" by Patrick Rothfuss</title><content type='html'>I love the Fantasy genre and this book is is one of the best. A great story with well-interleaved flashbacks and great prose.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;It was one of those perfect autumn days so common in stories and so rare in the real world. The weather was warm and dry, ideal for ripening a field of wheat or corn. On both sides of the road the trees were changing color. Tall poplars had gone a buttery yellow while the shrubby sumac encroaching on the read was tinged a violent red. Only the old oaks seemed reluctant to give up the summer, and their leaves remained an even mingling of gold and green.&lt;br /&gt;&lt;br /&gt;Everything said, you couldn't hope for a nicer day to have a half dozen ex-soldiers with hunting bows relieve you of everything you owned.&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The humorous style of writing made it a joy to read. I picked that passage at random - it is the start of the second chapter - but it is typical of the whole. Just reading that passage again makes me want to re-read the whole book. The characters are well-developed and this, the first of three books, finished much too soon (662 pages).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-6388903672461112749?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/6388903672461112749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=6388903672461112749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6388903672461112749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/6388903672461112749'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/06/name-of-wind-by-patrick-rothfuss.html' title='&quot;The Name of the Wind&quot; by Patrick Rothfuss'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-5342928887668773103</id><published>2008-05-09T11:28:00.000-07:00</published><updated>2008-05-10T18:11:26.097-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cory Doctorow'/><category scheme='http://www.blogger.com/atom/ns#' term='Neil Gaiman'/><category scheme='http://www.blogger.com/atom/ns#' term='Little Brother'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Little Brother by Cory Doctorow</title><content type='html'>I was going to write a review of the book but a quick Google gave me &lt;span style="font-style:italic;"&gt;Neil Gaiman's&lt;/span&gt; &lt;a href="http://journal.neilgaiman.com/2007/12/changing-planes.html"&gt;review&lt;/a&gt; from six months ago. I had read his review but did not try the book because work was just too time-consuming then.&lt;br /&gt;&lt;br /&gt;Neil's more recent &lt;a href="http://journal.neilgaiman.com/2008/05/get-your-yas-out.html"&gt;reference&lt;/a&gt; caught me with a little more free time.&lt;br /&gt;&lt;br /&gt;Read his review; read the book. Give the book to a teenager you know. I plan to give copies to all the young adults I know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-5342928887668773103?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/5342928887668773103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=5342928887668773103' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5342928887668773103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5342928887668773103'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/05/little-brother-by-cory-doctorow.html' title='Little Brother by Cory Doctorow'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-740593963721964307</id><published>2008-05-09T10:42:00.000-07:00</published><updated>2008-05-09T11:27:09.195-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='configuration'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring Configuration</title><content type='html'>A recent task was to consume a simple comma-separated file and generate database records from it.&lt;br /&gt;&lt;br /&gt;Our application is quite middle of the road in terms of the complexity of it's configuration. One of the most complex parts is the many databases which we access from our code. In this case, I wanted to import test data so we could check out the user interface we were developing for it.&lt;br /&gt;&lt;br /&gt;I spent about a week on the task. Four and a half days working on the wiring, trying to find a way to build a configuration which would run and be able to access the database. Just half a day was required to write and debug the actual code.&lt;br /&gt;&lt;br /&gt;In the end I gave up on trying to test it in the 'correct' place in the code, and hacked at some code where I knew that I would be able to access the database and have a existing user interface to invoke it from, and see the results.&lt;br /&gt;&lt;br /&gt;The code works. Our user interface looks good and displays the imported data.&lt;br /&gt;&lt;br /&gt;This configuration overhead adds to development time and makes it harder to justify extensive testing.&lt;br /&gt;&lt;br /&gt;We have a number of cross-cutting concerns and use &lt;span style="font-style:italic;"&gt;Java 5&lt;/span&gt; annotations extensively. Not all these concerns result in annotations at the places which 'need' them. Our transaction interceptor is an example. For most of our code it 'just works'. The rest of the time it can be hard to know where to start on a solution to the problem.&lt;br /&gt;&lt;br /&gt;To be fair, not all of the configuration overhead relates to our &lt;span style="font-style:italic;"&gt;Spring&lt;/span&gt; wiring. I did lose a couple of hours when a &lt;span style="font-style:italic;"&gt;Maven&lt;/span&gt; deploy on another branch caused a puzzling regression. That is clearly &lt;span style="font-style:italic;"&gt;Maven&lt;/span&gt; configuration overhead.&lt;br /&gt;&lt;br /&gt;While I have done some work with &lt;span style="font-style:italic;"&gt;Groovy&lt;/span&gt;, I have not tried &lt;span style="font-style:italic;"&gt;Grails&lt;/span&gt; yet. I have used &lt;span style="font-style:italic;"&gt;Tapestry&lt;/span&gt; in the past but &lt;span style="font-style:italic;"&gt;Tapestry 5&lt;/span&gt; is a lot different than the &lt;span style="font-style:italic;"&gt;Tapestry 3&lt;/span&gt; I used. I doubt that &lt;span style="font-style:italic;"&gt;Tapestry&lt;/span&gt; will ease these configuration issues. &lt;span style="font-style:italic;"&gt;Grails&lt;/span&gt; might based on my experience with &lt;span style="font-style:italic;"&gt;Ruby on Rails&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-740593963721964307?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/740593963721964307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=740593963721964307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/740593963721964307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/740593963721964307'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/05/spring-configuration.html' title='Spring Configuration'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-8681025952708840888</id><published>2008-04-30T10:02:00.000-07:00</published><updated>2008-05-10T18:10:34.438-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JExample'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit'/><title type='text'>Testing by  JExample</title><content type='html'>The back end of our software - the part which allows us to scale to millions of users - has some very long tests involving networks and databases. They take long enough to run (30+ minutes) that, when run over our VPN, the connection is sometimes dropped before the tests can conclude. While infrequent it is a cause of great frustration when it happens.&lt;br /&gt;&lt;br /&gt;Unit tests need isolation from potential side-effects. Providing that isolation requires potentially extensive and / or time-consuming setup and sometimes tear-down code.&lt;br /&gt;&lt;br /&gt;A very new testing framework based on JUnit is called JExample. Unlike JUnit, tests can depend one upon another. Since the tests have passed, the environment is in a known, tested as correct, state and can be relied upon as the basis of subsequent tests.If test A passes, then test B can rely upon the result and context of A. When A is a long test, or requires considerable setup or teardown, this can result in substantial time savings.&lt;br /&gt;&lt;br /&gt;A dependency graph of tests is built and used to order the tests.&lt;br /&gt;&lt;br /&gt;The main results are less elapsed time for the tests and test failures which are more likely to pin-[point the exact place where a problem is occurring.&lt;br /&gt;&lt;br /&gt;The work is based on the paper by  &lt;a href="http://www.iam.unibe.ch/~scg/Archive/Papers/Kuhn08aJExample.pdf"&gt;Kuhn, Van Rompaey, Haesenbarger, Nierstrasz, Demeyer, Gaelli and Van Leemput&lt;/a&gt;. There is an &lt;a href="http://www.iam.unibe.ch/~akuhn/blog/2008/04/jexample-quickstart/"&gt;introduction&lt;/a&gt; and Eclipse integration. Java 6 is required.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-8681025952708840888?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/8681025952708840888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=8681025952708840888' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8681025952708840888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8681025952708840888'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/testing-by-jexample.html' title='Testing by  JExample'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-2374639122770288058</id><published>2008-04-29T14:56:00.000-07:00</published><updated>2008-05-10T18:10:07.851-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>The Rails Way</title><content type='html'>&lt;div style="float:left;"&gt;&lt;img width="264" height="368" src="http://www.rubyinside.com/wp-content/uploads/2007/12/railsway.png"/&gt;&lt;/div&gt;I never picked up my novel. &lt;span style="font-style: italic;"&gt;The Rails Way&lt;/span&gt; is well-written enough to have kept me reading it through the whole vacation. I read about 500 pages and if our vacation had been any less busy I would have finished it.&lt;br /&gt;&lt;br /&gt;The text is easy to follow no matter how complex the topic, with the exception of a passage relating to meta-programming. I will have to go back and see if I do better a second time around.&lt;br /&gt;&lt;br /&gt;I found a few typos and errors but none that obscured my understanding of the author's true intent.&lt;br /&gt;&lt;br /&gt;The testing section had some good coverage of Rail's built-in facilities and also of &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt;. I have been reading about &lt;span style="font-style:italic;"&gt;Shoulda&lt;/span&gt; &lt;a href="http://pragdave.blogs.pragprog.com/pragdave/2008/04/shoulda-used-th.html"&gt;recently&lt;/a&gt; also and I plan to compare the two more closely.&lt;br /&gt;&lt;br /&gt;&lt;div style="float: right;"&gt;&lt;img src="http://www.pragprog.com/images/covers/original/rails3.jpg" height="228" width="190" /&gt;&lt;/div&gt;&lt;span style="font-style: italic;"&gt;Agile Web Development with Rails&lt;/span&gt; has been considered the leading book on Rails. For a newcomer to the topic it is still a better book but, for anyone with some knowledge of the framework, this is a much better organized volume. &lt;a href="http://www.intertwingly.net/"&gt;Sam Ruby&lt;/a&gt; is updating it for Rails 2 but it will only be a beta book for most of this year.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-2374639122770288058?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/2374639122770288058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=2374639122770288058' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2374639122770288058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2374639122770288058'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/rails-way.html' title='The Rails Way'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-5035537210770813016</id><published>2008-04-29T05:29:00.000-07:00</published><updated>2008-05-10T18:09:32.192-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nice'/><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><title type='text'>Hill towns of the Cote d'Azur</title><content type='html'>Haut de Cagnes and St. Paul de Vence were two hill towns which we visited. People have been seeking the shelter of these steep hills since at least Roman times.&lt;br /&gt;&lt;br /&gt;They both have associations with the Grimaldi family - rulers of Monaco - but only Haut de Cagnes attained the importance to gain a castle.&lt;br /&gt;&lt;br /&gt;As a child I read how Hannibal crossed the Alps with his Elephants to avoid a Roman army blocking the route to Italy. Given the terrain it would have been very hard to force a passage along the coast with plenty of places for the Romans to set up a strong defensive position.&lt;br /&gt;&lt;br /&gt;Now the coastal hills are thickly littered with houses showing how many people are attracted to the scenery, climate and food.&lt;br /&gt;&lt;div style="float:left"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="%3Ca%20href=" com="" cook="" france2008="" authkey="zzA-RhsdxM8#5194669072185541890&amp;quot;"&gt;&lt;img src="http://lh6.ggpht.com/n.k.cook/SBcr_6VTxQI/AAAAAAAAAZ8/Jo8MH505RjQ/s144/0424081538b.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;Haut de Vance&lt;br/&gt;town square from&lt;br/&gt;the castle roof.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-5035537210770813016?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/5035537210770813016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=5035537210770813016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5035537210770813016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/5035537210770813016'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/hill-towns-of-cote-dazur.html' title='Hill towns of the Cote d&apos;Azur'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/n.k.cook/SBcr_6VTxQI/AAAAAAAAAZ8/Jo8MH505RjQ/s72-c/0424081538b.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-8149831435558360005</id><published>2008-04-24T13:58:00.000-07:00</published><updated>2008-05-10T18:08:56.777-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Paris'/><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><title type='text'></title><content type='html'>From the Left Bank to &lt;span style="font-style: italic;"&gt;Notre Dame&lt;/span&gt; to the &lt;span style="font-style: italic;"&gt;Louvre&lt;/span&gt; along the &lt;span style="font-style: italic;"&gt;Champs Elysee&lt;/span&gt; to the top of the &lt;span style="font-style: italic;"&gt;Arc de &lt;/span&gt;&lt;b&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-style: italic;"&gt;Triomphe&lt;/span&gt; to the &lt;span style="font-style: italic;"&gt;Eiffel Tower &lt;/span&gt;to a bus back was about six miles including the long, long corridors of the &lt;span style="font-style: italic;"&gt;Louvre. &lt;/span&gt;Excellent exercise after months of keyboard pounding.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:194px;float:right;"&gt;&lt;tr&gt;&lt;td align="center" style="height:194px;background:url(http://picasaweb.google.com/f/img/transparent_album_background.gif) no-repeat left"&gt;&lt;a href="http://picasaweb.google.com/n.k.cook/ArcDeTriomphe"&gt;&lt;img src="http://lh4.ggpht.com/n.k.cook/SBdpzqVTxtE/AAAAAAAAAZg/4kdg1BKfZsw/s160-c/ArcDeTriomphe.jpg" width="160" height="160" style="margin:1px 0 0 4px;"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="text-align:center;font-family:arial,sans-serif;font-size:11px"&gt;&lt;a href="http://picasaweb.google.com/n.k.cook/ArcDeTriomphe" style="color:#4D4D4D;font-weight:bold;text-decoration:none;"&gt;Arc de Triomphe&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;I took photographs of each of the twelve roads leading from the &lt;span style="font-style: italic;"&gt;Arc de Triomphe&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Notre Dame&lt;/span&gt;&lt;/span&gt; has a crypt but, here, that is an archaeological site showing some of the foundations and wall upon which the area in front of the cathedral has been built. Apart from the many changes in use - including as houses and two different hospitals - it was a shore fortification in Roman times although the bank of the &lt;span style="font-style: italic;"&gt;Seine&lt;/span&gt; is now at least fifty yards distant.&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-8149831435558360005?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/8149831435558360005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=8149831435558360005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8149831435558360005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/8149831435558360005'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/from-left-bank-to-notre-dame-to-louvre.html' title=''/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/n.k.cook/SBdpzqVTxtE/AAAAAAAAAZg/4kdg1BKfZsw/s72-c/ArcDeTriomphe.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-566453765486793352</id><published>2008-04-24T10:02:00.000-07:00</published><updated>2008-05-10T08:54:08.430-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Paris'/><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><title type='text'>Do I hear footsteps?</title><content type='html'>A friend lent us a map of Paris. After arrival we noticed that she had underlined the metro station we used on the way in from the airport. She had also underlined the road of our hotel. The road is only 100 yards long and just has one hotel.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Before looking at the map I would have imagined that the odds of us staying at the same hotel were small. Now I have to believe that we actually did stay there...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-566453765486793352?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/566453765486793352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=566453765486793352' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/566453765486793352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/566453765486793352'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/do-i-hear-footsteps.html' title='Do I hear footsteps?'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-4670649071420188936</id><published>2008-04-23T13:50:00.000-07:00</published><updated>2008-05-09T13:48:26.272-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Paris'/><category scheme='http://www.blogger.com/atom/ns#' term='Nice'/><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><title type='text'></title><content type='html'>&lt;span style="font-style: italic;"&gt;The Rails Way &lt;/span&gt;is proving very readable and I am yet to pick up my novel.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Paris&lt;/span&gt; was fantastic - more on that later. We are now staying in a converted castle guardhouse near Nice. The restaurant here is incredibly good. Our room is huge with a balcony looking out over the valley. There are some very acceptable frog noises in the background as type. We are planning a more relaxing day tomorrow so I will catch up on the events of Paris then.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-4670649071420188936?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/4670649071420188936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=4670649071420188936' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4670649071420188936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/4670649071420188936'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/rails-way-is-proving-very-readable-and.html' title=''/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-1166285847825922732</id><published>2008-04-19T14:04:00.000-07:00</published><updated>2008-05-09T13:02:08.714-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Vacation reading</title><content type='html'>I often find it difficult to decide what books to read on vacation. Fun? Technical? If I really think I need to read some thick technical tome, I will often take just that one book. If I take the big book and a fun one, I know which one I will pick up when I get a moment.&lt;br /&gt;&lt;br /&gt;For this trip I brought along &lt;span style="font-style: italic;"&gt;"The Rails Way"&lt;/span&gt;. I have found it very readable so far. I have been using Rails for a couple of years now and I find the approach of this book much more suitable now than the &lt;span style="font-style: italic;"&gt;"Agile"&lt;/span&gt; book.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;At the risk of not reading &lt;span style="font-style: italic;"&gt;The Rails way&lt;/span&gt;, I also brought along &lt;span style="font-style: italic;"&gt;Shadowplay&lt;/span&gt; by &lt;span style="font-style: italic;"&gt;Tad Williams. &lt;/span&gt;I am a huge fan of his other books. &lt;span style="font-style: italic;"&gt;Memory, Sorrow and Thorn&lt;/span&gt; is from the same genre but I liked it much more than the first book in this series. I will see if it grows on me...&lt;br /&gt;&lt;br /&gt;The plane is waiting...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-1166285847825922732?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/1166285847825922732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=1166285847825922732' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1166285847825922732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/1166285847825922732'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/vacation-reading.html' title='Vacation reading'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7741860926133428681.post-2650539460559096047</id><published>2008-04-18T10:25:00.000-07:00</published><updated>2008-04-18T10:45:02.299-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vacation'/><title type='text'>Making a start</title><content type='html'>My last vacation was to &lt;span style="font-style: italic;"&gt;Scotland&lt;/span&gt; in 2006. I love the Highlands and Islands: &lt;span style="font-style: italic;"&gt;The Great Glen&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;Skye&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;Kyle of&lt;/span&gt; &lt;span style="font-style: italic;"&gt;Lochalsh&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;Mallaig&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;Oban&lt;/span&gt; and the lochs and valleys which connect them. &lt;span style="font-style: italic;"&gt;Tobermory &lt;/span&gt;on &lt;span style="font-style: italic;"&gt;Mull&lt;/span&gt; is a great favourite.&lt;br /&gt;&lt;br /&gt;Tomorrow we leave for &lt;span style="font-style: italic;"&gt;Paris&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;Nice&lt;/span&gt;. They will be such a contrast. One of the great cities of the world with its monuments and museums; and the grassy, rocky, lochs of the Scottish coast. Each is beautiful in its own way - each refreshing to the soul.&lt;br /&gt;&lt;br /&gt;I still have to decide whether to bring my MacBook Pro with me. I can not remember the last vacation I took where I did not spend hours working late at night after a busy day's sightseeing. I have some ideas for a new web site. It would be a contrast to the heavy Java coding of the last ten months. I would probably use Ruby on Rails although Merb is an interesting and tempting alternative.&lt;br /&gt;&lt;br /&gt;If I do not take the laptop with me, this first post might not be succeeded for a couple of weeks. I would love to be able to add some photos of &lt;span style="font-style: italic;"&gt;Paris&lt;/span&gt; though...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7741860926133428681-2650539460559096047?l=engineeringcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://engineeringcode.blogspot.com/feeds/2650539460559096047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7741860926133428681&amp;postID=2650539460559096047' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2650539460559096047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7741860926133428681/posts/default/2650539460559096047'/><link rel='alternate' type='text/html' href='http://engineeringcode.blogspot.com/2008/04/making-start.html' title='Making a start'/><author><name>Neil</name><uri>http://www.blogger.com/profile/16917093353541805205</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
