<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6413447460022831327</id><updated>2012-02-16T07:08:02.323-08:00</updated><title type='text'>Tomy's Blog At the End of Teh Internets</title><subtitle type='html'>Exploring the world through hacking.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-5337949986727144437</id><published>2008-07-07T20:54:00.000-07:00</published><updated>2008-07-07T21:06:17.535-07:00</updated><title type='text'>A Unified Runtime for Dynamic Languages.</title><content type='html'>&lt;a href="http://cs.swan.ac.uk/~csdavec/libobjc/libobjc.pdf"&gt;This&lt;/a&gt; seems like a great starting point for a unified runtime for a large set of dynamic languages. Having studied the Ruby runtime, I believe it could be implemented in a prototype-based language. Imagine Ruby, Javascript, Smalltalk, and Objective-C all living in the same runtime.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I've been chomping at the bit to do something with &lt;a href="http://www.llvm.org"&gt;LLVM&lt;/a&gt;, and combining this runtime with JIT's for Ruby and Javascript seems like the Holy Grail to me.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Combined with all the optimizations that the Self guys pioneered, and the fact that Gnustep/Cocoa/NextStep has to be the least painful way I've found to develop GUI apps, this is something I plan on pursuing Real Soon Now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-5337949986727144437?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/5337949986727144437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=5337949986727144437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/5337949986727144437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/5337949986727144437'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/07/unified-runtime-for-dynamic-languages.html' title='A Unified Runtime for Dynamic Languages.'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-5309919565608868057</id><published>2008-06-25T15:54:00.000-07:00</published><updated>2008-06-25T16:49:38.881-07:00</updated><title type='text'>VALUE: One thing to reference them all.</title><content type='html'>Common to the implementation of a lot of Lisps, Schemes, and other dynamic languages is VALUE. These usually hold a pointer to whatever is considered an object in the system. For performance reasons, some values are stored directly in the VALUE, commonly called 'immediate values'. Since pointers are 4-byte aligned on modern architectures, we know that any value with the final two bits set to 1, 2, or 3 isn't a pointer to some heap or stack allocated object, and we can use this to our advantage to store immediate values for things like integers that would be too costly to allocate. Ruby does this by left shifting integers on bit and adding one to them. Thus, value with the low bit set is an integer (Fixnum) and it's value can be found by right shifting one bit. Ruby uses a special macro for this to handle architectures that don't preserve the sign bit in right shifts. Though I don't know what architectures do this, I do know that LLVM has a instruction that specifically preserves this bit.&lt;br /&gt;&lt;br /&gt;Also in Ruby, false, or Qfalse in the C code, is implemented as 0x00, Qtrue is 0x02, and Qnil is 0x04.&lt;br /&gt;&lt;br /&gt;There are other ways to do this. Ages ago I worked on a system called LeLisp, which used separate memory zones for each type of object. Thus no tagging was necessary, you just rounded the address and it gave you a zone type address.&lt;br /&gt;&lt;br /&gt;I was reading a paper the other day on &lt;a href="http://citeseer.ist.psu.edu/342939.html"&gt;implementing Scheme for microcontrollers&lt;/a&gt;, and it gives a good overview of the various methods of implementing VALUE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-5309919565608868057?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/5309919565608868057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=5309919565608868057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/5309919565608868057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/5309919565608868057'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/value-one-thing-to-reference-them-all.html' title='VALUE: One thing to reference them all.'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-1192321152955300291</id><published>2008-06-12T18:37:00.000-07:00</published><updated>2008-06-12T19:35:15.839-07:00</updated><title type='text'></title><content type='html'>Lately I've been working on a new hash table implementation, combining ideas from several papers, and benchmarking every little idiom. As impressive as modern compiler optimization has become, it's still interesting to find amazing speedups you can achieve by avoiding conditionals. For example, I have a Bucket class that holds up to four items. Now I could store the count of items in the bucket, or I could count them on demand, an issue of speed versus memory. Should I choose to count them, then how I choose to count them becomes important. The naive way might look like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;size_t size(char* keys)&lt;br /&gt;{&lt;br /&gt; int i;&lt;br /&gt; int count = 0;&lt;br /&gt; for (i = 0; i &amp;lt; 4; ++i)&lt;br /&gt;    if (keys[i] &gt; 0)&lt;br /&gt;      count++;&lt;br /&gt;  return count;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I won't bore you with the body of main that I used to test this with, but basically calling this MAX_INT times, (and doing something with the return so the compiler won't optimize it all away), I get these times on a 1.8 mhz core duo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;real 0m12.796s&lt;br /&gt;user 0m12.785s&lt;br /&gt;sys 0m0.000s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So lets look at an unconventional way to compute size:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int size(char* keys)&lt;br /&gt;{&lt;br /&gt; return (keys[0] != 0) +&lt;br /&gt;   (keys[1] != 0) +&lt;br /&gt;   (keys[2] != 0) +&lt;br /&gt;   (keys[3] != 0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This version, in the same loop as the previous example, turns in the following times:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;real 0m0.004s&lt;br /&gt;user 0m0.004s&lt;br /&gt;sys 0m0.000s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Oh, yeah. Considering this function can get called on every insertion in my modified Cuckoo Hash, this is a big improvement. Obviously the new hand unrolled version isn't as flexible wrt bucket size, so let's see how a hybrid approach might perform:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int size(char* keys, size_t bsize)&lt;br /&gt;{&lt;br /&gt; unsigned int count = 0;&lt;br /&gt; int i;&lt;br /&gt;&lt;br /&gt; for (i = 0; i &amp;lt; bsize; ++i)&lt;br /&gt;    count += (keys[i] != 0);&lt;br /&gt;  return count;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Okay this still performs better than the original:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;real 0m2.200s&lt;br /&gt;user 0m2.196s&lt;br /&gt;sys 0m0.004s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Not quite as good, but still better if you need the flexibility of specifying array size at runtime. I'm sure there's a way to describe a recursive C++ template to get the benefit of the unrolled version if you are content to specify array size at compile time.&lt;br /&gt;&lt;br /&gt;Of course, the unrolled version could also use SIMD instructions for an even greater speedup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-1192321152955300291?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/1192321152955300291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=1192321152955300291' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/1192321152955300291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/1192321152955300291'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/lately-ive-been-working-on-new-hash.html' title=''/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-4578253490867559227</id><published>2008-06-04T22:45:00.000-07:00</published><updated>2008-06-04T23:11:51.883-07:00</updated><title type='text'>I Hate Virtual Machines</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When I first started working at Amazon, a change to one of their low-level libraries would trigger a rebuild that could take a week to recompile all affected packages. My focus was improving their build times. One build tool, used to convert IDL-like descriptions to code, and might be invoked a hundred times for a given library, was written in Java. For the hell of it, I wrote a program in C++ that would produce the same output for a given input. It could be invoked eighty times for each single invocation of the original Java program. So when some Java apologist suggests that "Java is as fast as C or C++", they always fail to mention the head start you need to give them (note the speed tests in the Computer Language Shootout are for Java Server, which means I have to have the damn virtual machine running and taking up memory even when I am not using it). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ultimately the solution to Amazon's build times involved dependency analysis and parallelization in a multi-machine build farm. But I stand by my hatred of all current virtual machine implementations. Anyone who writes a command line tool in Java, Smalltalk, Lisp, C#, or any other language implementation that takes longer to start up than actually compute the solution should be castrated so that their defective genes are not passed on to future generations.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;How about a virtual machine that did some partial evaluation to reduce the solution to something that didn't require the entire 'X' class library? In other words, a compiler that created a new smaller virtual machine based on the input text. Of course, in dynamic languages, if the evil "eval" is used, then you need to include everything. But how many real programs need this?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-4578253490867559227?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/4578253490867559227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=4578253490867559227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/4578253490867559227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/4578253490867559227'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/i-hate-virtual-machines.html' title='I Hate Virtual Machines'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-7416916378618345049</id><published>2008-06-04T20:45:00.000-07:00</published><updated>2008-06-04T21:05:34.974-07:00</updated><title type='text'>Beyond Scripting Language OO: Minimal Object Models</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the frustrations of any object model is living with the implementation. How can I change the rules of multiple inheritance (never mind the total insanity of wanting multiple inheritance)?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you've ever used something like &lt;a href="http://en.wikipedia.org/wiki/CLOS"&gt;CLOS&lt;/a&gt;, you have never realized that you are a slave to the object model of your language. Can you change the inheritance rules? Can you change the method lookup algorithm? Can you change the object structure?&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In a "&lt;a href="http://en.wikipedia.org/wiki/Lisp_language"&gt;programmable programming language&lt;/a&gt;" you can change the rules of the object system, defined by a &lt;a href="http://en.wikipedia.org/wiki/Metaobject"&gt;MOP&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To me the holy grail is making as many parts of the implementation "&lt;a href="http://en.wikipedia.org/wiki/First-class_object"&gt;first class&lt;/a&gt;" as possible. Can I tweak the virtual method tables? Can I reference closures, scopes,  or stack frames as some data type that I can manipulate and change the behavior of the language.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what sort of minimal, least restrictive implementation could we do for the platform for dynamic languages. I don't know the answer, but &lt;a href="http://piumarta.com/cv/"&gt;Ian Piumarta&lt;/a&gt; has written some interesting papers on the &lt;a href="http://piumarta.com/software/cola/"&gt;subject&lt;/a&gt;. Be sure to check out &lt;a href="http://piumarta.com/software/id-objmodel/"&gt;id-object&lt;/a&gt;, which combined with LLVM seems like ripe ground for experimentation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-7416916378618345049?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/7416916378618345049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=7416916378618345049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7416916378618345049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7416916378618345049'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/beyond-scripting-language-oo-minimal.html' title='Beyond Scripting Language OO: Minimal Object Models'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-7541886144450921772</id><published>2008-06-04T20:09:00.000-07:00</published><updated>2008-06-04T20:41:39.329-07:00</updated><title type='text'>Dynamic Language Optimizations: Polymorphic Inline Caches</title><content type='html'>The biggest performance problem with dynamic languages is that almost everything reduces to a lookup of a method call:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;x = a + b&lt;br /&gt;&lt;/pre&gt;This actually works out to:&lt;div&gt;&lt;ul&gt;&lt;li&gt;send the '+' message to the object referenced by 'a' with an argument of 'b'.&lt;/li&gt;&lt;li&gt;if the class of object 'a' doesn't respond to '+', consult the parent class of 'a'.&lt;/li&gt;&lt;li&gt;if the parent class doesn't respond to '+' continue up the class hierarchy until you find a class that does.&lt;/li&gt;&lt;li&gt;if no ancestor class responds to '+' see if the object referenced implements 'method_missing'.&lt;/li&gt;&lt;li&gt;if not do the same search up the ancestor tree for this method.&lt;/li&gt;&lt;li&gt;once you have found an implementation of '+' or 'method_missing', call it with the argument 'b'.&lt;/li&gt;&lt;li&gt;take the result of this method call and use it as an argument and send the '=' message to 'x' .&lt;/li&gt;&lt;li&gt;Rinse and repeat.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;So the first optimization at a given call site is to cache the result of the last lookup. So next time through if 'a' is the same class as before, we already know the method pointer, assuming a long laundry list of items ('a' hasn't implemented an instance method of the same name, no one has modified the definition of this method in the parent classes, etc).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The next optimization is &lt;a href="http://research.sun.com/self/papers/pics.html"&gt;polymorphic inline caches&lt;/a&gt;. Of course, every paper by the &lt;a href="http://en.wikipedia.org/wiki/Self_programming_language"&gt;Self&lt;/a&gt; guys should be studied. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-7541886144450921772?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/7541886144450921772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=7541886144450921772' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7541886144450921772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7541886144450921772'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/dynamic-language-optimizations.html' title='Dynamic Language Optimizations: Polymorphic Inline Caches'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-7478680335401192255</id><published>2008-06-04T19:31:00.000-07:00</published><updated>2008-06-04T20:03:53.390-07:00</updated><title type='text'>This software project goes to eleven</title><content type='html'>Here's a list of the first eleven things you do for a new software project. Note that this is "not advice, merely custom" (with apologies to Mark Twain):&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Come up with a cool name that &lt;a href="http://en.wikipedia.org/wiki/Apple_Inc._litigation#Libel_dispute_with_Carl_Sagan"&gt;hopefully you won't be sued for&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Have t-shirts made for all the developers with the project name. This is especially cool since most good developers' wardrobe consists entirely of &lt;a href="http://en.wikipedia.org/wiki/Promotional_item"&gt;swag&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Write a string class in C++, &lt;a href="http://www.google.com/search?hl=en&amp;amp;client=safari&amp;amp;rls=en-us&amp;amp;q=string+lib&amp;amp;btnG=Search"&gt;since all the other string libs suck.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Decide that rather than base the internal representation on one good standard (UTF8, UTF16, ShiftJIS, etc), that you'll support all representations and fix it with implicit casting operations.&lt;/li&gt;&lt;li&gt;Write a smart pointer and decide to retrofit the growing code base with reference counting.&lt;/li&gt;&lt;li&gt;Decide to switch from C++ to Java, because C++ sucks.&lt;/li&gt;&lt;li&gt;Rewrite all the code using Swing for the GUI.&lt;/li&gt;&lt;li&gt;Decide to switch back to C++ because Java is "Write-Once Debug Everywhere."&lt;/li&gt;&lt;li&gt;Decide that desktop apps are a thing of the past and rewrite in PHP.&lt;/li&gt;&lt;li&gt;Realize that your PHP code is unmaintainable, and discover what &lt;a href="http://www.youtube.com/watch?v=FisaVM93bdg"&gt;PHP is really an acronym for.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Rewrite your web app in Ruby on Rails and find it has one tenth the lines of code and one tenth the performance.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Actually I like Ruby and Rails, this is probably more a commentary on the past twenty years of my career than any one technology.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-7478680335401192255?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/7478680335401192255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=7478680335401192255' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7478680335401192255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7478680335401192255'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/this-software-project-goes-to-eleven.html' title='This software project goes to eleven'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-1752173245129032591</id><published>2008-06-04T17:56:00.000-07:00</published><updated>2008-06-04T18:05:46.732-07:00</updated><title type='text'></title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_tZCk63oKpQs/SEc7rl2i_gI/AAAAAAAAAAo/cvzppPrHHGQ/s1600-h/Zztop.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_tZCk63oKpQs/SEc7rl2i_gI/AAAAAAAAAAo/cvzppPrHHGQ/s320/Zztop.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5208197114158579202" /&gt;&lt;/a&gt;&lt;br /&gt;Imagine what &lt;a href="http://www.alenz.org/mirror/khason/why-microsoft-can-blow-off-with-c.html"&gt;success&lt;/a&gt; Billy Gibbons would have if he invented a programming language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-1752173245129032591?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/1752173245129032591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=1752173245129032591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/1752173245129032591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/1752173245129032591'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/imagine-what-success-billy-gibbons.html' title=''/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_tZCk63oKpQs/SEc7rl2i_gI/AAAAAAAAAAo/cvzppPrHHGQ/s72-c/Zztop.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-8942238182763688954</id><published>2008-06-04T17:35:00.000-07:00</published><updated>2008-06-04T17:51:20.388-07:00</updated><title type='text'></title><content type='html'>I've spent the last month of my daily bus rides exploring &lt;a href="http://llvm.org/"&gt;LLVM&lt;/a&gt;. It's a really great framework, and now I've gone past the toy languages in the tutorials to work on wrapping the API in Ruby. I spent some time trying to wrap the C++ API using &lt;a href="http://rice.rubyforge.org/"&gt;Rice&lt;/a&gt; and/or &lt;a href="http://rubyforge.org/projects/rbplusplus"&gt;rb++&lt;/a&gt;, the latter is not quite complete enough yet, and the former reminds me of why I enjoy Ruby so much over my days of hacking in C++, namely the horror of template error reporting in most C++ compilers:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;g++ -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0 -I. `llvm-config --cxxflags core` -I/usr/local/include -fno-common -arch i386 -Os -pipe -fno-common   -Wall -g -c llvm.cpp&lt;br /&gt;/usr/local/include/rice/detail/../detail/to_ruby.ipp: In static member function ‘static Rice::Object Rice::detail::to_ruby_&lt;t&gt;::convert(const T&amp;amp;) [with T = llvm::Constant*]’:&lt;br /&gt;/usr/local/include/rice/to_from_ruby_defn.hpp:67:   instantiated from ‘Rice::Object to_ruby(const T&amp;amp;) [with T = llvm::Constant*]’&lt;br /&gt;/usr/local/include/rice/detail/../detail/Auto_Member_Function_Wrapper.ipp:1188:   instantiated from ‘static VALUE Rice::detail::Auto_Member_Function_Wrapper&lt;func_t, void=""&gt;::call(VALUE, VALUE, VALUE) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&amp;amp;, const llvm::FunctionType*), Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&amp;amp;, Arg2_T = const llvm::FunctionType*]’&lt;br /&gt;/usr/local/include/rice/detail/../detail/Auto_Member_Function_Wrapper.ipp:1171:   instantiated from ‘Rice::detail::Auto_Member_Function_Wrapper&lt;func_t, void=""&gt;::Auto_Member_Function_Wrapper(Func_T, const Rice::detail::Exception_Handler*) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&amp;amp;, const llvm::FunctionType*), Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&amp;amp;, Arg2_T = const llvm::FunctionType*]’&lt;br /&gt;/usr/local/include/rice/detail/../detail/wrap_function.ipp:89:   instantiated from ‘Rice::detail::Wrapped_Function* Rice::detail::wrap_function(Ret_T (Self_T::*)(Arg1_T, Arg2_T), const Rice::detail::Exception_Handler*) [with Ret_T = llvm::Constant*, Self_T = llvm::Module, Arg1_T = const std::string&amp;amp;, Arg2_T = const llvm::FunctionType*]’&lt;br /&gt;/usr/local/include/rice/detail/../detail/define_method_and_auto_wrap.ipp:16:   instantiated from ‘void Rice::detail::define_method_and_auto_wrap(VALUE, const char*, Fun_T, const Rice::detail::Exception_Handler*) [with Fun_T = llvm::Constant* (llvm::Module::*)(const std::string&amp;amp;, const llvm::FunctionType*)]’&lt;br /&gt;/usr/local/include/rice/detail/../Module_impl.ipp:66:   instantiated from ‘Derived_T&amp;amp; Rice::Module_impl&lt;base_t, derived_t=""&gt;::define_method(const char*, Func_T) [with Func_T = llvm::Constant* (llvm::Module::*)(const std::string&amp;amp;, const llvm::FunctionType*), Base_T = Rice::Data_Type_Base, Derived_T = Rice::Data_Type&lt;llvm::module&gt;]’&lt;br /&gt;llvm.cpp:51:   instantiated from here&lt;br /&gt;/usr/local/include/rice/detail/../detail/to_ruby.ipp:7: error: creating array with size zero (‘no_to_ruby_conversion_defined’)&lt;br /&gt;make: *** [llvm.o] Error 1&lt;br /&gt;&lt;/llvm::module&gt;&lt;/base_t,&gt;&lt;/func_t,&gt;&lt;/func_t,&gt;&lt;/t&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;Clear as mud, no? &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also gave &lt;a href="http://www.swig.org/"&gt;swig&lt;/a&gt; a try, but it choked on the C++ headers. I'll probably give it a try using the C API, or just create some Ruby to parse the c headers and generate an interface.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-8942238182763688954?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/8942238182763688954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=8942238182763688954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/8942238182763688954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/8942238182763688954'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/06/ive-spent-last-month-of-my-daily-bus.html' title=''/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-7101224225545275007</id><published>2008-05-31T16:00:00.001-07:00</published><updated>2008-05-31T19:41:56.203-07:00</updated><title type='text'>Dynamic Language Optimizations: Memoization</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;The real raison d'être for this blog is to simply record my progress and notes in my current exploration of dynamic language implementation and optimization. First up I'd like to talk about &lt;a href="http://en.wikipedia.org/wiki/Memoization" target="_blank"&gt;memoization&lt;/a&gt;, which is basically trading space for time. If we have a function or method that is not affected by external variables, i.e. it references no global values or instance data,, then we can cache the result of each call to the function, and on subsequent calls with the same input, return the cached value instead of redoing the computation.&lt;br /&gt;&lt;br /&gt;For example, here's a naive recursive implementation of the Fibonacci series in Ruby and in C, along with execution times:&lt;br /&gt;&lt;pre class="hl"&gt;&lt;br /&gt;&lt;span class="kwa"&gt;def&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n)&lt;br /&gt;&lt;span class="kwa"&gt;  if&lt;/span&gt; n == &lt;span class="num"&gt;0&lt;/span&gt; &lt;span class="sym"&gt;||&lt;/span&gt; n == &lt;span class="num"&gt;1&lt;/span&gt;&lt;br /&gt;   n&lt;br /&gt;&lt;span class="kwa"&gt;  else&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n-1) &lt;span class="sym"&gt;+&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n-2)&lt;br /&gt;&lt;span class="kwa"&gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="num"&gt;36&lt;/span&gt;&lt;span class="sym"&gt;.&lt;/span&gt;times &lt;span class="kwa"&gt;do&lt;/span&gt; &lt;span class="sym"&gt;|&lt;/span&gt;i&lt;span class="sym"&gt;|&lt;/span&gt;&lt;br /&gt;puts &lt;span class="str"&gt;"n=#{ i} =&gt; #{fib(i)&lt;/span&gt;&lt;span class="sym"&gt;}&lt;/span&gt;&lt;span class="str"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class="str"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;real 0m54.742s&lt;br /&gt;user 0m54.613s&lt;br /&gt;sys 0m0.077s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="hl"&gt;&lt;span class="dir"&gt;#include "stdio.h"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwb"&gt;int&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="kwb"&gt;int&lt;/span&gt; n&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  if&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;n &lt;span class="sym"&gt;==&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt; &lt;span class="sym"&gt;||&lt;/span&gt; n &lt;span class="sym"&gt;==&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwa"&gt;return&lt;/span&gt; n&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  else&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwa"&gt;return&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n&lt;span class="sym"&gt;-&lt;/span&gt;&lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;) +&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n&lt;span class="sym"&gt;-&lt;/span&gt;&lt;span class="num"&gt;2&lt;/span&gt;&lt;span class="sym"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="kwd"&gt;main&lt;/span&gt;&lt;span class="sym"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="kwb"&gt;  int&lt;/span&gt; i&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  for&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;i &lt;span class="sym"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;span class="sym"&gt;;&lt;/span&gt; i &lt;span class="sym"&gt;&amp;amp;lt;&lt;/span&gt; &lt;span class="num"&gt;36&lt;/span&gt;&lt;span class="sym"&gt;; ++&lt;/span&gt;i&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwd"&gt;printf&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"%d =&amp;amp;gt; %d&lt;/span&gt;&lt;span class="esc"&gt;\n&lt;/span&gt;&lt;span class="str"&gt;"&lt;/span&gt;&lt;span class="sym"&gt;,&lt;/span&gt;i&lt;span class="sym"&gt;,&lt;/span&gt;&lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;i&lt;span class="sym"&gt;));&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;real 0m0.666s&lt;br /&gt;user 0m0.663s&lt;br /&gt;sys 0m0.002s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;"OMG! Ruby is eighty times slower than C!", I hear you say. But  I would add, for certain values of &lt;span style="font-style: italic;"&gt;X&lt;/span&gt;, specifically those values that are in the set of stupid benchmarks.&lt;br /&gt;&lt;br /&gt;So let's apply memoization to this Ruby script, a whopping two additional code lines and time it again:&lt;br /&gt;&lt;br /&gt;&lt;pre class="hl"&gt;&lt;br /&gt;&lt;span class="kwa"&gt;def&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n)&lt;br /&gt; @cache &lt;span class="sym"&gt;||&lt;/span&gt;= Hash&lt;span class="sym"&gt;.&lt;/span&gt;new&lt;br /&gt; &lt;span class="kwa"&gt;return&lt;/span&gt; @cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;]&lt;/span&gt; &lt;span class="kwa"&gt;if&lt;/span&gt; @cache&lt;span class="sym"&gt;.&lt;/span&gt;has_key? n&lt;br /&gt; &lt;span class="kwa"&gt;if&lt;/span&gt; n == &lt;span class="num"&gt;0&lt;/span&gt; &lt;span class="sym"&gt;||&lt;/span&gt; n == &lt;span class="num"&gt;1&lt;/span&gt;&lt;br /&gt;     @cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;]&lt;/span&gt; = n&lt;br /&gt; &lt;span class="kwa"&gt;else&lt;/span&gt;&lt;br /&gt;     @cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;]&lt;/span&gt; = &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n-1) &lt;span class="sym"&gt;+&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n-2)&lt;br /&gt; &lt;span class="kwa"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="num"&gt;36&lt;/span&gt;&lt;span class="sym"&gt;.&lt;/span&gt;times &lt;span class="kwa"&gt;do&lt;/span&gt; &lt;span class="sym"&gt;|&lt;/span&gt;i&lt;span class="sym"&gt;|&lt;/span&gt;&lt;br /&gt; puts &lt;span class="str"&gt;"n=#{ i} =&gt; #{fib(i)&lt;/span&gt;&lt;span class="sym"&gt;}&lt;/span&gt;&lt;span class="str"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class="str"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;pre class="hl"&gt;&lt;br /&gt;real 0m0.009s&lt;br /&gt;user 0m0.005s&lt;br /&gt;sys 0m0.004s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hmmm. With a little less naivete, our intrepid Ruby programmer has made his version run over seventy times faster than the naive C version. I suppose we could improve the C version:&lt;br /&gt;&lt;pre class="hl"&gt;&lt;br /&gt;&lt;span class="dir"&gt;#include "stdio.h"&lt;/span&gt;&lt;br /&gt;&lt;span class="dir"&gt;#include "stdlib.h"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwb"&gt;int&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="kwb"&gt;int&lt;/span&gt; n&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="kwb"&gt;  static int&lt;/span&gt; length &lt;span class="sym"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwb"&gt;  static int&lt;/span&gt;&lt;span class="sym"&gt;*&lt;/span&gt; cache &lt;span class="sym"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  if&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;length &lt;span class="sym"&gt;&amp;amp;lt;&lt;/span&gt; n&lt;span class="sym"&gt;) {&lt;/span&gt;&lt;br /&gt;   cache &lt;span class="sym"&gt;=&lt;/span&gt; &lt;span class="kwd"&gt;malloc&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="kwa"&gt;sizeof&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="kwb"&gt;int&lt;/span&gt;&lt;span class="sym"&gt;)*(&lt;/span&gt;n&lt;span class="sym"&gt;+&lt;/span&gt;&lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;)*&lt;/span&gt;&lt;span class="num"&gt;2&lt;/span&gt;&lt;span class="sym"&gt;);&lt;/span&gt;&lt;br /&gt;   length &lt;span class="sym"&gt;= (&lt;/span&gt;n &lt;span class="sym"&gt;+&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;) *&lt;/span&gt; &lt;span class="num"&gt;2&lt;/span&gt;&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  if&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;n &lt;span class="sym"&gt;==&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt; &lt;span class="sym"&gt;||&lt;/span&gt; n &lt;span class="sym"&gt;==&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwa"&gt;return&lt;/span&gt; n&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  else if&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;] ==&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt;   cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;] =&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n&lt;span class="sym"&gt;-&lt;/span&gt;&lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="sym"&gt;) +&lt;/span&gt; &lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;n&lt;span class="sym"&gt;-&lt;/span&gt;&lt;span class="num"&gt;2&lt;/span&gt;&lt;span class="sym"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  return&lt;/span&gt; cache&lt;span class="sym"&gt;[&lt;/span&gt;n&lt;span class="sym"&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="kwd"&gt;main&lt;/span&gt;&lt;span class="sym"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="kwb"&gt;  int&lt;/span&gt; i&lt;span class="sym"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwa"&gt;  for&lt;/span&gt; &lt;span class="sym"&gt;(&lt;/span&gt;i &lt;span class="sym"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;span class="sym"&gt;;&lt;/span&gt; i &lt;span class="sym"&gt;&amp;amp;lt;&lt;/span&gt; &lt;span class="num"&gt;36&lt;/span&gt;&lt;span class="sym"&gt;; ++&lt;/span&gt;i&lt;span class="sym"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;span class="kwd"&gt;printf&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"%d =&gt; %d&lt;/span&gt;&lt;span class="esc"&gt;\n&lt;/span&gt;&lt;span class="str"&gt;"&lt;/span&gt;&lt;span class="sym"&gt;,&lt;/span&gt;i&lt;span class="sym"&gt;,&lt;/span&gt;&lt;span class="kwd"&gt;fib&lt;/span&gt;&lt;span class="sym"&gt;(&lt;/span&gt;i&lt;span class="sym"&gt;));&lt;/span&gt;&lt;br /&gt;&lt;span class="sym"&gt;}&lt;/span&gt;&lt;br /&gt;real 0m0.004s&lt;br /&gt;user 0m0.001s&lt;br /&gt;sys 0m0.003s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Looks like it can help C also. But the improvement to Ruby is more drastic. In fact, Ruby has a gem called &lt;a href="http://raa.ruby-lang.org/project/memoize/" target="_blank"&gt;memoize&lt;/a&gt; that allows you to wrap methods you wish to cache the result of.&lt;br /&gt;&lt;br /&gt;Wouldn't it be nice if our compiler or interpreter could recognize when it could cache method returns automatically? In fact there has been a &lt;a href="http://citeseer.ist.psu.edu/mayfield95using.html" target="_blank"&gt;bit&lt;/a&gt; or &lt;a href="http://www.actapress.com/PaperInfo.aspx?PaperID=29650&amp;amp;amp;reason=500" target="_blank"&gt;more&lt;br /&gt;&lt;/a&gt; of research on this.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-7101224225545275007?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/7101224225545275007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=7101224225545275007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7101224225545275007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7101224225545275007'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/05/dynamic-language-optimizations.html' title='Dynamic Language Optimizations: Memoization'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6413447460022831327.post-7063174774071606684</id><published>2008-05-31T12:06:00.000-07:00</published><updated>2008-05-31T12:25:17.071-07:00</updated><title type='text'>Frist Psot!</title><content type='html'>Just what Teh Internets needs, another blog (well and maybe some of &lt;a href="http://www.youtube.com/watch?v=rgpD8CKSmhs"&gt;this&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6413447460022831327-7063174774071606684?l=my-god-its-full-of-tubes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://my-god-its-full-of-tubes.blogspot.com/feeds/7063174774071606684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6413447460022831327&amp;postID=7063174774071606684' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7063174774071606684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6413447460022831327/posts/default/7063174774071606684'/><link rel='alternate' type='text/html' href='http://my-god-its-full-of-tubes.blogspot.com/2008/05/frist-psot.html' title='Frist Psot!'/><author><name>Tomy</name><uri>http://www.blogger.com/profile/00665085049997491126</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_tZCk63oKpQs/SEIJK12i_dI/AAAAAAAAAAU/rSmcbD6mgTM/S220/Divide.jpg'/></author><thr:total>0</thr:total></entry></feed>
