{"id":68,"date":"2008-02-19T01:46:27","date_gmt":"2008-02-19T07:46:27","guid":{"rendered":"http:\/\/www.philhassey.com\/blog\/2008\/02\/19\/tinypy-64k-nearing-10-and-it-really-does-fit-in-64k\/"},"modified":"2008-02-19T01:47:10","modified_gmt":"2008-02-19T07:47:10","slug":"tinypy-64k-nearing-10-and-it-really-does-fit-in-64k","status":"publish","type":"post","link":"https:\/\/www.philhassey.com\/blog\/2008\/02\/19\/tinypy-64k-nearing-10-and-it-really-does-fit-in-64k\/","title":{"rendered":"tinypy 64k &#8211; nearing 1.0 &#8211; and it really does fit in 64k!"},"content":{"rendered":"<p>Updates &#8211; I&#8217;ve got it all fitting in 64k*.  It&#8217;s amazing how many functions that don&#8217;t do anything you can come across if you look around long enough.  Not to mention how many little things you can trim out that don&#8217;t actually do anything.  I have no idea where all this cruft comes from, but having a nice suite of tests sure is helpful for re-working stuff.  I also cut out a bunch of stupid features nobody would ever use**.  I was able to reduce the number of native types from 9 to 7.<\/p>\n<p>One of the challenges I faced was trying to fix up the incremental garbage collection.  My initial implementation was rather inefficient and caused some odd problems with how I wanted to code things.  I was using a dict to store all the &#8220;white&#8221; items, which caused loads of dict hash lookups.<\/p>\n<p>So in my mind I crafted a grand vision on how to accomplish this goal.  I would adjust all objects (sans numbers) to contain a pointer to some data which would have some header data for the GC to do some bookkeeping in.  Great!  However, when I implemented this, I found that a number of problems presented themselves: I had to perform a malloc for each and every string that I used, which killed performance, actually making things 2-3x slower.  I also noticed that the weird struct I defined was maybe a bit less standards compliant.  This attempt was a wash.<\/p>\n<p>So I re-crafted my grand vision.  This time I would do the same thing.  <em>Brilliant aren&#8217;t I?<\/em>  Anyway, the results were basically the same.  <em>Who&#8217;d&#8217;ve thunk?<\/em>  It was slower again, this time I was quite confused by it, since I had worked around some of the string issues.  I also found that the API for creating new strings wasn&#8217;t quite as &#8220;clean&#8221; as my original simple one.  This caused some issues in the exception handling mechanism.  I had to toss this try as well.<\/p>\n<p>At this point, having re-mangled the code twice and having poor results, I suspected something else might be wrong.  <em>My brain was turning into mush.<\/em>  Each time I had completely edited my &#8220;tp.h&#8221; with all my struct changes in one go.  I decided to make a final attempt at reworking tinypy, this time *one* data type at a time.  After each data type I added I was able to see if my changes caused any performance issues.  I found that my function data type was the culprit.  My hashing function (borrowed from lua) wasn&#8217;t getting enough entropy and was generating massive collision cases!  A few tweaks later, this was resolved.  I was able to also craft the string interface to be backwards compatible with the original string interface while also working with the new garbage collection.  This &#8220;step by step&#8221; approach got me to my goal.  All said and done, with a bit more tweaking, I was able to *double* the speed of tinypy \ud83d\ude42<\/p>\n<p>Lesson learned &#8211; even if it&#8217;s only 64k, it&#8217;s better to do changes step by step instead of in one big go.  valgrind and callgrind are your friends.  (Although I found that tinypy doesn&#8217;t entirely agree with callgrind &#8230; ideas anyone?)<\/p>\n<p>To wrap up this excessively long post about me trying to get code to work &#8212;  this weekend I&#8217;m hosting a <a href=\"http:\/\/www.imitationpickles.org\/ludum\/\">Ludum Dare warmup compo<\/a>.  I&#8217;m going to give tinypy a run in the &#8220;real world&#8221;.  Here&#8217;s to hoping!  Next week I plan on releasing the 1.0 version of tinypy.<\/p>\n<p>I&#8217;m also thinking about renaming some of my files.  And although pylang, dumbparse, and dump2vm have a certain rustic charm, I wonder if I&#8217;d do better with names like goat, gorilla, and sausage.  Or maybe more descriptive names like tokenator, parsalizer, and bytecodatron.<\/p>\n<p>svn:\/\/www.imitationpickles.org\/tinypy\/trunk for the brave.  If you want a zip or an exe, check back in a week.  I&#8217;ll have all those and more (a game!)  Note that I&#8217;ve split the SDL dependency out of the main tinypy code.  tinypy-sdl.c lets you run my julia.py example.  The bootstrapping process also has a final step of compiling with -O3, which I think might not work for everyone.  It gives pretty good speed gains on my system, so if it works for you, great!<\/p>\n<p>*python mk64k.py will do a bit of search-n-replace to cut it down to size.  I&#8217;ve resisted doing anything really ghastly, the code is still indented and readable.  See README.txt for more disgusting details on how I cheat to pretend this is 64k.<\/p>\n<p>**Okay, I&#8217;ve used some of those features.  But hey, this is a 64k implementation, I&#8217;ve got to trim the fat.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Updates &#8211; I&#8217;ve got it all fitting in 64k*. It&#8217;s amazing how many functions that don&#8217;t do anything you can come across if you look around long enough. Not to mention how many little things you can trim out that don&#8217;t actually do anything. I have no idea where all this cruft comes from, but [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,6,19,8,2,32],"tags":[],"class_list":["post-68","post","type-post","status-publish","format-standard","hentry","category-crazy","category-development","category-gamedev","category-languages","category-python","category-tinypy"],"_links":{"self":[{"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/posts\/68","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/comments?post=68"}],"version-history":[{"count":0,"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/posts\/68\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/media?parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/categories?post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.philhassey.com\/blog\/wp-json\/wp\/v2\/tags?post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}