<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>nirvdrum</title>
 <link href="http://nirvdrum.com/atom.xml" rel="self"/>
 <link href="http://nirvdrum.com/"/>
 <updated>2014-11-21T02:25:43+00:00</updated>
 <id>http://nirvdrum.com/</id>
 <author>
   <name>Kevin Menard</name>
   <email>nirvdrum@gmail.com</email>
 </author>

 
 <entry>
   <title>Open Sourcing a Failed Startup</title>
   <link href="http://nirvdrum.com/2014/11/20/open-sourcing-mogotest.html"/>
   <updated>2014-11-20T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2014/11/20/open-sourcing-mogotest</id>
   <content type="html">&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;In late October, 2014 I announced that I would be shutting down Mogotest.  After close to 5 years of operations it was clear I wouldn&#39;t be able to grow the business.  I don&#39;t think it was due to lack of business opportunity, but due to some business decisions made early on that became very difficult to course correct.  The exact line of reasoning that justified the shutdown is a topic for another day.  The purpose of this post is to discuss what to do with the code after the fact.&lt;/p&gt;

&lt;h2&gt;Are you Going to Open Source It?&lt;/h2&gt;

&lt;p&gt;Rather predictably, one of the first things I was asked after I announced the shutdown was whether I would be open sourcing it.  I was asked from current customers, by friends, by companies that were interested in the tech but never felt the need to support it by giving us business, by random people on Twitter, and so on.  I had already gone through some of the thought process a priori, but I was in a different state of mind then.  Getting the bombardment of questions after the announcment impacted me in ways I couldn&#39;t predict.&lt;/p&gt;

&lt;p&gt;For some additional context, I contribute to a lot of open source projects.  I don&#39;t have a &quot;brand name&quot; and I&#39;ve never professionaly sold open source software or sold consulting services around it, but I&#39;ve worked with a lot of projects.  I use the Apache Software license version 2.0 for just about everything.  And I guess I would consider myself more of a pragmatist than an ideologue when it comes to open source software.&lt;/p&gt;

&lt;p&gt;With that said, my gut reaction was to not open source it.  My analytical reaction was also not to open source it.&lt;/p&gt;

&lt;h2&gt;Why Not?&lt;/h2&gt;

&lt;p&gt;I&#39;d just like to insert a standard disclaimer at this point that what follows is my own experience and my own potentially irrational thought process.  If anything I say comes off as a generality, please note that my pomposity stops short of speaking for others.&lt;/p&gt;

&lt;p&gt;First up is the emotional aspect.  I had just made the extremely difficult decision to walk away from something I spent the past 5 years of my life dedicated to.  During that time, I lost at least two full years of wages, pissed through my savings, and lost ~$40K USD in cash invested into the business.  I battled with some form of founder depression.  Stastically speaking, this was the most likely outcome, so I&#39;m hardly looking for sympathy.  But, having made that gut-wrenching decision to walk away from it all, the prospect of going back to it and investing a non-trivial amount of effort just to give it away is a really tough pill to swallow.&lt;/p&gt;

&lt;p&gt;Also on the emotional aspect is just my own human pettiness.  I&#39;ve been asked to open source the codebase from people that evidently didn&#39;t think the software was good enough to be worth paying for as a service.  I&#39;ve been asked to open source the codebase by other companies in the space that didn&#39;t want to buy the rights when I was shopping the company around.  So, while I really want to provide a soft landing for my customers, I really didn&#39;t want to just be giving everything away to those that just wanted to mooch.&lt;/p&gt;

&lt;p&gt;Setting all that aside, open sourcing the codebase is not some trivial process.  And I&#39;m not talking wanting to clean up stuff I might be embarrassed by.  Here&#39;s a non-comprehensive list of issues that need to be addressed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The web site design was a theme bought on WrapBootstrap that I don&#39;t have the rights to sublicense.&lt;/li&gt;
&lt;li&gt;The rich UI widgets come from the commercial version of ExtJS.  That needs to be excised or the whole project needs to be GPLv3.&lt;/li&gt;
&lt;li&gt;Sidekiq Pro needs to be removed.&lt;/li&gt;
&lt;li&gt;Every JS lib and every image resource we used must have its license examined and potentially be replaced.&lt;/li&gt;
&lt;li&gt;Any customer info that made its way into the code needs to be removed.  As an example, we built up an extensive regression suite around customer data that can&#39;t be distributed.  This whole process means auditing every file in the codebase.&lt;/li&gt;
&lt;li&gt;Ensuring any API keys or passwords aren&#39;t floating around in the source or configuration files (obviously bad, but things happen).&lt;/li&gt;
&lt;li&gt;Potentially unobscuring security holes while the service is still running.&lt;/li&gt;
&lt;li&gt;Removing all the billing code.&lt;/li&gt;
&lt;li&gt;Removing all the drip email campaign code.&lt;/li&gt;
&lt;li&gt;Removing any other non-Web Consistency Testing parts from the code.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;A lot of this is a liability.  Going through it all is a ton of work.  After all that, I open myself up to all sorts of scrutiny I don&#39;t really care for.  Sometimes I swear in code.  I hold a somewhat traditionalist view of English and prefer my plurality to match up, so I use gendered pronouns in my personal writings, which will have now just become public.  I&#39;m certain there is some colorful commentary about each of the browser vendors buried somewhere in the source.  Without a doubt, something in this codebase will offend someone and my personal reputation is at risk when it simply wouldn&#39;t have been by keeping it private.&lt;/p&gt;

&lt;p&gt;It&#39;s basically all the work required to clean up during an acquisition, but with the inverse financial outcome.&lt;/p&gt;

&lt;p&gt;If I managed to clear that hurdle, the next problem is that I simply don&#39;t find there to be much value in open source code.  Open source projects, yes.  Open source code, rarely.  I won&#39;t have either the time or the wherewithal to spend any additional effort on this project.  If I make the code publicly available, people will have questions that I won&#39;t have time to answer.  Consequently, I&#39;m just going to constantly feel like an inadequate piece of garbage.  On the other hand, if I manage to find time to engage, I don&#39;t have the energy to justify every design decision.  Some things do just look silly, but they were the product of the constraints imposed at the time.  Contextually, they were sound.  In today&#39;s world &amp;hellip; probably not so much.  Fixing them would certainly be progress, but in my experience these sorts of things aren&#39;t approached tactfully and I&#39;d rather not be called an idiot without having the resources to defend the context.&lt;/p&gt;

&lt;h2&gt;Second Thoughts&lt;/h2&gt;

&lt;p&gt;At the end of the day, I want Web Consistency Testing to evolve.  If making Mogotest open source will help achieve that, I&#39;m willing to overlook some of the other problems.  I&#39;ve already released the &lt;a href=&quot;https://bitbucket.org/mogotest/&quot;&gt;ancillary libraries&lt;/a&gt; as ASLv2, and I was going to release the main application under the Affero General Public License (AGPL).  After spending 14 hours cleaning things up this past weekend, I&#39;m still not 100% certain I&#39;m not violating IP somewhere or leaking customer info and I&#39;ve had to gut the product so thoroughly that it&#39;s virltually useless.  Rewriting all the view code just isn&#39;t something I have the desire to do.&lt;/p&gt;

&lt;p&gt;In conjunction with the decision to use the AGPL, I decided to try a &lt;a href=&quot;https://www.indiegogo.com/projects/open-source-mogotest/x/2556255&quot;&gt;crowd-sourced campaign&lt;/a&gt; to help with the open sourcing effort.  Precisely zero of the companies that have been begging me to open-source the code have contributed in any capacity.  The incredible amount spam I&#39;ve received via comments on IndieGogo and Twitter have been equally disheartening.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I had my initial emotional reaction, I analyzed the hell out of it, I decided against my better judgment to try opening the code anyway, and I simply can&#39;t do it.  I think the tools I have open-sourced will be beneficial to others and I&#39;ve explained how things work fairly extensively in &lt;a href=&quot;http://webconsistencytesting.com/&quot;&gt;a talk I gave&lt;/a&gt; at Google&#39;s Test Automation Conference.  A clean-room implementation shouldn&#39;t be too onerous, given I&#39;ve solved a lot of the environmental problems you&#39;re apt to encounter.  Unfortunately, this is where I have to get off the train.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Take Full Page or Full Canvas Screenshots in Windows</title>
   <link href="http://nirvdrum.com/2010/03/25/how-to-take-full-page-or-full-canvas-screenshots-in-windows.html"/>
   <updated>2010-03-25T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2010/03/25/how-to-take-full-page-or-full-canvas-screenshots-in-windows</id>
   <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;While developing &lt;a href=&quot;http://mogotest.com/&quot;&gt;MogoTest&lt;/a&gt;, a service for detecting Web browser rendering issues, I found it necessary to be able to capture the contents of the entire browser canvas rather than just the current viewport.  A full page screenshot lets the user see how their content looks from a holistic perspective.  Unfortunately, capturing all of the content clipped by the scrollable viewport is not a very straightforward process.&lt;/p&gt;

&lt;p&gt;One approach to grabbing the full canvas is to take a screenshot and then scroll the viewport to display all the previously hidden sections, stitching all of the images together to form one composite that represents the full canvas contents.  While this generally works, it fails if there are any fixed position elements on the page or if there is ECMAScript in place to modify the DOM on scroll events because in both cases the very act of scrolling modifies the canvas&#39;s contents.  It would be better then to capture the entire canvas without scrolling.&lt;/p&gt;

&lt;h2&gt;The Problem with Making Windows Large Enough to Remove Scrollbars&lt;/h2&gt;

&lt;p&gt;Windows does not allow windows to be larger than the virtual screen resolution by default.  The virtual screen resolution is defined as the vertical and horizontal span of all connected displays.  If you have a single display, the current screen resolution will have a 1:1 match with the virtual screen resolution and if you have two displays side-by-side, the virtual screen resolution will be the height of the lowest resolution by the sum of the two horizontal screen resolutions.&lt;/p&gt;

&lt;p&gt;Resizing the window to display the entire canvas contents, thus, requires some trickery in handling the virtual screen dimensions.  As it turns out, every window is sent a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms632626%28VS.85%29.aspx&quot;&gt;&lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message&lt;/a&gt; just before the window&#39;s screen coordinates or size is changed.  &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; passes as its &lt;code&gt;lParam&lt;/code&gt; a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms632605%28VS.85%29.aspx&quot;&gt;&lt;code&gt;MINMAXINFO&lt;/code&gt; value&lt;/a&gt; which contains the virtual screen dimensions as the the &lt;code&gt;ptMaxTrackSize&lt;/code&gt; member.  Modifying the &lt;code&gt;lParam&lt;/code&gt; before the window receives the message would allow us to effectively change the virtual screen resolutions on a per-process basis.&lt;/p&gt;

&lt;p&gt;If you have access to the source code of the application you&#39;d like to capture the full canvas contents of, the solution is simple: just modify your message processing loop to handle &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; messages and modify the &lt;code&gt;lParam&lt;/code&gt; as necessary.  In the general case, however, you won&#39;t be able to modify the binary so you&#39;ll have to modify the executing process&#39;s address space to inject your own message handler.&lt;/p&gt;

&lt;p&gt;While the general concept is rather straightforward, the implementation is fairly convoluted.  At the core of it, the complexity is caused by the &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message being sent rather than retrieved by the window.&lt;/p&gt;

&lt;h2&gt;Tricking Windows into Letting you Resize the Window Larger than the Screen&lt;/h2&gt;

&lt;p&gt;The Win32 API allows applications to monitor global event message traffic by setting up a hook procedure via the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms644990%28VS.85%29.aspx&quot;&gt;&lt;code&gt;SetWindowsHookEx&lt;/code&gt; function&lt;/a&gt;.  This is how utilities like Spy++ are able to tell what messages are being sent to a program.  As of this writing, there are thirteen different &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx#types&quot;&gt;types of hooks&lt;/a&gt;, each with its own context and execution point in the global chain.&lt;/p&gt;

&lt;p&gt;If you&#39;re like me, you&#39;d probably try to register a &lt;code&gt;WH_GETMESSAGE&lt;/code&gt; hook with &lt;code&gt;GetMsgProc&lt;/code&gt;.  On the outset it seems logical enough: intercept the &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message before &lt;code&gt;GetMessage&lt;/code&gt; or &lt;code&gt;PeekMessage&lt;/code&gt; is called and modify accordingly.  This will not work, however, and you will waste a lot of time trying to make it work.  The nuance here is that &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; is sent to the window -- the window does not poll for it -- and as such a &lt;code&gt;WH_GETMESSAGE&lt;/code&gt; hook will never see the message.&lt;/p&gt;

&lt;p&gt;The next seemingly logical hook type to try is &lt;code&gt;WH_CALLWNDPROC&lt;/code&gt;, which you register with the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms644975%28VS.85%29.aspx&quot;&gt;&lt;code&gt;CallWndProc&lt;/code&gt; function&lt;/a&gt;.  This type of hook will indeed intercept the &lt;code&gt;WM_MINMAXINFO&lt;/code&gt; message before the window will, but unfortunately, the hook procedure cannot modify the message.  This is by design and Windows will enforce it; trying to get a reference to the &lt;code&gt;lParam&lt;/code&gt; to modify the value in memory will not work.&lt;/p&gt;

&lt;p&gt;And so it goes with all the hook types.  Many look like they&#39;ll do what you need, but will fail in some way.  It seems that modifying the &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message from out of process is not possible.  And largely that&#39;s true.  However, we can get creative by supplanting the process&#39;s window procedure, which executes in process, by using &lt;code&gt;SetWindowLongPtr&lt;/code&gt; from the &lt;code&gt;WH_CALLWNDPROC&lt;/code&gt; hook.  Example 1 shows what that interaction may look like.&lt;/p&gt;

&lt;pre class=&#39;brush: cpp;&#39;&gt;
// The WH_CALLWNDPROC hook procedure, executed out-of-process.
LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    CWPSTRUCT* cwp = (CWPSTRUCT*) lParam;

    if (WM_GETMINMAXINFO == cwp-&gt;message)
    {
        // Inject our own message processor into the process so we
        // can modify the WM_GETMINMAXINFO message.  It is not possible
        // to modify the message from this hook, so the best we can do
        // is inject a function that can.
        LONG_PTR proc = SetWindowLongPtr(cwp-&gt;hwnd, GWL_WNDPROC, (LONG_PTR) MinMaxInfoHandler);
        
        // Store a handle to the original window procedure in the window&#39;s
        // property list so we can restore the procedure from the custom processor.
        SetProp(cwp-&gt;hwnd, L&quot;__original_message_processor__&quot;, (HANDLE) proc);
    }

    return CallhkHookEx(hkHook, nCode, wParam, lParam);
}

// Install the hook procedure in the global hook chain.  DLL_PATH must be
// a fully qualified path to the DLL file containing the WH_CALLWNDPROC hook procedure.
HINSTANCE hinstDLL = LoadLibrary(DLL_PATH);
HOOKPROC hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, &quot;CallWndProc&quot;);
HHOOK hkHook = SetWindowsHookEx(WH_CALLWNDPROC, hkprcSysMsg, hinstDLL, 0);
&lt;/pre&gt;


&lt;div class=&#39;caption&#39;&gt;Example 1: Registering the &lt;code&gt;WH_CALLWNDPROC&lt;/code&gt; hook procedure.&lt;/div&gt;


&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms644898%28VS.85%29.aspx&quot;&gt;&lt;code&gt;SetWindowLongPtr&lt;/code&gt;&lt;/a&gt; is an amazing feature of Windows that lets you supply a new function pointer for a restricted set of functions in a Windows process.  The new function can then call out to the original function through a handle to that function.  One of the functions allowed to be replaced is the window procedure.  By supplying our own we will be able to finally modify that &lt;code&gt;WM_MINMAXINFO&lt;/code&gt; message.  In &lt;code&gt;Example 1&lt;/code&gt; we showed how to call &lt;code&gt;SetWindowLongPtr&lt;/code&gt;.  &lt;code&gt;Example 2&lt;/code&gt; shows what the custom window procedure looks like:&lt;/p&gt;

&lt;pre class=&#39;brush: cpp;&#39;&gt;
// The custom window procedure, executed in-process, to manipulate the WM_MINMAXINFO message.
LRESULT CALLBACK MinMaxInfoHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // Grab a reference to the original message processor.
    HANDLE originalMessageProc = GetProp(hwnd, L&quot;__original_message_processor__&quot;);
    RemoveProp(hwnd, L&quot;__original_message_processor__&quot;);
 
    // Uninstall this custom window procedure so the next message will use the original procedure.
    SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR) originalMessageProc);
 
    // Only handle the message we&#39;re interested in.
    if (WM_GETMINMAXINFO == message)
    {
        MINMAXINFO* minMaxInfo = (MINMAXINFO*) lParam;
 
        // ptMaxTrackSize corresponds to the screen&#39;s virtual dimensions.
        // MAX_WIDTH and MAX_HEIGHT should be the width and height of the window allowing the full
        // canvas to be displayed without scrollbars.  This is application dependent.
        minMaxInfo-&gt;ptMaxTrackSize.x = MAX_WIDTH;
        minMaxInfo-&gt;ptMaxTrackSize.y = MAX_HEIGHT;
 
        // We&#39;re not going to pass this message onto the original message processor, so we should
        // return 0, per the contract for the WM_GETMINMAXINFO message.
        return 0;
    }
 
    // All other messages should be handled by the original message processor.
    return CallWindowProc((WNDPROC) originalMessageProc, hwnd, message, wParam, lParam);
}
&lt;/pre&gt;


&lt;div class=&#39;caption&#39;&gt;Example 2: Modifying the &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message with a custom window procedure.&lt;/div&gt;


&lt;p&gt;Note that we only handle the &lt;code&gt;WM_GETMINMAXINFO&lt;/code&gt; message and delegate all others to the original window procedure.  Additionally, we uninstall the custom procedure as soon as we&#39;ve accomplished what we need to.&lt;/p&gt;

&lt;p&gt;We modify the &lt;code&gt;ptMaxTrackSize&lt;/code&gt; component of the &lt;code&gt;MINMAXINFO&lt;/code&gt; struct, which is itself a &lt;code&gt;POINT&lt;/code&gt; struct, having an &lt;code&gt;x&lt;/code&gt; and a &lt;code&gt;y&lt;/code&gt; component.  These should be set large enough to handle the full canvas plus the window chrome that surrounds the main client area.  Once this is done, you should be able to size the window large enough to obviate the need for scrollbars.&lt;/p&gt;

&lt;p&gt;Fig. 1 shows how this all ties together between a theoretical screenshot.exe process taking full canvas screenshots in Internet Explorer.&lt;/p&gt;

&lt;div class=&quot;figure&quot;&gt;
  &lt;img src=&quot;/images/how-to-take-full-page-screenshots-in-windows/comprehensive-system-diagram.png&quot; /&gt;
  
  Fig. 1: Comprehensive interaction diagram for taking full page screenshots.
&lt;/div&gt;


&lt;h2&gt;Capturing the Canvas Contents&lt;/h2&gt;

&lt;p&gt;Now that your application can be sized large enough to capture the canvas contents, you must resize the window to that maximum size.  This calculation is application dependent.  For Internet Explorer much of the work is done with the IWebBrowser2 interface, for example.&lt;/p&gt;

&lt;p&gt;One caveat is that if the window is already maximized, Windows will not send it a sizing message.  My solution to this problem is to first check if the window is already maximized and if so note that fact, change the maximized state to restored, then resize the window to be large enough for the full canvas contents.  Once done, I then re-maximize the window if it was previously maximized, effectively restoring the window to its original dimensions.  It is a bit kludgy, but I haven&#39;t been able to come up with a better solution.  I suspect there is a way by intercepting a different window message, but I couldn&#39;t figure out which one if it is in fact possible.  This process can be seen in &lt;code&gt;Example 3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All that remains now is to capture the contents, unregister the &lt;code&gt;WH_CALLWNDPROC&lt;/code&gt; hook, and resize the window to its original dimensions so the user doesn&#39;t have to deal with a massive window.  &lt;code&gt;Example 3&lt;/code&gt; pulls all this code together.&lt;/p&gt;

&lt;pre class=&#39;brush: cpp;&#39;&gt;
// Check if the window is maximized.
BOOL isMaximized = IsZoomed(hwnd);
if (isMaximized)
{
    ShowWindow(hwnd, SW_SHOWNORMAL);
}
else
{
  // Store the window&#39;s original dimensions into some local variables.
}

// Set the window to its new dimensions.  There are a variety of ways to do this.

// Note that CImage is part of ATL.  If you want to use strict Win32 API for DIBs, you
// can do so; it&#39;s just much more complicated.
CImage image;
image.Create(imageWidth, imageHeight, 24);
CImageDC imageDC(image);

// Capture the contents of the client area to our image DC.
PrintWindow(hwnd, imageDC, PW_CLIENTONLY);

// Remove our `WH_CALLWNDPROC` hook procedure from the global hook chain.
// hkHook was the return value from the SetWindowsHookEx function call.
UnhookWindowsHookEx(hkHook);

// Restore the window to the original dimensions.
if (isMaximized)
{
    ShowWindow(hwnd, SW_MAXIMIZE);
}
else
{
    // Set the window to its original dimensions.
}

// Actually save the image file.
image.Save(CW2T(outputFile));
&lt;/pre&gt;


&lt;div class=&#39;caption&#39;&gt;Example 3: Taking the full canvas screenshot.&lt;/div&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Taking full page or full canvas screenshots in Windows can be tricky, but the method discussed in this article should be widely applicable.  In my particular case I was enhancing the &lt;a href=&quot;http://snapsie.sf.net/&quot;&gt;SnapsIE&lt;/a&gt; utility.  My &lt;a href=&quot;http://github.com/nirvdrum/SnapsIE/blob/master/CoSnapsie.cpp&quot;&gt;SnapsIE fork&lt;/a&gt; illustrates how I use all of these techniques.  Note that SnapsIE is written as an ActiveX control for Internet Explorer, so the code is likely more complex than is warranted in many cases.&lt;/p&gt;

&lt;h2&gt;Acknowledgments&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Haw-Bin Chai for &lt;a href=&quot;http://snapsie.sourceforge.net/&quot;&gt;SnapsIE&lt;/a&gt;, which served as a basis for much of the work I did.&lt;/li&gt;
&lt;li&gt;Jim Evans for more &lt;a href=&quot;http://code.google.com/p/selenium/issues/detail?id=326&amp;amp;colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary&amp;amp;start=100&quot;&gt;IE screenshot work on selenium&lt;/a&gt;, which handled IE8 a bit more gracefully than SnapsIE did.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.codeguru.com/forum/showthread.php?p=1889928&quot;&gt;sunnyandy&lt;/a&gt;, who had the closest answer on how to take full screen screenshots that I was able to find.&lt;/li&gt;
&lt;li&gt;Igor Tandetnik, who knows VC++ better than any human I&#39;m aware of.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://neverlet.be/&quot;&gt;Jeff Rafter&lt;/a&gt;, who helped me debug all sorts of issues while I was developing the foundation for this article and then served as a peer reviewer of the content.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mogotest.com/&quot;&gt;MogoTest&lt;/a&gt; for allowing me to spend all this time solving the problem.&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>On Amazon EC2 Spot Instances</title>
   <link href="http://nirvdrum.com/2010/01/22/ec2-spot-instance-requests.html"/>
   <updated>2010-01-22T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2010/01/22/ec2-spot-instance-requests</id>
   <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;A couple months ago Amazon &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2009/12/14/announcing-amazon-ec2-spot-instances/&quot;&gt;announced&lt;/a&gt; support for &lt;a href=&quot;http://aws.amazon.com/ec2/spot-instances/&quot;&gt;EC2 spot instances&lt;/a&gt;.  In a nutshell, a spot instance is an EC2 instance that you bid on and that Amazon creates and destroys based upon whatever spare capacity is available in a given EC2 availability zone (i.e., supply) and your maximum bidding price versus the current spot instance price (i.e., demand).  A spot instance is less flexible than an on-demand or reserved instance is in terms of lifecycle, but could be significantly cheaper if your application can handle that volatility.&lt;/p&gt;

&lt;p&gt;This post summarizes my experience with spot instances and how I make use of them.&lt;/p&gt;

&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;My &lt;a href=&quot;http://mogotest.com/&quot;&gt;latest project&lt;/a&gt; is a front-end web testing tool, running a variety of web browsers across both Linux and Windows.  We make heavy use of EC2, which allows us to pay for servers as we use them.  While EC2 drastically reduces the start-up costs because we don&#39;t need to bulk purchase equipment, it can still be costly.  The rate as of this posting for a small Windows instance is $0.12 USD / hour.  At approximately 720 hours in a month, that&#39;s roughly $86 USD / month.  In order to process our work queue quickly we need to run a decent sized cluster.&lt;/p&gt;

&lt;p&gt;Like any reasonable organization, we&#39;d like to reduce cost without adversely impacting quality of service.  Prior to spot instances there were several ways to reduce cost, but none were ideal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The simplest, but most costly, is to purchase a &lt;a href=&quot;http://aws.amazon.com/ec2/#pricing&quot;&gt;reserved instance&lt;/a&gt;.  With a reserved instance you pay an up-front fee but then pay reduced hourly rates as you run your instance.  Over the long term there are significant savings, but you have to be able to afford the initial cost and Amazon only supports reserved instances for Linux.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another cost-saving technique is to adjust your number of running instances based on load, so you don&#39;t pay for resources you aren&#39;t really using.  This can be tricky to do correctly though and you could be caught with an anemic cluster if you have a large burst of traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The hardest approach is to try to increase throughput on a given server.  This could require significant man power to achieve and for some applications may not even be possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Spot instances change the problem domain by making the instance price variable without having to be burdened with the initial expense of a reserved instance.  We&#39;ve been able to get small Windows instances for as low as $0.05 / hour, which equates to a nearly 60% savings.  Similar savings can be had for linux servers as well at all of the various EC2 sizes (e.g., we routinely pay less for a medium linux spot instance than for a small linux on-demand instance).  Spot instance pricing can change at various times throughout the day, but the price is almost always below the current on-demand instance price.  Theoretically it could go higher than the on-demand price, but it would be silly to do so because you could just get an on-demand instance then.  With that savings, we can run more instances for each browser type on the same budget, increasing quality of service.&lt;/p&gt;

&lt;p&gt;Of course, this is all predicated on the cluster being able to handle the dynamic addition and removal of instances.  You will have to account for the case where a spot instance dies in the middle of processing a request and be able to recover from that.  So, spot instances are not ideal for all applications.  But, for a background worker system it can be a cost-effective way to work through your queue more quickly.&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;

&lt;p&gt;We use &lt;a href=&quot;http://github.com/wr0ngway/rubber&quot;&gt;rubber&lt;/a&gt; for our cluster configuration and app deployment.  Rubber is a &lt;a href=&quot;http://www.capify.org/&quot;&gt;capistrano&lt;/a&gt; plugin that simplifies working with Amazon Web Services.  Using role-based deployment, we can configure the packages and gems to be installed on an EC2 instance, attach an EBS volume if necessary, and backup files to S3 with succinct YAML configuration.  As of the &lt;a href=&quot;http://github.com/wr0ngway/rubber/commits/v1.2.0&quot;&gt;1.2.0 version&lt;/a&gt;, rubber can now handle spot instance requests.&lt;/p&gt;

&lt;p&gt;A sample configuration for a single host in rubber would look like the following rubber.yml extract.&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
# Sample spot instance request configuration in rubber.yml.
hosts:
  ie8:                         # The instance&#39;s hostname
    instance_roles: &quot;vnc,rdp&quot;  # Only expose VNC and RDP for this server
    cloud_providers:
      aws:
        image_id: ami-df20c3b6 # Standard 32-bit Windows 2003 Server image
        image_type: m1.small   # Create a small EC2 instance
        spot_price: &quot;0.12&quot;     # Max. spot price you are willing to pay
        spot_instance: true    # Default is false.
        spot_instance_request_timeout: 600 # Fall back to on-demand after 5 min.
&lt;/pre&gt;


&lt;p&gt;While this example shows configuration for a single host, any option could also be applied globally for all nodes in your cluster and can be overridden on a host-by-host basis.  So, you can vary the maximum price you&#39;re willing to pay for a server on a per-instance basis and you can have a combination of on-demand and spot instances in your cluster.&lt;/p&gt;

&lt;p&gt;One thing to note is that rubber was originally designed for on-demand and reserved instances, which have synchronous creation characteristics.  Spot instance requests, on the other hand, are satisfied asynchronously.  Rubber&#39;s solution is to block after the spot instance request is made and to poll Amazon until the instance is created.  Since waiting ad infinitum isn&#39;t ideal for everyone, rubber lets you set your own service level target through a request timeout value (&lt;code&gt;spot_instance_request_timeout&lt;/code&gt; in the example).  If the request fails to be fulfilled before that timeout is exceeded, the spot instance request will be canceled and rubber will fallback to creating an on-demand instance.&lt;/p&gt;

&lt;p&gt;We use &lt;a href=&quot;http://github.com/defunkt/resque&quot;&gt;resque&lt;/a&gt; for our work queue.  Resque does an excellent job of adapting to changes in the worker topology.  So, adding new workers through spot instances and even removing instances cleanly is managed nicely for us.  Additionally, resque was designed to handle job failures from the outset.  While this won&#39;t help you if your job is shutdown midway-through a non-atomic operation, it does ease the task of job management -- you just have to make sure your jobs are resumable.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As would be expected, spot instance requests are easier to fulfill during non-peak hours.  Likewise, the most expensive operating times are during peak hours.  We&#39;ve found that trying to create a spot instance during peak business hours may take a while to fulfill, whereas requests during non-peak hours are fulfilled quickly (oftentimes under 3 minutes).  If you set your maximum price high enough, you shouldn&#39;t lose your instance after it&#39;s created either, unless Amazon needs to reclaim resources for on-demand customers.  In practice we&#39;ve run spot instances for weeks at a time.  We&#39;ve also had some die shortly after creation because we didn&#39;t set a high enough maximum price.  You&#39;ll have to do some analysis to find out what&#39;s best for your application.&lt;/p&gt;

&lt;p&gt;If you can be flexible with your EC2 availability zones, you&#39;ll see the best results.  There are marginal bandwidth fees between availability zones in the same region, but in our case the savings from a spot instance trump the bandwidth charges.  However, if you do large amounts of data transfer between instances, you should take that into consideration.&lt;/p&gt;

&lt;p&gt;Overall, we&#39;ve found spot instances to be a great way to grow our cluster with a fixed budget.  We&#39;ve had to architect our application to be resilient to nondeterministic node additions and removals, but that was a lot easier for us than trying to increase the work throughput on any single server.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>My New Tech Tumblr</title>
   <link href="http://nirvdrum.com/2010/01/17/my-new-tech-tumblr.html"/>
   <updated>2010-01-17T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2010/01/17/my-new-tech-tumblr</id>
   <content type="html">&lt;p&gt;Following in the footsteps of &lt;a href=&quot;http://tumblr.graysky.org/&quot;&gt;Mike Champion&lt;/a&gt; and several others from &lt;a href=&quot;http://bostonrb.org&quot;&gt;boston.rb&lt;/a&gt;, I&#39;ve decided to set up a tech tumblr account.  Basically, it&#39;s a place where I can bookmark and annotate links to content of high technical value without having to deal with the ephemeral nature of twitter or the time sink of writing a full weblog post.&lt;/p&gt;

&lt;p&gt;Anyway, if you&#39;re interested in some of the same things I am, you may find some value in it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tumblr.nirvdrum.com/&quot;&gt;My tech tumblr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tumblr.nirvdrum.com/rss&quot;&gt;RSS feed for my tech tumblr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Lessons Learned in Large Computations with Ruby</title>
   <link href="http://nirvdrum.com/2009/09/17/lessons-learned-in-large-computations-with-ruby.html"/>
   <updated>2009-09-17T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2009/09/17/lessons-learned-in-large-computations-with-ruby</id>
   <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This is the follow-up post to my &lt;a href=&quot;http://nirvdrum.com/2009/09/03/github-contest-recap.html&quot;&gt;GitHub Contest Recap&lt;/a&gt; post that I promised.  As mentioned, I submitted two entries for the GitHub contest, starting with Ruby and then rewriting in Java.  This post summarizes why I ultimately dropped Ruby in favor of Java for this particular task.  I apologize for its length, but it is divided into discrete sections and can be read in chunks without great loss of continuity.&lt;/p&gt;

&lt;h2&gt;Things that Worked Well with Ruby&lt;/h2&gt;

&lt;h3&gt;Very quick and easy text processing&lt;/h3&gt;

&lt;p&gt;Overall, Ruby excelled at the tasks I knew it would excel at.  Principally, I was able to write fairly clean code that produced results in short order.  Its text processing capabilities are solid and were a big boon in processing the data files supplied as part of the contest.  Likewise, generating a results file was a trivial matter.&lt;/p&gt;

&lt;h3&gt;Class re-opening&lt;/h3&gt;

&lt;p&gt;I generally shy away from monkey-patching unless absolutely necessary, but having the ability to do it easily is always nice.  I found myself working around limitations in &lt;a href=&quot;http://ai4r.rubyforge.org/&quot;&gt;AI4R&lt;/a&gt;, a Ruby-based artificial intelligence library, and adding basic statistics functions to Array.  Being able to call &lt;code&gt;[x, y, z].mean&lt;/code&gt; or &lt;code&gt;[t, u, v].sum&lt;/code&gt; was an extremely concise way to represent terms in some of my equations.&lt;/p&gt;

&lt;h2&gt;Things that Did Not Work Well with Ruby&lt;/h2&gt;

&lt;p&gt;I had thought that I understood Ruby fairly well, but this project taught me otherwise.  Much like Java and the JVM, there are a lot of subtleties in Ruby I was either blissfully unaware of or haven&#39;t had to worry about in any great detail.  From the seemingly inane, such as the three different methods of object equality, to the surprising, such as the lack of a Float::Infinity constant.&lt;/p&gt;

&lt;h3&gt;Marshalling circular relationships&lt;/h3&gt;

&lt;p&gt;One of my earliest setbacks was related to marshalling.  Given that I was dealing with processed datasets and a large number of objects, I thought marshalling the data to and from disk would be an appropriate thing to do in order to save start-up time.  I had written my code such that a &lt;code&gt;Watcher&lt;/code&gt; class and a &lt;code&gt;Repository&lt;/code&gt; class maintained bi-directional references to one another.  By using a set for the associations, I avoided creating infinite loops when establishing the relationships.  However, the marshalling library does not know how to deal with circular references.  Thus, an attempt to marshal resulted in an infinite loop.  This seems quite odd to me as the problem of persisting a graph of objects is not intractable and thus I consider the limitation to be a bug in the marshalling library.&lt;/p&gt;

&lt;p&gt;To be fair, Ruby does provide means of manually controlling marshalling, but I did not pursue this path.  Ultimately, I was using Ruby because it was supposed to make my development faster.  Getting drawn into the nuances of marshalling was something I didn&#39;t have time for and had no interest in doing.&lt;/p&gt;

&lt;h3&gt;Creating large number of objects&lt;/h3&gt;

&lt;p&gt;An early design decision I made was to keep as much data in memory as possible.  This was because I was planning on running a large number of computations and wanted data access to be as quick as possible; faulting in from disk or DB would have been too slow.  A consequence of that decision was that in my very first pass at the program I had 750,000 objects in memory.  I never grew significantly beyond that because I managed to make the garbage collector in MRI segfault several times.  For about a week I tried to clean up my memory space: I dropped the bi-directional relationships between a watcher and a repository; I removed memoized calculations; and I did away with local copies of data at both the method and instance levels in favor of effectively global data.  Essentially, I tossed away any legibility my code once had.  In the end, however, the program was able to run without crashing the garbage collector, albeit several multitudes slower.  This prompted me to attempt profiling the application.&lt;/p&gt;

&lt;h3&gt;Profiling with perftools.rb&lt;/h3&gt;

&lt;p&gt;My first attempt at profiling was with &lt;a href=&quot;http://github.com/tmm1/perftools.rb&quot;&gt;perftools.rb&lt;/a&gt;, which uses Google&#39;s profiling tools.  I had &lt;a href=&quot;http://www.igvita.com/2009/06/13/profiling-ruby-with-googles-perftools/&quot;&gt;read good things&lt;/a&gt; about it from people that I generally hold in high regard.  Alas, I was unable to run it.  On both my MacOS X 10.5.7 laptop using prefixed Gentoo&#39;s Ruby (1.8.7p174) and Ubuntu 9.04&#39;s Ruby (1.8.7p72) the profiler segfaulted almost immediately.  I believe this had to do with the large object graph, but the error message wasn&#39;t terribly helpful and I had little interest in analyzing the coredump.&lt;/p&gt;

&lt;h3&gt;Profiling with ruby-prof&lt;/h3&gt;

&lt;p&gt;Having failed to accomplish anything with profile.rb, I fell back to the venerable ruby-prof.  This profiler worked, but was extremely slow.  After several hours of running, I finally relented and sent it a SIGTERM.  I was pleasantly surprised to see that it maintained intermediary stats and output them upon application exit.  Unfortunately, it hadn&#39;t moved beyond my initial data loading code, so the reported information was of limited value.&lt;/p&gt;

&lt;h3&gt;Memoizing at class method level&lt;/h3&gt;

&lt;p&gt;At one point my back-of-the-napkin calculation was that I was performing 13 MM point comparisons in &lt;a href=&quot;http://nirvdrum.com/2009/09/03/github-contest-recap.html&quot;&gt;my instance space&lt;/a&gt;, many of them duplicating internal computations.  This was an easy target for optimization just through caching, so I decided to try out the memoize gem.  The general lack of code examples for it leads me to believe that it is not in widespread use.  All examples I found, including the one in &quot;The Ruby Way,&quot; use the library outside of any class structure.  After searching news groups for a while and studying the source, I managed to get memoization going for instance methods on an object.  However, I was unable to figure out how to get the library to work on class methods without code modification; another irritating setback.&lt;/p&gt;

&lt;h3&gt;Memcache only storing 1MB files&lt;/h3&gt;

&lt;p&gt;Having had issues with the MRI garbage collector and hoping to save costly calculations between data runs, I turned to the quintessential memory caching tool, memcached.  I was running version 1.4.0, which sports a new binary protocol for compressed communication.  Although I was connecting to localhost, I wanted to reduce latency as much as possible.  Unfortunately, the memcache-client library had not yet been updated to use the new protocol, forcing me to use the older, less efficient protocol.&lt;/p&gt;

&lt;p&gt;As it turned out, fretting over the application protocol was not time well spent; unbeknownst to me, memcache has a 1 MB limit on the size of an object being stored and I was storing rather large hashes.  Although the limit can be configured at compilation time, preliminary research indicated this was not a recommended practice.  Even if it worked, the memcache-client lib has the 1 MB limit hardcoded to avoid network traffic for large data, so the gem would also have to be patched and recompiled.&lt;/p&gt;

&lt;h2&gt;Alternative Ruby Implementations&lt;/h2&gt;

&lt;p&gt;Throughout the course my Ruby implementation I used three of the major Ruby implementations.  I began with MRI (1.8.7p174) and moved to YARV (1.9.1p129) and ended up with JRuby 1.3.1 (1.8.6p287 compatible).  Most of the discussion up until now has focused on my use of MRI.  The following sections describe my experiences with alternative Ruby implementations.&lt;/p&gt;

&lt;h3&gt;YARV&lt;/h3&gt;

&lt;p&gt;I was excited at the prospect of being able to use Ruby 1.9 for a project.  My contest entry had a small number of dependencies to cope with so I thought my potentials for failure were limited.  Generally, things seemed to work well with YARV.  I definitely saw a speed improvement over MRI.  However, the ruby debug gem has not been updated for 1.9.  Not having a debugger is not acceptable for development, so I had to abandon this path.&lt;/p&gt;

&lt;h3&gt;JRuby&lt;/h3&gt;

&lt;p&gt;After having experienced issues with MRI &amp;amp; Ruby 1.9, JRuby ended up being my runtime of choice.  It was remarkably faster than MRI and did not suffer from the garbage collection issues.  Likewise, it had the full debugger support that Ruby 1.9 lacked.  However, there were several issues I ran into with JRuby.&lt;/p&gt;

&lt;h4&gt;Breaking the debugger with optimizations turned on&lt;/h4&gt;

&lt;p&gt;In order to maximize execution speed, I used the &lt;a href=&quot;http://kenai.com/projects/jruby/pages/PerformanceTuning#Using_JRuby_s_Fast_Mode&quot;&gt;--fast flag&lt;/a&gt;, which performs some bytecode optimizations especially suited for &lt;code&gt;Fixnum&lt;/code&gt; operations at the cost of compatibility with Ruby&#39;s stacktrace format.  Generally, this was acceptable because I could largely deduce what a problem was by unraveling the stacktrace by inspection.  The problem is that the Ruby debugger apparently relies quite heavily on its stacktrace format.  I was astonished by this finding, but I was unable to use the debugger until the &lt;code&gt;--fast&lt;/code&gt; flag was removed, forcing me to have to bounce from one to the other.&lt;/p&gt;

&lt;h4&gt;Lack of profiling tools&lt;/h4&gt;

&lt;p&gt;Discovering the source of massive heap use was difficult due to the lack of profiling tools for JRuby.  None of the standard Ruby ones seemed to work at all.  I tried to use &lt;a href=&quot;http://yourkit.com/&quot;&gt;YourKit for Java&lt;/a&gt;, which technically worked, but the class names did not match the Ruby ones and I think I was profiling more JRuby proper rather than my application.  Unable to make much use of the results, I abandoned the profiling effort and resorted to manual code analysis, something humans are notoriously bad at.&lt;/p&gt;

&lt;h4&gt;Debugger issues&lt;/h4&gt;

&lt;p&gt;I wrote most of my Ruby implementation using the &lt;a href=&quot;http://www.jetbrains.com/ruby/index.html&quot;&gt;RubyMine&lt;/a&gt; IDE.  RubyMine has an integrated graphical debugger, which worked fairly well.  I found that often, however, the debugger would detach itself from the process forcing me to start debugging from scratch.  It appears that this may be a problem with the ruby-debug-ide gem.  I noticed that the issue occurred more frequently with the 1.5 beta of RubyMine than it did with the stable 1.1.1 release, so I suspect it may have to do with RubyMine itself to some degree.  I also found it happened much more frequently with JRuby than it did with MRI.&lt;/p&gt;

&lt;h2&gt;The Switch to Java&lt;/h2&gt;

&lt;p&gt;Unhappy with the progress I had made with my Ruby-based contest entry, I made the decision to port the whole project over to Java.  It was something I was extremely remiss to do, but ultimately I wanted to see the performance impact would be.&lt;/p&gt;

&lt;h3&gt;Static type checking&lt;/h3&gt;

&lt;p&gt;Dealing with generics in Java is an abomination, but static type checking was of enormous use when porting the Ruby code over to Java.  One of the biggest headaches I had in Ruby was related to my used of the property named &quot;id.&quot;  When I had a rich object model, it wasn&#39;t a problem, but when I had to decompose that model I ran into all sorts problems because every object in Ruby has a default &quot;id&quot; property.  It became hard to keep track of what were domain model objects and what were simple Strings.  When porting over to Java, the distinction was quite clear and the IDE let me know immediately if I was using the wrong type.  Granted it was more verbose, but when running an application with long runtime characteristics, relying on runtime type checking can be a brutal cycle of run-wait-fix-repeat.&lt;/p&gt;

&lt;h3&gt;Fast execution&lt;/h3&gt;

&lt;p&gt;My initial data load went down from about 2.5 minutes in JRuby (the fastest Ruby implementation I tried) to about 8 seconds in Java.  The gain was so great that I was convinced I had made a mistake somewhere.  Fortunately, I had a test suite to help indicate otherwise.&lt;/p&gt;

&lt;p&gt;My best explanation for the difference in execution times is that Java must handle object creation much faster than JRuby can, despite both of them running on the JVM.  All this particular section of code did was iterate through the data files and create my watcher and repository representations.  That is to say, at this stage no &quot;real work&quot; had yet been performed.&lt;/p&gt;

&lt;h3&gt;Handling large object graph easily&lt;/h3&gt;

&lt;p&gt;During my translation from Ruby to Java I migrated back to a rich object model.  Whereas I had to break down true bi-directional associations into hash lookups just to make my Ruby implementation run, Java could handle my full object graph quite easily.  As a result, the code was much more straightforward.  Additionally, I was able to cache values in memory judiciously without eating up the entire heap or breaking the garbage collector.  This helped in making the overall solution faster.&lt;/p&gt;

&lt;h3&gt;Built-in thread pooling with producer / consumer model&lt;/h3&gt;

&lt;p&gt;In my Ruby implementation I wrote my own poor man&#39;s thread pool, used in conjunction with &lt;a href=&quot;http://kenai.com/projects/jruby/pages/PerformanceTuning#Enabling_Thread_Pooling&quot;&gt;JRuby&#39;s native thread pool&lt;/a&gt;.  The former allowed me to do concurrent execution of point comparisons while the latter allowed me to reuse discarded native threads.  While my pool did work, I didn&#39;t abstract it very well and had to drain it frequently lest I ran out of stack space.  I&#39;m still amazed I couldn&#39;t find anything in the Ruby standard library or even a widely used third party gem for thread pooling.&lt;/p&gt;

&lt;p&gt;While constructing threads in Java is not as nice as in Ruby, Java 5 introduced a set of concurrency APIs that remove a lot of the pain with thread management.  Creating a thread pool and using a producer / consumer model backed by the pool was trivial to do.  It was a small thing, but it meant I didn&#39;t have to worry about managing the pool in my code and I had a high degree of confidence that the JDK&#39;s implementation was correct.  The JVM&#39;s native threads scheduling on multiple cores and the easy-to-use thread pool helped increase the throughput of my contest entry.&lt;/p&gt;

&lt;h3&gt;Profiling tools&lt;/h3&gt;

&lt;p&gt;The JVM makes it very easy to profile a running Java application.  I used YourKit for Java on my entry early on when it felt slow.  I found a few problems areas and addressed them, allowing the program to run an order of magnitude faster.  This whole process didn&#39;t take much more than a couple hours in contrast to the many hours I spent, with minimal results, trying to do the same thing by inspection with my Ruby implementation.&lt;/p&gt;

&lt;h3&gt;Debugger&lt;/h3&gt;

&lt;p&gt;Debugging applications in Java is quite simple.  The tools for doing so have been around a long time and are generally quite solid.  I used &lt;a href=&quot;http://www.jetbrains.com/idea/index.html&quot;&gt;IntelliJ IDEA&lt;/a&gt; as my primary development tool for the Java-based solution and relied on its graphical debugger for solving various problems.  Not having a debugger that disconnects from its process should be a given, but happened all too frequently with RubyMine &amp;amp; JRuby.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;After three days of porting, my first run of the Java implementation yielded a 36% prediction accuracy and ran in less than 10 minutes.  My best Ruby implementation, after weeks of development, only had a 31% prediction accuracy and took almost 7 hours to compute it.  With a few more hours of work the Java implementation broke 40% accuracy and ran in less than 3 minutes.  Unfortunately, at this point I became ill and by the time I recovered the contest had ended.&lt;/p&gt;

&lt;p&gt;My takeaway from the project is that Ruby is a great language hampered by a terrible execution environment.  When writing Rails apps, this usually isn&#39;t a problem.  I&#39;d even go so far as to say for most types of applications it shouldn&#39;t be a problem.  For anything that&#39;s heavily CPU bound or dealing with large object graphs, however, I don&#39;t think Ruby is a suitable option.  In these cases, Ruby may best serve as a rapid prototyping tool.  By writing the code in Ruby first I had a clear approach to use when translating to Java.&lt;/p&gt;

&lt;p&gt;This was the first Java project I had written start to finish in a while.  Most of my Java work is on existing codebases.  I was pleasantly surprised to see how few issues I had with the &lt;a href=&quot;http://maven.apache.org/&quot;&gt;maven&lt;/a&gt; build system and it was nice to have a real profiler at my disposal; for much of my Ruby work I must rely on a hosted service for my profiling needs, which is less than ideal.  The Java language wasn&#39;t even that bad to write in.  I&#39;m convinced that if there were easier syntax for collection access and proper language property support that writing in Java may even be a pleasant experience.&lt;/p&gt;

&lt;p&gt;It seems Ruby and Java have become the two representatives for the dynamic versus static language debate.  It would be nice if some of the vitriol could be removed from the discussion and the two languages evaluated on their merits for particular tasks.  It should go without saying that every language has its place.  This exercise has given me a clearer understanding of where Ruby should and should not be used.  It also helped reassert to me what Java&#39;s strengths and weaknesses are.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GitHub Contest Recap</title>
   <link href="http://nirvdrum.com/2009/09/03/github-contest-recap.html"/>
   <updated>2009-09-03T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2009/09/03/github-contest-recap</id>
   <content type="html">&lt;p&gt;Recently I decided to throw my hat into the &lt;a href=&quot;http://contest.github.com/&quot;&gt;GitHub contest&lt;/a&gt; ring, the goal of which was to predict repositories that a GitHub user should watch.  It had been some years since I had really done anything intensive with artificial intelligence (AI) and I thought it would be fun.  I was also attracted to the bounty offered: an aged bottle of bourbon and a lifetime large GitHub account.  This post serves as my high-level recap of the contest.&lt;/p&gt;

&lt;p&gt;While I had never worked on a recommendation system per se, I had done work with classifiers before.  Looking at the problem, my gut reaction was that an &lt;a href=&quot;http://en.wikipedia.org/wiki/Instance-based_learning&quot;&gt;instance-based learning algorithm&lt;/a&gt;, such as &lt;a href=&quot;http://en.wikipedia.org/wiki/K-nearest_neighbor_algorithm&quot;&gt;k-nearest neighbors&lt;/a&gt;, would be the most effective approach.  I also anticipated the top three winning entries to end up somewhere in the 70 - 85% accuracy range.  As it turns out, the best accuracy at the end of the contest was 56%.  While it is possible that this prediction accuracy is the best that could be achieved with the data, my guess is the relatively short time allowed for the contest (roughly a month) made it difficult for a very strong entry in the contest.  Additionally, the prize offered likely only attracted amateur entries.  This is not to say the contestants were unskilled, just that I doubt the dedication shown for something such as the Netflix contest was exerted for the GitHub contest.&lt;/p&gt;

&lt;p&gt;I decided to use the &lt;a href=&quot;http://users.dsic.upv.es/~rparedes/english/research/CPW/index.html&quot;&gt;weighted k-nearest-neighbors&lt;/a&gt; algorithm as the basis for my submission.  In order to measure progress and avoid overfitting results, I used a &lt;a href=&quot;http://en.wikipedia.org/wiki/Stratified_sampling&quot;&gt;stratified&lt;/a&gt; n-fold cross validation evaluation strategy.  The idea behind n-fold cross validation is to partition the dataset into proper subsets (the &quot;fold&quot;) that each maintain the underlying distribution of the full dataset.  This consisted of taking a stratified sample (watcher ID, repository ID) pairings, using the repository ID as the class value.  Once the n folds are created, one is used as a test set while the other n - 1 are used for training; the process is repeated until every fold has the opportunity to be the test set (the cross validation).  The average of the observed accuracies is used to mitigate the effect &lt;a href=&quot;http://en.wikipedia.org/wiki/Cross-validation_%28statistics%29#Limitations_and_misuse&quot;&gt;potential sampling bias&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My first approach was not terribly efficient, but I had taken the engineering approach of making it correct and then making it fast.  I was quite surprised when my first pass wouldn&#39;t even run because it broke the MRI Ruby garbage collector.  This forced me to reduce the search space earlier than I had intended.  While I could have taken a stratified sample of the training data, I wanted to minimize data loss, so I opted to restructure the instance space into regions grouped by repository ancestry.  This reduced the instance space down from about 113,000 points to roughly 77,000 using 10 folds.  While an improvement, this reduced space still proved to be too large to perform full evaluations over doing pairwise comparisons (a O(n&lt;sup&gt;2&lt;/sup&gt;) approach).  Other pruning methods, such as removing regions with single repositories or single watchers, further reduced the search space, but at the cost of accuracy.&lt;/p&gt;

&lt;p&gt;The next step, thus, was to devise a search strategy that attempted to find the regions that the test instance belonged to, while avoiding those that the instance did not.  I tried several heuristics with varying degrees of success.  Empirical evidence suggested that if a test instance either watched 25% or more of an owner&#39;s repositories or 25% of the test instance&#39;s repositories were owned by the same person, that the test instance would be likely to watch other repositories owned by that person.  For my final submission the search heuristic I used considered all the regions that the test instance was already known to belong to and regions that contained repositories that were owned by any repository owner that the test instance was known to watch a substantial portion of.&lt;/p&gt;

&lt;p&gt;Simply finding the correct regions wasn&#39;t sufficient, however.  Once the regions were chosen there was still the matter of choosing the correct repositories from those regions.  I found that using the most forked repository per region was generally the correct one.  A minor accuracy boost was achieved by evaluating the parent of any repository that a test instance was known to be watching, working under the observation that watchers tended to watch parent repositories when watching one of that repository&#39;s children.&lt;/p&gt;

&lt;p&gt;Evaluations were performed by calculating the &lt;a href=&quot;http://en.wikipedia.org/wiki/Euclidean_distance&quot;&gt;Euclidian distance&lt;/a&gt; between two repositories.  My first approaches were pure distances and yielded symmetric results.  As the project evolved, however, I found myself augmenting the definition of distance to be a route taken between two repositories by a given training instance and even adopted some aspects of &lt;a href=&quot;http://en.wikipedia.org/wiki/Hamming_distance&quot;&gt;Hamming distance&lt;/a&gt;.  This meant that for two repositories r&lt;sub&gt;1&lt;/sub&gt; and r&lt;sub&gt;2&lt;/sub&gt;, given training instances t&lt;sub&gt;1&lt;/sub&gt; and t&lt;sub&gt;2&lt;/sub&gt;, the distance between r&lt;sub&gt;1&lt;/sub&gt; and r&lt;sub&gt;2&lt;/sub&gt; could vary depending on characteristics of t&lt;sub&gt;1&lt;/sub&gt; and t&lt;sub&gt;2&lt;/sub&gt;.  While this may not be a strict Euclidian distance calculation, I likened it to modes of transportation.  E.g., the distance between two city centers may be fixed for a straight line, but can vary considerably if one chooses to walk versus take a train.&lt;/p&gt;

&lt;p&gt;The distance calculation weighted different attributes based upon observations of the shape of the training data.  The attributes I ended up using were: parent-child relationships, general common ancestry, common owner, and common watchers.  I had planned on using a genetic algorithm to optimize the weighting system, but ran out of time before the end of the contest.&lt;/p&gt;

&lt;p&gt;I had two goals when starting this project: 1) win the contest; and 2) learn more about Ruby.  Unfortunately, achieving the latter may have come at the expense of the former.  In the end, I achieved slightly over 40% accuracy, which was a far cry from where I had expected to end up and wasn&#39;t enough to win the contest.  My original choice of technology stack was not appropriate.  In most of my previous AI projects I used Java with a smattering Python and to a lesser extent, ML and LISP.  Having been using Ruby as my primary programming language for the past year and a half, I thought I would use it for my contest entry.  I spent roughly three weeks trying to optimize a Ruby solution that could only achieve 31% accuracy after a seven hour run on a quad core machine with 4 GB RAM.  During the last week of the contest, I rewrote the project in Java and achieved 40% accuracy with a 10 minute long run on a dual core MacBook Pro.  I plan on elaborating on that a bit in a future post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Edit: (Sept. 17, 2009) I&#39;ve now published the &lt;a href=&quot;http://nirvdrum.com/2009/09/17/lessons-learned-in-large-computations-with-ruby.html&quot;&gt;post comparing my Ruby and Java entries&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code for my entry can be found on &lt;a href=&quot;http://github.com/nirvdrum/github-contest-java/tree/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nesting alias_method_chain Calls</title>
   <link href="http://nirvdrum.com/2009/05/15/alias-method-chain-closure-issue.html"/>
   <updated>2009-05-15T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2009/05/15/alias-method-chain-closure-issue</id>
   <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Rails provides a nifty utility in ActiveSupport called &lt;code&gt;alias_method_chain&lt;/code&gt;. For those not familiar with it, it simplifies the task of &quot;replacing&quot; an already defined method with an augmented one. The new method is aliased to the name of the original method and the original method is aliased to some other name in order that it may still be referenced.&lt;/p&gt;

&lt;p&gt;More succinctly, the following call:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
alias_method_chain :number_printer, :filter
&lt;/pre&gt;


&lt;p&gt;is effectively the same as:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
alias_method :number_printer_without_filter, :number_printer
alias_method :number_printer, :number_printer_with_filter
&lt;/pre&gt;


&lt;p&gt;Fig. 1 illustrates how the &lt;code&gt;alias_method_chain&lt;/code&gt; call changes references to the method definitions like so:&lt;/p&gt;

&lt;div class=&quot;figure&quot;&gt;
  &lt;img src=&quot;/images/alias-method-chain-closure-issue/alias_method_chain.png&quot; /&gt;
  
  Fig. 1: Results of alias_method_chain call.
&lt;/div&gt;


&lt;p&gt;Now the original method defined as &lt;code&gt;:number_printer&lt;/code&gt; is referenced as &lt;code&gt;:number_printer_without_filter&lt;/code&gt;.  &lt;code&gt;:number_printer&lt;/code&gt; now points to the method definition for &lt;code&gt;:number_printer_with_filter&lt;/code&gt;, which can be referenced as either &lt;code&gt;:number_printer&lt;/code&gt; or &lt;code&gt;:number_printer_with_filter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This implies that prior to the execution of the &lt;code&gt;alias_method_chain&lt;/code&gt; call, you must define both methods &lt;code&gt;:number_printer&lt;/code&gt; and &lt;code&gt;:number_printer_with_filter&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Motivating Example&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;http://github.com/haruska/ninja-decorators/&quot;&gt;ninja-decorators project&lt;/a&gt; relies heavily on &lt;code&gt;alias_method_chain&lt;/code&gt; and its usage will be used as the example throughout the remainder of the article.  ninja-decorators gives you &lt;code&gt;before_filter&lt;/code&gt;, &lt;code&gt;after_filter&lt;/code&gt;, and &lt;code&gt;around_filter&lt;/code&gt; functionality outside of Rails controllers.  With these methods you can handle cross-cutting concerns in a class located elsewhere in your Rails app or without having to use Rails at all.  Using the standard examples of security and logging as cross-cutting concerns, we have something like the following:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
around_filter :secure_around, [:number_printer]
around_filter :log_around, [:number_printer]
&lt;/pre&gt;


&lt;p&gt;Here, we want &lt;code&gt;:log_around&lt;/code&gt; to decorate &lt;code&gt;:number_printer&lt;/code&gt; with &lt;code&gt;:secure_around&lt;/code&gt; applied.  Internally, &lt;code&gt;around_filter&lt;/code&gt; delegates to &lt;code&gt;alias_method_chain&lt;/code&gt; to handle method decoration.&lt;/p&gt;

&lt;h2&gt;Problem&lt;/h2&gt;

&lt;p&gt;The problem with the implementation of &lt;code&gt;alias_method_chain&lt;/code&gt; is one of definition order with regards to its two internal &lt;code&gt;alias_method&lt;/code&gt; calls.  If the new head of the chain is an enhancement of an existing method in the chain, there likely exists a coupling between the two.  Since the &lt;code&gt;alias_method_chain&lt;/code&gt; call is effectively atomic, however, this complicates how the two methods reference each other. Fig. 2 shows the intermittent states between each of the two &lt;code&gt;alias_method&lt;/code&gt; calls made internally by &lt;code&gt;alias_method_chain&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;figure&quot;&gt;
  &lt;img src=&quot;/images/alias-method-chain-closure-issue/alias_method_chain_detailed.png&quot; /&gt;
  
  Figure 2: Detailed breakdown of alias_method_chain mechanics.
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;:number_printer_without_filter&lt;/code&gt; will not exist until after the &lt;code&gt;alias_method_chain&lt;/code&gt; call is complete. &lt;code&gt;:number_printer_with_filter&lt;/code&gt; must exist before the &lt;code&gt;alias_method_chain&lt;/code&gt; call can begin, otherwise the second &lt;code&gt;alias_method&lt;/code&gt; call made internally will fail.  As a consequence, &lt;code&gt;:number_printer_with_filter&lt;/code&gt; must call &lt;code&gt;:number_printer_without_filter&lt;/code&gt; dynamically.  As long as you only use one level of &lt;code&gt;alias_method_chain&lt;/code&gt; calls, this isn&#39;t a problem.  With multiple levels of chaining, however, dynamic calls like this fall apart.&lt;/p&gt;

&lt;p&gt;To make the discussion a little more concrete, we&#39;ll use the following example adapted from the ninja-decorators project.  It is a bit contrived, but should serve well enough as a basis for discussion.&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
require &#39;activesupport&#39;
  
class NumberFun
  def self.around_filter(around_method, method_names)
    method_names.each do |meth|
      define_method(&quot;#{meth}_with_around_filter&quot;) do |*args|        
        send(around_method, *args) do |*ar_args|
          send(&quot;#{meth}_without_around_filter&quot;, *ar_args)
        end
      end

      alias_method_chain meth, :around_filter
    end
  end

  def increment_filter(num)
    yield(num + 1)
  end

  def number_printer(num)
    puts num
  end

  def square_printer(num)
    puts num * num
  end

  around_filter :increment_filter, [:number_printer, :square_printer]
end
&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;:number_printer&lt;/code&gt; and &lt;code&gt;:square_printer&lt;/code&gt; are two simple methods.  They take a number in and print out its value or its square, respectively.  &lt;code&gt;:increment_filter&lt;/code&gt; is a simple &quot;around filter&quot;; it augments a method by incrementing the input argument by 1 before executing the original method.  Running both methods will produce the following in IRB:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
&gt;&gt; NumberFun.new.number_printer 3
4
=&gt; nil
&gt;&gt; NumberFun.new.square_printer 5
36
=&gt; nil
&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;around_filter&lt;/code&gt; is where all the hard work is being done and is where &lt;code&gt;alias_method_chain&lt;/code&gt; is employed.  It takes as its arguments a filter method name and a list of method names to decorate with that filter.  For each method to decorate it defines the required &quot;with&quot; method for &lt;code&gt;alias_method_chain&lt;/code&gt;.  This newly defined method will call the filter method (&lt;code&gt;:increment_filter&lt;/code&gt; in this case), which will in turn call the original, undecorated method (&lt;code&gt;:number_printer_without_increment_filter&lt;/code&gt; or &lt;code&gt;:square_printer_without_increment_filter&lt;/code&gt;) as a block.  Once the &quot;with&quot; method is defined,  &lt;code&gt;alias_method_chain&lt;/code&gt; is called so that the original method name can be used to transparently call the newly decorated method.&lt;/p&gt;

&lt;p&gt;While convoluted (don&#39;t worry, it&#39;s wrapped up a library), this approach will work dandily until you need to start decorating a method more than once.  For the sake of the example, we&#39;ll pretend that we actually want to increment each input argument as two.  In reality, well&#39;d likely want to apply a completely different filter.  The outcome is precisely the same, but to keep things simple, we&#39;ll just apply the &lt;code&gt;:increment_filter&lt;/code&gt; twice:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
around_filter :increment_filter, [:number_printer, :square_printer]
around_filter :increment_filter, [:number_printer, :square_printer]
&lt;/pre&gt;


&lt;p&gt;Running this through IRB again, we&#39;d likely expect to see &lt;code&gt;:number_printer&lt;/code&gt; print out &lt;code&gt;2 + num&lt;/code&gt; for argument &lt;code&gt;num&lt;/code&gt;.  Instead, the session looks like this:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
&gt;&gt; NumberFun.new.number_printer 3
SystemStackError: stack level too deep
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `send&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `number_printer_with_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `number_printer_without_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `send&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `number_printer_with_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:16:in `increment_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `send&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `number_printer_with_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `number_printer_without_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `send&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `number_printer_with_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:16:in `increment_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `send&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:6:in `number_printer_with_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `number_printer_without_around_filter&#39;
    from /Users/nirvdrum/dev/workspaces/alias_method_chain/blah.rb:7:in `send&#39;
... 7586 levels...
&lt;/pre&gt;


&lt;p&gt;That&#39;s the polite way of telling you that you have infinite recursion, not the expected value of 5.  The issue is that each &lt;code&gt;around_filter&lt;/code&gt; call defines a new &quot;with&quot; method that calls the &quot;without&quot; method dynamically.  Calling a method by name with &lt;code&gt;send&lt;/code&gt;, however, only calls the one at the current lexical scope.  Meanwhile, each call to &lt;code&gt;alias_method_chain&lt;/code&gt; changes the alias target of the &quot;without&quot; method.  As such, we have the execution flow illustrated in Fig. 3 rather than the expected one in Fig. 4.&lt;/p&gt;

&lt;div style=&quot;float: left; width: 100%; margin: 10px;&quot;&gt;
  &lt;div class=&quot;figure&quot; style=&quot;float: left; width: 50%;&quot;&gt;
    &lt;img src=&quot;/images/alias-method-chain-closure-issue/actual_nesting_behavior.png&quot; /&gt;
  
    Figure 3: Actual behavior when chaining &lt;code&gt;alias_method_chain&lt;/code&gt; calls.
  &lt;/div&gt;

  &lt;div class=&quot;figure&quot; style=&quot;float: left;&quot;&gt;
    &lt;img src=&quot;/images/alias-method-chain-closure-issue/expected_nesting_behavior.png&quot; /&gt;
  
    Figure 4: Expected behavior when chaining &lt;code&gt;alias_method_chain&lt;/code&gt; calls.
  &lt;/div&gt;
  
  &lt;p style=&quot;clear: both;&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;The key thing to note about the code behavior observed in Fig. 3 is that the second &lt;code&gt;alias_method_chain&lt;/code&gt; call will alias &lt;code&gt;:number_printer&lt;/code&gt; to &lt;code&gt;:number_printer_without_filter&lt;/code&gt;, just like the first call will.  However, after the first &lt;code&gt;alias_method_chain&lt;/code&gt; call is made, &lt;code&gt;:number_printer&lt;/code&gt; is aliased to the definition &lt;code&gt;:number_printer_with_filter&lt;/code&gt; (as seen in Fig. 2).  Calling &lt;code&gt;:number_printer&lt;/code&gt; at this point will call &lt;code&gt;:number_printer_with_filter&lt;/code&gt; because of the decoration and, subsequently, &lt;code&gt;:number_printer_with_filter&lt;/code&gt; will call &lt;code&gt;:number_printer_without_filter&lt;/code&gt;, the latter of which is now pointing at the definition of &lt;code&gt;:number_printer_with_filter&lt;/code&gt; as well.  That&#39;s a lot of words to say that we end up in a situation where &lt;code&gt;:number_printer_with_filter&lt;/code&gt; calls itself inadvertently and there&#39;s no base case to break out.&lt;/p&gt;

&lt;p&gt;There is no* clean way around this with &lt;code&gt;alias_method_chain&lt;/code&gt;.  It&#39;s a classic chicken-and-egg situation.  The best that can be done is for &lt;code&gt;around_filter&lt;/code&gt; to maintain a stack of &lt;code&gt;UnboundMethod&lt;/code&gt; objects in a class instance variable.  While doable, this resource management is error-prone and would have to be replicated by any method affected by the problem.  Effectively, it is the same process the VM would normally perform in managing stack frames at each recursion level, so it&#39;s best to let the VM do it.&lt;/p&gt;

&lt;p&gt;The problem can be averted with a minor change in &lt;code&gt;alias_method_chain&lt;/code&gt;.  The idea is to yield to a block between the two &lt;code&gt;alias_method&lt;/code&gt; calls, allowing the proper formation of closures to the &quot;without&quot; method.  Unfortunately, this is not backwards-compatible with Rails because &lt;code&gt;alias_method_chain&lt;/code&gt; yields to a block elsewhere for reasons that are not quite clear to me (I believe it&#39;s to handle method names with punctuation).&lt;/p&gt;

&lt;p&gt;A simplified definition is thus:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
def alias_method_chain(target, feature)
  with_method = &quot;#{target}_with_#{feature}&quot;
  without_method = &quot;#{target}_without_#{feature}&quot;

  alias_method without_method, target
  yield if block_given?
  alias_method target, with_method
end
&lt;/pre&gt;


&lt;p&gt;The block passed to alias_method_chain can then take care of the creation of the &quot;with&quot; method, which will have access to the &quot;without&quot; method at the current level.  Breaking away from &lt;code&gt;around_filter&lt;/code&gt;, we can more easily see how nested &lt;code&gt;alias_method_chain&lt;/code&gt; calls work with the new definition:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
class MoreNumberFun
  # Build up a proc that will construct the filtered method
  # Execution of the proc is delayed until we encounter the alias_method_chain call.
  filtered_method_builder = Proc.new do

    # Get a reference to the unfiltered method or, more accurately, the original method with
    # all previous filters already applied.  This new filtered method builds up on the filters
    # already applied.
    unfiltered_method = instance_method :number_printer_without_filter

    # Define the newly filtered method.
    define_method(&quot;number_printer_with_filter&quot;) do |*args|
      unfiltered_method.bind(self).call(args.first + 1)
    end
  end

  def number_printer(num)
    puts num
  end

  alias_method_chain :number_printer, :filter, &amp;filtered_method_builder
  alias_method_chain :number_printer, :filter, &amp;filtered_method_builder
end
&lt;/pre&gt;


&lt;p&gt;In this admittedly convoluted example, the block passed to the &lt;code&gt;alias_method_chain&lt;/code&gt; calls is built up as a proc first.  This allows us to make the same &lt;code&gt;alias_method_chain&lt;/code&gt; calls without needing to duplicate code.  The proc gets a reference to &lt;code&gt;:number_printer_without_filter&lt;/code&gt; and calls it within the newly defined &lt;code&gt;:number_printer_with_filter&lt;/code&gt;, which for simplicity in the example, provides the same behavior that &lt;code&gt;:increment_filter&lt;/code&gt; previously did.  This forms a closure and lets each level of &quot;with&quot; and &quot;without&quot; methods to pair up, subsequently avoiding the infinite recursion problem when using just &lt;code&gt;send&lt;/code&gt; alone.&lt;/p&gt;

&lt;p&gt;Running in IRB now, we get the expected behavior of print out of &lt;code&gt;2 + num&lt;/code&gt; for argument &lt;code&gt;num&lt;/code&gt;, rather than the stack overflow exception we previously experienced:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
&gt;&gt; MoreNumberFun.new.number_printer 3
5
=&gt; nil
&lt;/pre&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I began writing this post just to document the changes necessary to alias_method_chain in order to make ninja-decorators work.  If this work could make its way back into Rails core, great.  Otherwise, it serves as a decent rationale document.  If you&#39;ve run into similar issues yourself, you should now know why and how to work around them.  One issue not addressed here is reordering the chain or removing links from the chain.  Since each link has a tight coupling at the time of definition, altering the chain via anything other than an append/prepend may be confusing.&lt;/p&gt;

&lt;p&gt;* I suspect someone much smarter than me knows a way.  After a couple days on the issue, I couldn&#39;t come up with anything.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Composite Index Problem with PostgreSQL and Rails 2.x</title>
   <link href="http://nirvdrum.com/2009/04/26/composite-index-problem-with-postgresql-and-rails-2.x.html"/>
   <updated>2009-04-26T00:00:00+00:00</updated>
   <id>http://nirvdrum.com/2009/04/26/composite-index-problem-with-postgresql-and-rails-2.x</id>
   <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Recently I ran into an issue with using composite indices in PostgreSQL and Rails 2.3.2.  I only managed to
catch the problem by using the &lt;a href=&quot;http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActiveRecord/Macros.html#M000057&quot;&gt;shoulda should_have_index&lt;/a&gt; macro.
This macro asserts that an index appears on a list of columns.  Since it is a list, the order of the columns is
in fact significant.&lt;/p&gt;

&lt;h2&gt;Problem&lt;/h2&gt;

&lt;p&gt;The problem is that given a table with the following definition:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
  create_table &quot;video_games&quot;, :force =&gt; true do |t|
    t.string   &quot;asin&quot;
    t.integer  &quot;user_id&quot;, :null =&gt; false
  end
&lt;/pre&gt;


&lt;p&gt;and the following migration:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
  add_index :video_games, [:user_id, :asin], :unique =&gt; true
&lt;/pre&gt;


&lt;p&gt;the schema dumper for the ActiveRecord PostgreSQL adapter may actually produce the following in schema.rb:&lt;/p&gt;

&lt;pre class=&quot;brush:ruby&quot;&gt;
  add_index &quot;video_games&quot;, [&quot;asin&quot;, &quot;user_id&quot;],
    :name =&gt; &quot;index_video_games_on_user_id_and_asin&quot;,
    :unique =&gt; true
&lt;/pre&gt;


&lt;p&gt;The distinction here is subtle, but important.  In the migration, I declared the index should be on the tuple &lt;code&gt;(user_id, asin)&lt;/code&gt; and the schema dumper in turn generated code that would add a tuple on &lt;code&gt;(asin, user_id)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The issue was with the way that the adapter was fetching the index data.  It issued a query against PostgreSQL&#39;s
maintenance tables to reconstruct the index pseudo-DDL statement.  The query used in Rails 2.3.2 is:&lt;/p&gt;

&lt;pre class=&quot;brush:sql&quot;&gt;
  SELECT distinct i.relname, d.indisunique, a.attname
     FROM pg_class t, pg_class i, pg_index d, pg_attribute a
   WHERE i.relkind = &#39;i&#39;
     AND d.indexrelid = i.oid
     AND d.indisprimary = &#39;f&#39;
     AND t.oid = d.indrelid
     AND t.relname = &#39;#{table_name}&#39;
     AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) )
     AND a.attrelid = t.oid
     AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum
        OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum
        OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum
        OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum
        OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )
  ORDER BY i.relname
&lt;/pre&gt;


&lt;p&gt;There&#39;s a lot going on there that may be hard to follow.  The query returns the index name (&lt;code&gt;i.relname&lt;/code&gt;),
a Boolean indicating whether or not the index is unique (&lt;code&gt;d.indisunique&lt;/code&gt;), and a member column of the index (&lt;code&gt;a.attname&lt;/code&gt;).  For
composite indices, there are multiple rows, one for each member column.&lt;/p&gt;

&lt;p&gt;The important thing to note is that &lt;code&gt;d.indkey&lt;/code&gt; is a PostgreSQL array type (&lt;code&gt;int2vector&lt;/code&gt;) that contains a list
of column positions for member columns of the index.  As can be seen by the query, there is no explicit ordering
of the &lt;code&gt;a.attname&lt;/code&gt;, so PostgreSQL is free to return the rows in any order it wishes.  In PostgreSQL 8.3, this ordering
appears to be attribute&#39;s positional index, in ascending order.  Please not that I have not consulted the
PostgreSQL source to verify this.  Suffice it to say, the returned ordering should not be relied upon and is
not guaranteed to match the order in &lt;code&gt;d.indkey&lt;/code&gt;.  The problem is that the schema dumper did in fact rely on this order.&lt;/p&gt;

&lt;p&gt;As an aside, there is another problem with this query.  It will only index 10 elements of the d.indkey array, leading
to a ceiling of 10 columns per index.  This is a Rails-imposed limit.  As of at least PostgreSQL 7.4, that limit is
32 by default and can be configured higher at compile-time.&lt;/p&gt;

&lt;h2&gt;Resolution&lt;/h2&gt;

&lt;p&gt;Both issues were fixed as of April 21, 2009 with the closing of &lt;a href=&quot;https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2515&quot;&gt;Rails ticket #2515&lt;/a&gt;, nearly 3.5 years after the problem
was first introduced on September 23, 2005.  Interestingly, the problem was reported by three different parties
in April 2009.  Between the time I came across it and then eventually came up with a fix and filed a ticket, someone else reported the issue and fixed it.  So, that&#39;s how I ended up with this analysis of a problem that in the end I didn&#39;t have to solve.&lt;/p&gt;

&lt;p&gt;Interestingly, the issue shows up with &lt;code&gt;rake db:test:load&lt;/code&gt; but not &lt;code&gt;rake db:test:clone_structure&lt;/code&gt; because the
former uses the ActiveRecord PostgreSQL adapter&#39;s implementation of schema dumping and loading, whereas the latter
uses the pg_dump tool to create a DDL file.  &lt;code&gt;rake db:test:prepare&lt;/code&gt; does a &lt;code&gt;clone_structure&lt;/code&gt; followed by a &lt;code&gt;load&lt;/code&gt;,
which yields a test database that does not match the correct one used in development.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
