{"id":171,"date":"2006-01-14T23:14:02","date_gmt":"2006-01-14T12:14:02","guid":{"rendered":"http:\/\/www.somethinkodd.com\/oddthinking\/2006\/01\/14\/rational-1000-version-control-war-story\/"},"modified":"2006-10-09T18:09:16","modified_gmt":"2006-10-09T07:09:16","slug":"rational-1000-version-control-war-story","status":"publish","type":"post","link":"https:\/\/www.somethinkodd.com\/oddthinking\/2006\/01\/14\/rational-1000-version-control-war-story\/","title":{"rendered":"Rational 1000: A Version Control War Story"},"content":{"rendered":"<p><div class=\"aside\">This is one of a <a href=\"http:\/\/www.somethinkodd.com\/oddthinking\/category\/rat1000\/\">not so short series<\/a> of nostalgic reminiscences about the Rational 1000.<\/div>\n<\/p>\n<h4>Taking Over Before a Deadline<\/h4>\n<p>My cow-orker, Greg, had worked for some time on a software component, when he was dragged onto another part of the project at short notice, and I was asked to take over his work.<\/p>\n<p>There wasn&#8217;t much to do on the component &#8211; perhaps a couple of weeks&#8217; work &#8211; but the deadline was a big one; it had to be finished by the end of the last Friday of the month to be part of a major delivery. I actually completed the last of the work on the Thursday afternoon before the deadline. All that remained to do was to &#8220;check in&#8221; the files &#8211; to mark them as officially delivered so that the weekend compilation process would include them in the next version of the software.<\/p>\n<h4>Slow Diff<\/h4>\n<p>Have I mentioned that the Rational 1000 was slow? <\/p>\n<p>One of the slowest operations was the check-in operation. A check-in operation was like an elaborate save command, that told other developers that this particular file was ready to be used.<\/p>\n<p>The check-in operation would produce a list of differences between the latest version of the file and the previous one; it is a standard part of compressing the storage of multiple versions of the code. Unfortunately the diff function (that found the differences) was particularly inefficient on the Rational.<\/p>\n<p>A simple check-in would take at least 1 or 2 minutes to run. I had heard complaints that a complex check-in would take over an hour to run!<\/p>\n<h4>Performing the Check-In<\/h4>\n<p>Rather than wait, I left the check-in process running when I went home on Thursday night, patting myself on the back for finishing a full day early before a major deadline.<\/p>\n<p>When I came in on Friday morning, I found the check-in process had frozen up. That wasn&#8217;t such an unusual occurrence. I simply aborted it, and ran it again.<\/p>\n<p>About an hour later, a horrid thought occurred to me&#8230; To explain it, I need to give some background.<\/p>\n<h4>Unit Testing<\/h4>\n<p>The Rational 1000 had a built-in Unit Test infrastructure. <\/p>\n<p>All the unit tests for a component could be placed in a folder. In another folder, you could put the &#8220;Golden Results&#8221; &#8211; a set of files containing the expected output (with a few regular expressions to handle expected variations like timestamps).<\/p>\n<p>With one button, all the tests would be run, and the output redirected to another folder. It would then be compared against the Golden Results, and an appropriate report produced.<\/p>\n<p>These types of unit-testing environments have become popular now, but at the time it was a great improvement over the other IDEs I had used.<\/p>\n<h4>Unit Testing Approach<\/h4>\n<p>Greg used an interesting tactic in the generation of his Golden Results. He computed the results of various functions, and put a lot of effort in outputting their values in the same format as Ada literals. (If you are familiar with the Python <a href=\"http:\/\/www.python.org\/doc\/current\/ref\/customization.html#l2h-179\"><code>repr()<\/code><\/a> function, you&#8217;ll understand the kind of code he wrote.)<\/p>\n<p>His unit tests generated 20,000 lines of output, which he added to the Golden Results, and then methodically worked through each line, reviewing its accuracy. As he reviewed a data structure, and confirmed that it was the result that he was happy with, he replaced the output code with an assert statement (or at least an equivalent <code>if<\/code> statement.)<\/p>\n<p>My Ada is pretty rusty, but let me try an example. The first round of the code might have looked like this:<\/p>\n<pre><code>result := Shakespeare.Get_First_Name();\r\nAda.Text_IO.Put_Line(\"\"\"\" & result & \"\"\"\");<\/code><\/pre>\n<p>and used to output:<\/p>\n<blockquote><p>&#8220;William&#8221;<\/p><\/blockquote>\n<p>Having carefully checked that <em>William<\/em> was the right result, Greg substituted in the generated literals:<\/p>\n<pre><code>result := Shakespeare.Get_First_Name();\r\nif result =\"William\" then\r\n    Ada.Text_IO.Put_Line(\"OK\");\r\nelse\r\n    Ada.Text_IO.Put_Line(\"Failed\");\r\nend if;\r\n<\/code><\/pre>\n<p>which would output:<\/p>\n<blockquote><p>OK<\/p><\/blockquote>\n<p>It was really easy to see whether the tests worked after this. Instead of 20,000 lines full of hard-to-check values, there were 500 lines of &#8220;OK&#8221; printed. A nice trick, Greg!<\/p>\n<h4>Horrid Realisation<\/h4>\n<p>So my horrid thought was the realisation that Rational&#8217;s incredibly slow diff function, running as part of the check-in process, was trying hard to match up the lines between a 20,000 lines of Ada-ish code, and 500 lines of output that simply said &#8220;OK&#8221;. There was nothing in common between the two files, but the check-in process didn&#8217;t know that.<\/p>\n<p>The check-in process I had aborted in the morning hadn&#8217;t frozen overnight.  <strong>It was still alive when I killed it!<\/strong>  Repeating the check-in process was going to take over 16 hours, but I had about 7 left before my deadline! I wasn&#8217;t going to make it, because I couldn&#8217;t save Greg&#8217;s file in time!<\/p>\n<h4>Coda<\/h4>\n<p>Careful grovelling got me special dispensation from my boss&#8217;s boss to deliver the code without delivering the Golden Results. I tried moving the two versions of the file onto a nearby VAX VMS machine, and ran the &#8220;diff&#8221; command there; it ran in under five seconds!<\/p>\n<p>The experience left a bad taste in my mouth. A year or two later, I got the opportunity to choose an algorithm to analyse a part of an algorithms course. I chose &#8220;diff&#8221;, in an attempt to understand the tradeoffs between choices in the diff algorithm that might explain the large discrepancy.  I was left unsatisfied; even the most basic implementations of diff do not have scalability issues in handling very large files which are nothing like each other. I still have no idea why the Rational diff command was so slow.<\/p>\n<div class=\"aside\">Update: Corrected line counts<\/div>\n","protected":false},"excerpt":{"rendered":"<p>About an hour after I started the check-in process, a horrid thought occurred to me&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_s2mail":"","footnotes":""},"categories":[23,35,25,42],"tags":[],"class_list":["post-171","post","type-post","status-publish","format-standard","hentry","category-based-on-a-true-story","category-heroic-failures","category-insufficiently-advanced-technology","category-rat1000"],"_links":{"self":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/comments?post=171"}],"version-history":[{"count":0,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/posts\/171\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/media?parent=171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/categories?post=171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.somethinkodd.com\/oddthinking\/wp-json\/wp\/v2\/tags?post=171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}