<?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-4174477887223349138</id><updated>2011-12-11T09:54:19.737-08:00</updated><category term='security jquery'/><title type='text'>Yet another blog with too much CS and not enough cycling</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-3307497352372419091</id><published>2011-12-05T11:52:00.000-08:00</published><updated>2011-12-05T12:10:22.253-08:00</updated><title type='text'>Climate Change Skepticism</title><content type='html'>Some climate change skeptics who are very dear to me keep expressing puzzlement over why I'm not outraged by the series of leaked emails that constitute "Climategate".  Specifically why do I not conclude from them that &lt;i&gt;the best information that we have at present should not make us confident that anthropogenic climate change is real.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I thought I'd explain and give climate change skeptics something easy to attack.  A positive argument.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;A conspiracy is only damaging if it is effective.&lt;/b&gt;  A bunch of ineffectual twits sitting around a table plotting is of no danger to anyone.  Leaked emails tell us where to look for evidence of damage&lt;br /&gt;but are not, by themselves, evidence of damage.&lt;/li&gt;&lt;li&gt;If there were an effective conspiracy to doctor data to create a false consensus then it could only have been successful in creating a false consensus &lt;b&gt;if there are papers that depend on doctored data.&lt;/b&gt;&lt;br /&gt;&lt;ol type=a&gt;&lt;li&gt;If so, &lt;b&gt;it should be easy to find examples&lt;/b&gt;, via the paper citation graph, and present them.&lt;/li&gt;&lt;li&gt;According to the skeptics, 1000's of scientists are outraged (outraged I tell you) that &lt;a href="http://www.climatedepot.com/a/9035/SPECIAL-REPORT-More-Than-1000-International-Scientists-Dissent-Over-ManMade-Global-Warming-Claims--Challenge-UN-IPCC--Gore"&gt;"the whole thing is a fraud"&lt;/a&gt; which permeates the IPCC and the climatological profession.  Being scientists, they should be able to follow citations to find those papers.  That they haven't over a year after the first "climategate" is reason enough to conclude tentatively that&lt;br /&gt;they can't.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;If there were an effective conspiracy to claim a consensus where none exists, then &lt;b&gt;there should be plenty of paleo-climatologists who assume the contrary position&lt;/b&gt; in the peer-reviewed literature.  &lt;a href="http://www.sciencemag.org/content/306/5702/1686.full"&gt;Oreskes et al.&lt;/a&gt; is a positive example of a survey that argues they assume climate change is real.&lt;ol type="a"&gt;&lt;li&gt;If there were an effective conspiracy to suppress the vast majority of research papers then there would be a large number of quality research papers that have been rejected and a large number of disaffected climatologists who would be clamoring to create their own journals, conferences, and review boards.  This has not happened in the decades during which climate change has been discussed.  Why not?&lt;/li&gt;&lt;li&gt;The unsanitized rejected papers would have data that is substantially different from the sanitized mainstream literature or draw starkly different conclusions from the same data.  The &lt;a href="http://www.washingtonpost.com/blogs/ezra-klein/post/a-skeptical-physicist-ends-up-confirming-climate-data/2011/10/20/gIQA6viC1L_blog.html"&gt;BEST&lt;/a&gt; study from Berkeley is positive evidence against the first.  The second requires a large effective conspiracy as in (4).&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;If there is a large, effective conspiracy that includes the majority of climatologists, then again, their data would have to be faked or their conclusions would not follow from this data.&lt;br /&gt;&lt;ol type=a&gt;&lt;li&gt;If their data is cooked, it would show.  Again, the BEST study from Berkeley is positive evidence against this claim.&lt;/li&gt;&lt;li&gt;If they make up false conclusions, then the evidence is in the literature, and there would have to be some mechanism by which large numbers of scientists coordinate to avoid contradictions that are obvious to lay-people.  What is this mechanism?&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Conclusion&lt;/b&gt;: If the data is not cooked (not 2), paleo-climatologists genuinely try to draw reliable conclusions from their data (not 4), and paleo-climatologists genuinely agree that anthropogenic climate-change is real (not 3) after decades of research, then the best available information says that anthropogenic climate change is real.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;If you are a climate change skeptic who wants to convince me of your position, argue against these propositions or present positive evidence.  I would love to see any of the following:&lt;br /&gt;&lt;ol type=i&gt;&lt;li&gt;&lt;b&gt;Papers that have been infected with cooked data&lt;/b&gt;, ideally including a proportion of the citation graph that depends on these papers.&lt;br /&gt;&lt;li&gt;&lt;b&gt;A survey of the recent existing literature&lt;/b&gt; that shows that many paleo-climatologists make assumptions inconsistent with anthropogenic climate change.  Ideally, this study would compare the proportion of historians of 20th century Europe who believe the holocaust did not happen with the proportion of paleo-climatologists who believe anthropogenic climate change did not happen.&lt;br /&gt;&lt;li&gt;&lt;b&gt;A comparison of the data in papers that were rejected due to the conspiracy&lt;/b&gt; and those that were rejected because they were genuinely crap.&lt;br /&gt;&lt;li&gt;&lt;b&gt;A coordinating organization&lt;/b&gt; that helps large numbers of conspiratorial scientists to come up with non-obviously-contradictory non-sequiturs based on real data.&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;I am not going to waste my time looking at: &lt;ol type=I&gt;&lt;li&gt;&lt;b&gt;Damning emails.&lt;/b&gt;  These are at best pointers where to look for evidence of damage caused by a conspiracy.  I've worked too long with databases to be impressed by hysterical emails claiming "the data is all corrupt".  When you dig into the problem, usually there isn't one, and most of the rest of the time some forensic work with logs and backups will let me recover the ground truth.  Emails are the least reliable signal.  Demonstrated damage in dependent applications is the best, and logs that allow forensic analysis are a distant second.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Lists of dissenters.&lt;/b&gt;  I've looked at a few of these lists and the ones I've checked are full of non-climatologists, economists, and weather forecasters.  I'm sure they're lovely people and most of them are probably competent in their own domains, but they are not competent on the question of "is anthropogenic climate change real?"  &lt;a href="http://en.wikipedia.org/wiki/A_Scientific_Dissent_From_Darwinism#Responses"&gt;"A Scientific Dissent from Darwinism&lt;/a&gt; is another scientist list in a different domain that I find equally unconvincing.  If you understand why I find &lt;a href="http://en.wikipedia.org/wiki/Project_Steve"&gt;Project Steve&lt;/a&gt; so funny, you'll understand why I find your lists unimpressive.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-3307497352372419091?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/3307497352372419091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=3307497352372419091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/3307497352372419091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/3307497352372419091'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2011/12/climate-change-skepticism.html' title='Climate Change Skepticism'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-8263243275469340465</id><published>2011-07-21T15:55:00.000-07:00</published><updated>2011-07-25T09:26:07.196-07:00</updated><title type='text'>Absolute belief</title><content type='html'>I have been accused of wishy-washiness for not having conviction, for not having the strength of absolute belief in things like apple pie or America (Fuck, yeah!).  This has always struck me as horribly unfair so allow me to set the record straight.&lt;br /&gt;&lt;br /&gt;I believe absolutely and without reservation that (drumroll, please) I have at least one belief that is not correct.  Obviously, the idea that I could be wrong about a belief I have because I have no beliefs about which I could be incorrect, or because I am incorrect about whether I hold this belief, beggars belief (pun intended).  To not be correct about this particular belief because I am correct in all my beliefs is absurd.&lt;br /&gt;&lt;br /&gt;Those who know me probably now think I am both wishy-washy and a pedant, but I think this belief is a better starting place for argument than Descarte's famous &lt;i&gt;"Cogito ergo sum"&lt;/i&gt;, "I think therefore I am."  Descarte fails to rule out solipsism because there is no object to which he relates himself; no attribute that distinguishes Descarte from anything else in the universe.  Presumably Descarte thought thoughts but his statement specifies no relationship between the thinker and the thought, so without saying something about what "I am," the statement "I exist" is meaningless&lt;br /&gt;&lt;br /&gt;My absolute belief defines me as a believer in relationship to my beliefs any of which may not be correct according to a standard independent of me, and it further establishes that I and my beliefs are proper objects of belief.  Not much, but it's a start.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;¿Credo ergo erro?&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-8263243275469340465?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/8263243275469340465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=8263243275469340465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/8263243275469340465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/8263243275469340465'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2011/07/absolute-belief.html' title='Absolute belief'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-6119824566446748955</id><published>2011-04-18T18:29:00.000-07:00</published><updated>2011-04-18T18:29:28.461-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security jquery'/><title type='text'>Making JQuery templates safe against HTML injection</title><content type='html'>&lt;a href="http://api.jquery.com/category/plugins/templates/"&gt;JQuery templates&lt;/a&gt; make it very easy for web app developers to compose HTML to keep their user interface up-to-date, but they make it very hard to do so in a way that is safe against &lt;a href="http://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;E.g. the JQuery template&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&amp;lt;a href="{$url}"&amp;gt;{$text}&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/blockquote&gt;means create a link whose target is the result of &lt;code&gt;url&lt;/code&gt; and whose body contains the result of &lt;code&gt;text&lt;/code&gt;.  JQuery does a lot better than most templating languages; &lt;code&gt;message&lt;/code&gt; is assumed to be plain text and automatically encoded so that the page can't be XSSed that way.  But it does nothing about &lt;code&gt;url&lt;/code&gt;.  If an attacker can make &lt;code&gt;url&lt;/code&gt; be &lt;code&gt;javascript:alert(1337)&lt;/code&gt; they can execute code with the full privileges of the containing page.  This is a serious hole as URLs abound in web applications.&lt;br /&gt;&lt;br /&gt;So right now, JQuery templates are easy to learn, but they have to be used cautiously.  They would be even easier to use if template authors (and the poor maintainers) didn't have to worry about the provenance of data values, and could promiscuously inject into URLs, CSS, and inline JavaScript.&lt;br /&gt;&lt;br /&gt;I've been cooking up a way to fix templating languages like JQuery.  You can play around with Secure JQuery templates in the &lt;a href="http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/jqueryTemplatesTestbed.html"&gt;playground&lt;/a&gt;, or read up on the &lt;a href="http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html"&gt;design&lt;/a&gt; which also includes an analysis of the performance of this system as applied to another templating language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-6119824566446748955?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/6119824566446748955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=6119824566446748955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6119824566446748955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6119824566446748955'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2011/04/making-jquery-templates-safe-against.html' title='Making JQuery templates safe against HTML injection'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-7038406207370760322</id><published>2011-01-09T15:54:00.000-08:00</published><updated>2011-01-12T19:15:32.904-08:00</updated><title type='text'>Domestic bliss and the keys thereto</title><content type='html'>&lt;style&gt;sup { font-size: 50% }dt { font-weight: bold; list-style-type: decimal; list-style-position: inside; display: list-item }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;In the short time I've been married, I've come to realize that the key to domestic bliss is having a theoretical framework before engaging in delicate negotiations. (Before you snigger, no, "negotiation" isn't meant euphamistically like routes to other kinds of bliss: "commerce", "congress", "intercourse", "relations", "union"; though you might find the rest of this post much more entertaining if you add a dash of your own innuendo.)&lt;br /&gt;&lt;p&gt;The wife and I are thinking that we might not want to spend the rest of our lives together &lt;i&gt;in a 1200 ft&lt;sup&gt;2&lt;/sup&gt; apartment&lt;/i&gt;. Before plonking down hard cash on something with a volatile price, we thought it might be good to figure out what we (collectively) want, so while the wife looked at house listings, I came up with a theoretical framework to save our marriage &lt;i&gt;from the stress that hasty decisions would lead to decades from now&lt;/i&gt;.&lt;br /&gt;&lt;p&gt;Observation 1: When buying a house, you usually have to buy the whole house. You can't buy the kitchen and bedroom and not pay for the formal dining room. Which parts are valuable to me and which aren't?&lt;br /&gt;&lt;p&gt;Observation 2: When selling a house, people expect certain things. In addition to the obvious walls, they expect a foyer, and many houses devote more space to baths than to showers. Since Winston Churchhill, has there been a gainfully employed adult with time to take baths?&lt;br /&gt;&lt;p&gt;Observation 3: After living in small apartments in San Francisco for a decade and change, I struggle to imagine what we could do with 7000 ft&lt;sup&gt;2&lt;/sup&gt;. What do people do with 13000 ft&lt;sup&gt;2&lt;/sup&gt; houses?  Sharks with laser beams?  I need a way to separate the definitely useless from the merely probably excessive.&lt;br /&gt;&lt;p&gt;So I want a way to think about the following questions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How much is a given existing house worth to me?&lt;br /&gt;&lt;li&gt;Of two houses with rooms of the same dimensions, and the same fixtures, but different layouts, which should I prefer?&lt;br /&gt;&lt;li&gt;Given time and a plot of land, what should I build on it, and what should I build now?&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Being a reductionist, I will try to answer these questions by dividing each concrete house into smaller abstract houses. &lt;p&gt;Each quality of the real house (the existence of a room, a fixture, a nice material or finishing, and qualities like the view, location, neighbors, and availability of jobs) goes into at most one of these houses and I should be able to easily classify things as I walk around a house or look at a plan.&lt;dl&gt;&lt;dt&gt;A practical house&lt;/dt&gt;&lt;dd&gt;The portion of the house that its inhabitants use&lt;sup&gt;&amp;dagger;&lt;/sup&gt; on a regular basis.  At a minimum, this includes the master-bedroom, a front-door, and a bathroom.    Unless the nature of your work makes it impossible to bring it home, it will almost certainly include some kind of quiet study space.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: Bachelors, this may not include the kitchen.   &lt;/dd&gt;&lt;dt&gt;An entertaining house&lt;/dt&gt;&lt;dd&gt;The portion of the house (not in the practical house above) that encourages wanted guests to visit.    This probably includes guest rooms, extra pantry space, wet bar, extra parking, and any dedicated dining room.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: See "safe house" re unwanted guests.   &lt;/dd&gt;&lt;dt&gt;A safe house / a contingent house&lt;/dt&gt;&lt;dd&gt;That portion of the house that you hope you will never use, but might.  This includes your alarms, guns, flashlight batteries, canned food, fire-extinguisher, and other things that you want to be able to lay your hands on quickly; but that you'd lose if mixed in with your everyday things.    Unless you're older or disabled, this probably includes any elevators.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: Survivalists, this includes your moat, bomb shelter, life boat, escape pods, and extra ammo.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: Yuppies, this includes your portable wealth, "the hounds" and their release switch, and that earthquake preparedness kit you've never opened.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: Hipsters, this includes your zombie preparedness kit, and the sealed cache of LPs that you're preserving for future generations.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: Zombies, no, brains go under (1).   &lt;/dd&gt;&lt;dt&gt;An ornamental house&lt;/dt&gt;&lt;dd&gt;That portion of the house that exists solely to impress non-inhabitants to allow resale or to meet legal requirements.    This probably includes any formal dining room, and most if not all baths.    &lt;br&gt;&lt;b&gt;Note&lt;/b&gt;: New-Agers, this does not include your chakra attuned crystal chandelier.   &lt;/dd&gt; &lt;/dl&gt;&lt;p&gt;Hopefully as the examples make clear, this is a subjective assessment.  A particular feature, like a pool, might be practical to some people who swim often, entertaining to people who want to entice their grandkids to visit, may be an essential safety feature to someone who is afraid of catching on fire, or might be an ornamental feature when every other house on the block has a pool. Finally it might not be in any house, an expensive hazard to busy parents with a toddler.&lt;br /&gt;&lt;h4&gt;Is there anything I'm likely to want in a house that doesn't fit in these four houses?&lt;/h4&gt;&lt;p&gt;If the residents don't want to use it (1), guests don't want to use it (2), it's not useful just in case (3), and it's not required for resale or for appearances, then why should it be part of the house?&lt;br /&gt;&lt;p&gt;This will not satisfy a pack-rat, to which I respond, "Don't be a pack-rat!" I have no better argument for its completeness than that I haven't seen a counter-example ; I've tried applying this taxonomy as I've looked at houses and have yet to find something that I could not easily classify based on my likes/dislikes and expected usage patterns.&lt;br /&gt;&lt;h4&gt;How does this answer "How much is a given existing house worth to me?"&lt;/h4&gt;&lt;p&gt;Once the inhabitants agree what is in which house, then the problem reduces to a simpler set of questions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What kind of creature comforts are important to us?  Value of (1) to me&lt;br /&gt;&lt;li&gt;What would our guests enjoy?  Value of (2) to me&lt;br /&gt;&lt;li&gt;How likely are various disasters?  Value of (3) to me&lt;br /&gt;&lt;li&gt;How soon will I resell the house, and how much will an impressive house benefit my career or community life?  Value of (4) to me&lt;br /&gt;&lt;li&gt;How many fewer creature comforts are we willing to put up with to get our friends to visit?  (1) vs (2)&lt;br /&gt;&lt;li&gt;How many comforts are we willing to forego for emergencies?  (1) and (2) vs (3)&lt;br /&gt;&lt;li&gt;How many comforts are we willing to forego for increased status?  (1) and (2) vs (4)&lt;br /&gt;&lt;li&gt;etc.&lt;br /&gt;&lt;/ul&gt;&lt;h4&gt;How does this answer "Of two houses with rooms of the same dimensions, and the same fixtures, but different layouts, which should I prefer?"&lt;/h4&gt;&lt;p&gt;If we had the luxury of embedding a house with N rooms in a space with N+2 spacelike dimension, then we could easily have every room adjacent to every other and still be 3 dimensional. Alternatively, we could wedge shaped rooms radiating out from one central corridor that is an N-gon. &lt;p&gt;But such houses are either physically impossible or hard to resell, so we need to know what makes a conventional 2&amp;frac12; dimensional house livable. &lt;p&gt;If the practical house is dispersed, then we're going to spend an inordinate amount of time walking through rooms that we don't use.  So we should prefer that the practical house be concentrated and that it be easy to get from one part to another. &lt;table title="It's time for ASCII art"&gt;&lt;tr&gt;&lt;th&gt;Good&lt;th&gt;Bad&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;?????&lt;br /&gt;??111??&lt;br /&gt;??111??&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;11?????????11&lt;br /&gt;11         11&lt;/pre&gt;&lt;/td&gt;&lt;/table&gt;&lt;p&gt;When entertaining, we're almost certainly going to be using some parts of (1) like bathrooms and kitchen space, but we may want to keep guests away from other parts of (1).  So a good arrangement has (1) adjacent to the entertaining house with the common parts at the joining edge.&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Good&lt;th&gt;Bad&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;?????&lt;br /&gt;??11122&lt;br /&gt;??11122&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;11?????????22&lt;br /&gt;11         22&lt;/pre&gt;&lt;/td&gt;&lt;/table&gt;&lt;p&gt;In an emergency, we want to be able to get to the safe house from (1) and less often from (2), but we don't want to lose our emergency stuff by mixing it with a bunch of everyday stuff, so (3) is ideally located at the periphery of (1) and (2) ideally adjacent to both.&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Good&lt;th&gt;Bad&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;???33&lt;br /&gt;??11122&lt;br /&gt;??11122&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;2211?????????33   ZOMB&lt;br /&gt;2211         33   IES!&lt;/pre&gt;&lt;/td&gt;&lt;/table&gt;&lt;p&gt;Finally, (4) should almost be entirely at the periphery where possible.  Why would we want to waste time walking through parts that nobody uses?&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Good&lt;th&gt;Bad&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;44433&lt;br /&gt;4411122&lt;br /&gt;4411122&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;114444222444433   ZOMB&lt;br /&gt;11    222    33   IES!&lt;/pre&gt;&lt;/td&gt;&lt;/table&gt;&lt;p&gt;So if you consider an adjacency graph of rooms, then it seems that the best layout has the practical house (1) as a densely connected subgraph (and probably adjacent to the outside), with (2) next to it with special attention paid to common areas, and (3) distinct but reachable from (1) and with (4) out of the way.&lt;br /&gt;&lt;pre&gt;&amp;nbsp;  33&lt;br /&gt;&amp;nbsp;  332222&lt;br /&gt;&amp;nbsp;111111122&lt;br /&gt;41111111&lt;br /&gt;444&lt;/pre&gt;&lt;p&gt;These diagrams should be taken with a grain of salt. Each real room doesn't necessarily fall within one abstract house. E.g. most of a stove might be practical, used daily, but maybe you only bake when entertaining, so a nice convection oven would be in the entertaining house.&lt;br /&gt;&lt;h4&gt;How does this answer "Given time and a plot of land, what should I build on it, and what should I build now?"&lt;/h4&gt;&lt;p&gt;The second part of this question is easily answered. You need most of the practical house early on. You can delay expensive parts of the other houses, and there's no real need to build the parts of the ornamental house that are for resale until you plan to resell. Building (1) then (2) then (3) then (4) may be ideal if you arrange it so the adjacency graph is in shells to get the layout described above.&lt;br /&gt;&lt;p&gt;The first part of the question can be answered by coming up with a wish list for each house and budgeting for it. The relative size of the practical and entertaining houses depends in part on how often you think you'll be able to entertain. The size of the ornamental house depends on how well funded your neighbors are, and the size of the safe house depends on how risk-averse you are and how well funded your enemies are.&lt;br /&gt;&lt;p&gt;Then you need to pare things back. Are all the things in the practical house things you will actually use on a regular basis? If not, maybe kick it into the entertaining house. Are all the things in the entertaining house things you or your guests will use? If not, get rid of it or move it into the ornamental house. The value of something in the safe house is the portion of the cost of the disaster mitigated by the probability of the disaster minus the cost. Consider insurance instead. For the ornamental house, ask whether it can be delayed or faked.&lt;br /&gt;&lt;p&gt;If you've pared it back to the bachelor minimum (bedroom, bathroom, front door), congratulations, your wife is going to leave you so you're done.&lt;br /&gt;&lt;h4&gt;Does this framework make delicate negotiations easier, more tractable, more likely to come to correct conclusions?&lt;/h4&gt;&lt;p&gt;I don't know.  The post-reduction questions above are by no means easy, but for a relationship to survive delicate negotiations, each needs to learn what the other values. They need to get things out in the open so that decisions are made with eyes open to minimize the chances of hidden resentment down the road, and maximize the chances of both enjoying their decisions. I hope these questions get to the heart of that.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;dagger; : I use the term "use" broadly; one who appreciates art uses it, and that a house is in a good school district is a practical concern if a child uses the school afforded by the house's location on a regular basis.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-7038406207370760322?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/7038406207370760322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=7038406207370760322' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/7038406207370760322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/7038406207370760322'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2011/01/domestic-bliss-and-keys-thereto.html' title='Domestic bliss and the keys thereto'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-9217957987768013908</id><published>2010-11-28T09:57:00.000-08:00</published><updated>2010-11-29T07:50:27.215-08:00</updated><title type='text'>Breaking a Tandem down for Travelling</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;I got a new tandem from Stephen &lt;a href="http://www.bilenky.com/Home.html"&gt;Bilenky&lt;/a&gt; yesterday.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;My wife and I are both tall (5'10" and 6'4" respectively aka 178 cm and 193 cm) so we went custom, and I asked him to build it with braze-ons for Beckman racks so he tweaked the geometry to fit those. &amp;nbsp;He also managed to get me an Acai drum brake on the rear so the rear wheel is non-dished between that and the cluster.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;He did a nice job with S&amp;amp;S couplers too and gave me the pieces in two standard size shipping cases with nicely labeled velcro padding. &amp;nbsp;Here's how to pack a tandem with 2 sets of S&amp;amp;S couplers.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP1n1C-NI/AAAAAAAABzU/5THFtXd_JMg/s1600/IMG_1724.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP1n1C-NI/AAAAAAAABzU/5THFtXd_JMg/s320/IMG_1724.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The first case contains the front wheel which fits inside the shallow top lid deflated with 35mm tires -- smaller tires might fit inflated but I wouldn't ship inflated tires in an unpressurized compartment.&lt;br /&gt;&lt;br /&gt;Visible on the left are the front fork and the front tubes with captain's cranks attached, &amp;nbsp;The captain's bars and headset are also visible and those have been removed from the fork. &amp;nbsp;In pictures below I show the details of the shift and brake cables connectors.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP6QzHI3I/AAAAAAAABzY/4OXmf4a2s9A/s1600/IMG_1725.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP6QzHI3I/AAAAAAAABzY/4OXmf4a2s9A/s320/IMG_1725.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Detail of the first case. &amp;nbsp;The package wrapped in white cloth is a saddle. &amp;nbsp;At the far right and bottom are two tubes wrapped in velcro padding,&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP7DHw5rI/AAAAAAAABzc/SHGpnd_E5yg/s1600/IMG_1726.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP7DHw5rI/AAAAAAAABzc/SHGpnd_E5yg/s320/IMG_1726.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The captain's drop bars curve around the front tubes and you just have to route the cables where they don't get in the way.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKP7xtsxJI/AAAAAAAABzg/IPITmiSeyoc/s1600/IMG_1727.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKP7xtsxJI/AAAAAAAABzg/IPITmiSeyoc/s320/IMG_1727.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here you can see three white posts sticking up. &amp;nbsp;Those should be located towards the center of the box, and there are corresponding end caps that go on the other end to prevent the cases from compressing during shipping.&lt;br /&gt;&lt;br /&gt;Closing the box requires putting the front wheel over those posts, putting the top caps on, closing the case most of the way, and then finessing the wheel into the space in the lid.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKP8uD3htI/AAAAAAAABzk/Ri2BJMItI6k/s1600/IMG_1728.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKP8uD3htI/AAAAAAAABzk/Ri2BJMItI6k/s320/IMG_1728.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The captain's seat post and saddle goes in the first case wherever it fits.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKP9vLoXKI/AAAAAAAABzo/7ZP9-GY68qw/s1600/IMG_1729.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKP9vLoXKI/AAAAAAAABzo/7ZP9-GY68qw/s320/IMG_1729.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The second case contains the rear wheel with drum brake facing up, the rear triangle and crank arms wrapped in cloth. &amp;nbsp;That thing nestled in the triangle is the stoker's saddle. &amp;nbsp;I have to swap that seatpost for a thudbuster so hopefully it all fits.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKP-dHyb9I/AAAAAAAABzs/9W4CXPIhYTc/s1600/IMG_1730.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKP-dHyb9I/AAAAAAAABzs/9W4CXPIhYTc/s320/IMG_1730.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The padding has 2 extra velcro straps for the chain. &amp;nbsp;The chain that connects the captain's and stoker's cranks and the skewers are in a separate envelope.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKP_X83eYI/AAAAAAAABzw/12gpu30RpQw/s1600/IMG_1731.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKP_X83eYI/AAAAAAAABzw/12gpu30RpQw/s320/IMG_1731.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Detail showing how the saddle fits.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQAGYPcQI/AAAAAAAABz0/y_rBCvR2GJM/s1600/IMG_1732.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQAGYPcQI/AAAAAAAABz0/y_rBCvR2GJM/s320/IMG_1732.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The front cantilever brakes are visible here.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQBCbpDwI/AAAAAAAABz4/yvYxDgRIRBM/s1600/IMG_1733.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQBCbpDwI/AAAAAAAABz4/yvYxDgRIRBM/s320/IMG_1733.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;That's a crank arm wrapped up there.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Bilenky was nice enough to write idiot-proof labels on the padding so here are some shots of that.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQEWiSF3I/AAAAAAAAB0E/mnlf84UEDWU/s1600/IMG_1736.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQEWiSF3I/AAAAAAAAB0E/mnlf84UEDWU/s320/IMG_1736.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Rear seat post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQE33PXXI/AAAAAAAAB0I/ZzhfHlu6878/s1600/IMG_1737.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQE33PXXI/AAAAAAAAB0I/ZzhfHlu6878/s320/IMG_1737.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Rear triangle with front derailleur and straps for chain and rear derailleur.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQGKAaLjI/AAAAAAAAB0M/F7_64HS_Me0/s1600/IMG_1738.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQGKAaLjI/AAAAAAAAB0M/F7_64HS_Me0/s320/IMG_1738.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Cables route through padding.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQHHX6gjI/AAAAAAAAB0Q/4RKw4dBbQlo/s1600/IMG_1739.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQHHX6gjI/AAAAAAAAB0Q/4RKw4dBbQlo/s320/IMG_1739.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQICNxeSI/AAAAAAAAB0U/VDy3TLySLcE/s1600/IMG_1740.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQICNxeSI/AAAAAAAAB0U/VDy3TLySLcE/s320/IMG_1740.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Rear derailleur and cable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQIx60nZI/AAAAAAAAB0Y/dJZase0KX0M/s1600/IMG_1741.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQIx60nZI/AAAAAAAAB0Y/dJZase0KX0M/s320/IMG_1741.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQJ3U32iI/AAAAAAAAB0c/0eO2W01clFI/s1600/IMG_1742.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQJ3U32iI/AAAAAAAAB0c/0eO2W01clFI/s320/IMG_1742.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The wrapping goes around the end of the S&amp;amp;S coupler face.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQKteBCEI/AAAAAAAAB0g/Pno0H7Qy8u8/s1600/IMG_1743.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQKteBCEI/AAAAAAAAB0g/Pno0H7Qy8u8/s320/IMG_1743.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The crank arms are fitted with self-extracting bolts so I need an 8mm allen to reassemble.&lt;br /&gt;The stoker's cranks are separately wrapped in cloth.&lt;br /&gt;Te skewers and the transfer chain are each in separate envelopes, which fit into another envelope.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQLbvSTiI/AAAAAAAAB0k/E3PMxJUFzhI/s1600/IMG_1744.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQLbvSTiI/AAAAAAAAB0k/E3PMxJUFzhI/s320/IMG_1744.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Each individual tube is wrapped. &amp;nbsp;You can see the cable guide sans-cable at the left.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQNB8-mVI/AAAAAAAAB0o/Rnk3XR1gcr0/s1600/IMG_1747.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQNB8-mVI/AAAAAAAAB0o/Rnk3XR1gcr0/s320/IMG_1747.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The fork our of the head tube. &amp;nbsp;There are two pieces of padding that have slits to wrap around the brakes, and one for the top. &amp;nbsp;The stem is not wrapped.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQN0ztgfI/AAAAAAAAB0s/WUsl1tVrAew/s1600/IMG_1748.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQN0ztgfI/AAAAAAAAB0s/WUsl1tVrAew/s320/IMG_1748.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQPJucAKI/AAAAAAAAB0w/4EFJMmheb1g/s1600/IMG_1749.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQPJucAKI/AAAAAAAAB0w/4EFJMmheb1g/s320/IMG_1749.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The captain's seat post is wrapped as is the tube for the stoker's bars.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQQfgLPPI/AAAAAAAAB00/MvaYfdi00jY/s1600/IMG_1751.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQQfgLPPI/AAAAAAAAB00/MvaYfdi00jY/s320/IMG_1751.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQRUEyfBI/AAAAAAAAB04/_grYP6fDClg/s1600/IMG_1752.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQRUEyfBI/AAAAAAAAB04/_grYP6fDClg/s320/IMG_1752.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Detail of the padding for the fork. &amp;nbsp;Notice the slit that allows it to go around the brake.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQSRgCPII/AAAAAAAAB08/7x8Cr2gRa-I/s1600/IMG_1755.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQSRgCPII/AAAAAAAAB08/7x8Cr2gRa-I/s320/IMG_1755.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQTFvjGdI/AAAAAAAAB1A/fraH-nRQ6T0/s1600/IMG_1758.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQTFvjGdI/AAAAAAAAB1A/fraH-nRQ6T0/s320/IMG_1758.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Notice how the cables don't come out of the bottom bracket guides. &amp;nbsp;They ship inside the bottom tube padding.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQUlH3A6I/AAAAAAAAB1E/AnilZSji1LE/s1600/IMG_1761.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_6t_UumMM-Z0/TPKQUlH3A6I/AAAAAAAAB1E/AnilZSji1LE/s320/IMG_1761.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Cables attach with down-tube bosses attached.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQVaUz4XI/AAAAAAAAB1I/f2W-OUgqk8c/s1600/IMG_1762.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/_6t_UumMM-Z0/TPKQVaUz4XI/AAAAAAAAB1I/f2W-OUgqk8c/s320/IMG_1762.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQWU7Fe7I/AAAAAAAAB1M/EHBEdYGMVgI/s1600/IMG_1763.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKQWU7Fe7I/AAAAAAAAB1M/EHBEdYGMVgI/s320/IMG_1763.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Padding for the front tubes has slits to protect the ends.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKYYiD-zHI/AAAAAAAAB1Y/9y82TA225ak/s1600/IMG_1766.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TPKYYiD-zHI/AAAAAAAAB1Y/9y82TA225ak/s320/IMG_1766.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Exploded view of the padding for the front tube.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQYD5HuAI/AAAAAAAAB1Q/AxJgodNYn3s/s1600/IMG_1769.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQYD5HuAI/AAAAAAAAB1Q/AxJgodNYn3s/s320/IMG_1769.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Bilenkey head badge. &amp;nbsp;Spiffy!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQZtRz_JI/AAAAAAAAB1U/naMK1CKhQ3Q/s1600/IMG_1772.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKQZtRz_JI/AAAAAAAAB1U/naMK1CKhQ3Q/s320/IMG_1772.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Yes, 700x35's with deep rims do fit in the cases deflated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-9217957987768013908?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/9217957987768013908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=9217957987768013908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/9217957987768013908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/9217957987768013908'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/11/breaking-tandem-down-for-travelling.html' title='Breaking a Tandem down for Travelling'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_6t_UumMM-Z0/TPKP1n1C-NI/AAAAAAAABzU/5THFtXd_JMg/s72-c/IMG_1724.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-6765731864802564577</id><published>2010-06-28T17:22:00.000-07:00</published><updated>2010-06-28T17:22:39.157-07:00</updated><title type='text'>Utilitarianism</title><content type='html'>I've called myself a utilitarian for some time but I've recently concluded that utilitarianism is untenable as a moral philosophy.&lt;br /&gt;&lt;br /&gt;I'm an engineer so my job is to understand the tradeoffs inherent in designing a device to suit a purpose. &amp;nbsp;Utilitarianism appealed to me because it treats all ethical decisions as tradeoffs. &amp;nbsp;I was trying to come up with a definition of tradeoffs and concluded that a tradeoff is any attempt to compare incomparables : e.g., maximum speed versus average power consumption, or cash on hand now versus a distribution of returns later. &amp;nbsp;There is no natural ordering of such values, so engineers fall back on (hopefully) their client's utility function : Q(low max speed, low power consumption) &amp;gt; Q(high max speed, high power consumption) is meaningful.&lt;br /&gt;&lt;br /&gt;Since tradeoffs can only be made in the presence of a utility function, utilitarianism requires a global utility function. &amp;nbsp;I started to think about the properties such a function would have. &amp;nbsp;For it to be useful in making moral decisions, it must be computable or at least approximable in a time that is sublinear to the number of inputs given that utilitarianism says that everything is potentially an input -- potentially the entirety of the moral actor's past light cone. &amp;nbsp;It must also be able to concretely balance short term gains against long term gains unless one is to forever be sacrificing present good for some distant utopia.&lt;br /&gt;&lt;br /&gt;Then I realized that my client's utility function is part of the dynamic system that describes them -- it might be better for my client that they change their utility function than that I really remove seatbelts to save weight. &amp;nbsp;This is not a problem for an engineer since it is my job to understand what the client wants, not worry about their mental health (within reason). &amp;nbsp;But utilitarianism equates "good" and "utility" so I can't make conative assumptions ; if I did, the global utility function would just be a fancy name for a personal god for which I have no evidence. &amp;nbsp;This is not fatal to a global utility function since many functions have fixed points, but it does eliminate many classes of simple functions so there is reason to be skeptical that there exists an approximation that requires only a very small portion of the inputs to the global utility function.&lt;br /&gt;&lt;br /&gt;These criteria (approximability, tractability, and horizon-independence) are not trivial so I can't just assert that such a function exists in the same way that any other mental abstraction exists. &amp;nbsp;Unless I have positive reason for believing such a function exists and that I can apply it to solve moral questions, then I have no business calling myself a utilitarian.&lt;br /&gt;&lt;br /&gt;So for now, I'm just an ex-utilitarian who thinks that the techniques engineers use to optimize designs can be useful in thinking about moral priorities, but that there are probably other principled ways to the same end.&lt;br /&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/4174477887223349138-6765731864802564577?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/6765731864802564577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=6765731864802564577' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6765731864802564577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6765731864802564577'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/06/utilitarianism.html' title='Utilitarianism'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-3359432263149618736</id><published>2010-06-15T16:17:00.000-07:00</published><updated>2010-06-15T16:17:22.664-07:00</updated><title type='text'>Reversing Code Bloat with thr JavaScript Knowledge Base</title><content type='html'>Lindsey Simon and I just announced JSKB on the &lt;a href="http://googlecode.blogspot.com/2010/06/reversing-code-bloat-with-javascript.html"&gt;google code blog&lt;/a&gt; about browser-specific JavaScript optimization. &amp;nbsp;I wanted to expand on that. &amp;nbsp;Unfortunately, I don't have the technical chops necessary to put nice looking charts into blogs, so take a look &lt;a href="http://google-caja.googlecode.com/svn/trunk/doc/html/jskb.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-3359432263149618736?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/3359432263149618736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=3359432263149618736' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/3359432263149618736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/3359432263149618736'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/06/reversing-code-bloat-with-thr_15.html' title='Reversing Code Bloat with thr JavaScript Knowledge Base'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-1423711821328311115</id><published>2010-06-09T17:14:00.000-07:00</published><updated>2010-06-09T17:14:09.015-07:00</updated><title type='text'>Talking at OWASP in Stockholm</title><content type='html'>I'm going to be talking at OWASP's &lt;a href="http://www.owasp.org/index.php/OWASP_AppSec_Research_2010_-_Stockholm,_Sweden"&gt;AppSec Research Conference&lt;/a&gt;&amp;nbsp;in Stockholm the week after next (23 June).&lt;br /&gt;&lt;br /&gt;Jasvir Nagra and I are talking about virtualization as a strategy for bolting new security policies onto systems that have major legacy constraints, e.g. the web. &amp;nbsp;If we have time, we're going to discuss some of the language changes that Tom Van Cutsem and Mark Miller (who I believe is presenting at OOPSLA) have proposed for EcmaScript.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_6t_UumMM-Z0/TBAuMImvTAI/AAAAAAAABxE/9iS1SMWWgzs/s1600/OWASP_AppSec_Research_2010_Full_Banner_Im_Speaking.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_6t_UumMM-Z0/TBAuMImvTAI/AAAAAAAABxE/9iS1SMWWgzs/s320/OWASP_AppSec_Research_2010_Full_Banner_Im_Speaking.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Beyond the Same Origin Policy&lt;/b&gt;&lt;br /&gt;&lt;i&gt;Jasvir Nagra and Mike Samuel, Google Inc.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The same-origin policy has governed interaction between client-side code and user data since Netscape 2.0, but new development techniques are rendering it obsolete. Traditionally, a website consisted of server-side code written by trusted, in-house developers&amp;nbsp;; and a minimum of client-side code written by the same in-house devs. The same-origin policy worked because it didn't matter whether code ran server-side or client-side&amp;nbsp;; the user was interacting with code produced by the same organization. But today, complex applications are being written almost entirely in client-side code requiring developers to specialize and share code across organizational boundaries.&lt;br /&gt;&lt;br /&gt;This talk will explain how the same-origin policy is breaking down, give examples of attacks, discuss the properties that any alternative must have, introduce a number of alternative models being examined by the Secure EcmaScript committee and other standards bodies, demonstrate how they do or don't thwart these attacks, and discuss how secure interactive documents could open up new markets for web developers. We assume a basic familiarity with web application protocols&amp;nbsp;: HTTP, HTML, JavaScript, CSS&amp;nbsp;; and common classes of attacks&amp;nbsp;: XSS, XSRF, Phishing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-1423711821328311115?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/1423711821328311115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=1423711821328311115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/1423711821328311115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/1423711821328311115'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/06/talking-at-owasp-in-stockholm.html' title='Talking at OWASP in Stockholm'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_6t_UumMM-Z0/TBAuMImvTAI/AAAAAAAABxE/9iS1SMWWgzs/s72-c/OWASP_AppSec_Research_2010_Full_Banner_Im_Speaking.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-4088264917162018899</id><published>2010-04-26T14:20:00.000-07:00</published><updated>2010-06-09T17:02:48.697-07:00</updated><title type='text'>The sweet spot in internet security.</title><content type='html'>New standards like HTML5 often try to address security problems by providing new security features.  I think some of these are well-intentioned but are not moving us to a fundamentally more secure internet.&lt;br /&gt;&lt;br /&gt;Let me commit blog suicide by starting with a chart that'll drive away most of my potential audience.  (Bye :)&lt;br /&gt;&lt;table border="1"&gt;&lt;tr&gt;&lt;th width=30%&gt;&lt;th width=35%&gt;Introduces New Tools&lt;th width=35%&gt;Improves Security of Existing Tools&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Large Audience &lt;br /&gt;(Web Devs)&lt;td&gt;Limited.  Slow to take hold.  E.g., &lt;tt&gt;toStaticHtml&lt;/tt&gt;&lt;td&gt;Good, but doesn't address zero-days.  E.g. PHP magic quotes.&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Small Audience &lt;br /&gt;(Library Authors &amp; Security folk)&lt;td&gt;Good, but won't help legacy apps. E.g. &lt;tt&gt;&amp;lt;iframe sandbox="..."&amp;gt;&lt;/tt&gt;&lt;td&gt;&lt;i&gt;The sweet spot&lt;/i&gt;.  A (relatively) small group can address emerging threats quickly.&lt;br /&gt;E.g., native JSON support&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;h2&gt;Small groups respond more quickly&lt;/h2&gt;&lt;p&gt;The chart is broken down by the size of audience needed to work with the new feature.  There are many more web programmers than library developers and web security professionals put together.  Any tool that requires most web programmers to use it and use it consistently is limited in its effects.  Conversely, if a small audience can change a system to be more secure, then it can have wide-reaching effects.  For example, browser developers, a very small audience are now implementing native JSON support.  This means that many of the websites out there that have old buggy versions of &lt;tt&gt;JSON.js&lt;/tt&gt; for which there are known script injection exploits, will become more secure because those old libraries were written expecting JSON to become standard and so defer to the newer native implementation on browsers where it exists.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Fix existing code; don't only enable newer better code&lt;/h2&gt;&lt;p&gt;The chart is also broken down by scope; will the changes only affect new code that uses new APIs, or does it fundamentally improve the security properties of existing code.  If it requires developers to update code, then it can definitely help, but its effects will be very slow to be felt, since existing sites will have to be updated to use it.  Website developers are notoriously conservative, and often rightly so ; you can go out of business by updating too soon and breaking your site for old browsers.&lt;br /&gt;&lt;br /&gt;Not everything needs to be in the bottom-right box and not everything can be ; there are no silver bullets in security.  It is good to have new tools, and to have tools targeted at the web development community at large, but we should always prefer the bottom-right.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Getting Ahead of the Game&lt;/h2&gt;&lt;p&gt;New tools also have a problem.  Many new security tools are reactions to emerging threats -- the threat model has changed so the HTML and Ecmascript committee respond with new tools that are suited to the new threat model.&lt;br /&gt;&lt;br /&gt;But the threat model is only going to keep changing.  To get to the sweet spot, we need meta-tools that help small groups of security professionals bolt new security policies onto existing code while maintaining backwards compatibility.  And a way to get these changes onto the web at large by targeting a small group -- content aggregators and social hubs that use a plugin model are a good candidate.  Ideally we'll get to the point where we have a patch-and-update cycle for the web.  As the threat model changes, security specialists use the meta-tools to adapt existing systems to just keep working, but better.&lt;br /&gt;&lt;br /&gt;I think the best candidate for meta-tools are software virtualization tools, like the membranes and proxies proposed for Ecmascript 5.  And my project, &lt;a href="http://code.google.com/p/google-caja"&gt;Caja&lt;/a&gt; is aiming at providing that layer.  We're not in the sweet-spot yet : we've virtualized the DOM and network so we're able to provide a huge array of security policies, but our questionable library support keeps us out of the sweet spot; we're working on that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-4088264917162018899?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/4088264917162018899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=4088264917162018899' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/4088264917162018899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/4088264917162018899'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/04/sweet-spot-in-internet-security.html' title='The sweet spot in internet security.'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-1419645886648702282</id><published>2010-04-16T17:08:00.000-07:00</published><updated>2010-04-16T17:13:01.208-07:00</updated><title type='text'>Talk on the semantic gap</title><content type='html'>Google's security team is expanding, so we're doing some recruiting.  To help out, I gave a talk to Dawn Song's class at Berkeley.&lt;br /&gt;&lt;br /&gt;In brief my argument was&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Programming language design choices affect the kinds of vulnerabilities that programs written in those languages are susceptible to.&lt;br /&gt;&lt;li&gt;The source of these vulnerabilities is not just ignorance by programmers, but includes rational trade-offs between correctness/security and tersity, completeness, maintainability, efficiency, and other concerns.&lt;br /&gt;&lt;li&gt;A "semantic gap" exists where programmers (intentionally or unintentionally) use an abstraction that doesn't do quite what they want it to do.&lt;br /&gt;&lt;li&gt;Often this gap is innocuous (silent overflow in 64b increment) but sometimes it has catastrophic consequences (naive string interpolation &amp;rarr; shell injection). &lt;br /&gt;&lt;li&gt;It is possible to close some of these gaps without unduly breaking existing programs by using static analysis, delayed binding, and opt-in defaults to infer intent. &lt;br /&gt;&lt;/ul&gt;Take a look at my &lt;a href="http://google-caja.googlecode.com/svn/trunk/doc/html/semantic-gap.html"&gt;slides&lt;/a&gt;.&lt;p&gt;&lt;b&gt;"Security by Closing the Semantic Gap"&lt;/b&gt;&lt;p&gt;Security is about more than just cryptography; programming language design choices affect the way programmers design programs. We start with code samples in popular programming languages and show how it can be easy to write code that is almost correct, but that fails in ways that are catastrophic security-wise. We demonstrate how tweaking language definitions can close the "semantic gap," the difference between the intended effect of the code and its actual semantics which allows exploitable vulnerabilities to creep in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-1419645886648702282?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/1419645886648702282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=1419645886648702282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/1419645886648702282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/1419645886648702282'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/04/talk-on-semantic-gap.html' title='Talk on the semantic gap'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-5243100038335238922</id><published>2010-03-23T14:45:00.000-07:00</published><updated>2010-03-23T14:48:42.844-07:00</updated><title type='text'>Macros for EcmaScript</title><content type='html'>I gave a talk a while back about a proposal for adding macros to JavaScript.  I'm likely going to be presenting that to the EcmaScript Harmony working group in the next few days.  You can take a look at the &lt;a href="http://google-caja.googlecode.com/svn/trunk/doc/html/es-macros.html"&gt;slides&lt;/a&gt; for a talk I gave to the friam group at HP research a while back.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-5243100038335238922?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/5243100038335238922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=5243100038335238922' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/5243100038335238922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/5243100038335238922'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/03/macros-for-ecmascript.html' title='Macros for EcmaScript'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-771203905539047358</id><published>2010-02-10T14:56:00.000-08:00</published><updated>2010-02-10T15:12:58.328-08:00</updated><title type='text'>EcmaScript 5 and Harmony</title><content type='html'>I gave a talk on EcmaScript 5 and 6.  My slides are available as &lt;a href="http://google-caja.googlecode.com/svn-history/r3980/trunk/doc/html/es56-talk.html"&gt;HTML&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My pre-talk notes below capture the gist of what I said:&lt;br /&gt;&lt;br /&gt;I'm sure you're all aware that browsers and standards bodies have been working on new versions of JavaScript and HTML.  I've been working on client side code for a while, so I'm excited about a lot of these changes.  I worked on GWS, and then was the first client dev on calendar.  I worked on Closure Compiler, doing optimization and type system work.  Recently, I've been working with the EcmaScript committee to try and make it a better language for writing secure and robust programs.&lt;br /&gt;&lt;br /&gt;I'd like to go over some of the languages changes in the recently release ES 5, and summarize some of the topics being discussed for the next version.  Then I'm going to talk about some strategies that might help you start using new language features in code that needs to work on older interpreters.&lt;br /&gt;&lt;br /&gt;There's a lot to cover, so I'm going to go pretty quickly, so please jump in if you see something that grabs your interest.&lt;br /&gt;&lt;br /&gt;First, a bit of history.  When I say "EcmaScript," I mean "JavaScript."  Browsers are working on implementing the latest version EcmaScript 5.  Most of you are probably familiar with EcmaScript 3.  That leaves ES4 which never made it out of committee.  ES4 went on for years without producing a standard, and it's now officially dead.  You may be familiar with some of the proposals that came out of it, like the type system on which Closure Compiler's type system is based.  But most of the work from that did not make it into ES5.&lt;br /&gt;&lt;br /&gt;While ES4 was languishing, the ES3.1 group started from scratch with more modest goals, and eventually produced ES5.  There are a few principles that they used to decide what to include and what not to.  They wanted to standardize extensions and quirks fixes that 3 out of 4 major intepreters agreed on to move divergent implementations towards compatibility, and address some of the major sources of confusion using an opt-in mode that breaks backwards compatibility.&lt;br /&gt;&lt;br /&gt;First major change.  ES5 lets user code deal with properties the same way browser intrinsics like DOM nodes do.  Many interpreters had implemented getters, setters, watchers, or some similar mechanism; but each was different.  This example shows a way of defining a getter and setter using a syntax familiar to anyone who has used SpiderMonkey extensions.  This is just a convenience for a richer API though.&lt;br /&gt;&lt;br /&gt;defineProperty exposes the full power of the new property APIs.  It lets you add a new property to an existing object - either a value property or a dynamic property.  And you can specify property attributes -- whether the property is read-only, shows up in a for...in loop, and whether the property can be deleted or reconfigured.  The top example shows a value property, and the bottom shows a dynamic property definition.&lt;br /&gt;&lt;br /&gt;These APIs are a bit unwieldy, so there are conveniences on top of them.  Object.defineProperties lets one combine multiple property definitions.  Object.create combines object creation with property definition.  Object.freeze makes all properties read-only and unconfigurable, and flips a bit on the object so that new properties can't be added.  This gives a shallow immutability which can help code expose objects to the outside world, while maintaining invariants without all kinds of defensive copying.&lt;br /&gt;&lt;br /&gt;ES5 also standardizes a lot of interfaces that various libraries have proven very useful.  Maybe you're familiar with Closure's goog.array.  These interfaces are very similar but implemented natively, and available even without a full-scale library.  There are all the usual functional operators, plus a few extra flavors of reduce.  There's also a curry operator, the new bind method of function.  You give bind a value for this, and optionally some positional parameters and it returns a function that delegates to the original with those parameters.&lt;br /&gt;&lt;br /&gt;Another API that most JS libraries reinvent are ones for serializing and deserializing data.  Many do this badly, and the number of JSON parsers floating around with known XSS holes is depressing.  Most modern interpreters have native JSON support built in.  This is a safer way to unpack data.  And on calendar, we had to jump through all kinds of hoops to get data unpacking to be as fast as possible.  The JSON grammar is significantly simpler than the JS grammar, so native JSON parsing is often faster than eval.  It's roughly twice as fast as eval on FF 3.5, though I think eval on V8 is currently faster since they've spent more time optimizing it.  One of the nice things you may not be aware of with the new JSON APIs is revivers and replacers which let you serialize/deserialize types other than Array and Object.  You can also use it to get better compaction, by doing your own constant pooling.  This example shows something that I did for calendar to get our messages smaller -- since instances of repeating events often contain repeated strings.  You can use JSON revivers to get the same effect without needing arbitrary JSON.  This code is not ideal for a slide, but it shows the basic contract of JSON revivers, and replacers are basically the dual of this.&lt;br /&gt;&lt;br /&gt;Besides new APIs, the ES5 group tried to fix spec errors that led to unnecessary confusion.  The ES3 spec specified the curly bracket object notation in terms of looking up the name Object in the current scope and calling it as a constructor.  This meant that a whole slew of identifiers -- Object, Array, Function -- had special significance.  That's no longer the case.  Most ES3 interpreters stopped doing this because it allowed some really sneaky cross-domain attacks.&lt;br /&gt;&lt;br /&gt;The second example shows another unintended consequence of poor spec language.  Function calling is specified in terms of an abstraction called, appropriately enough, a lexical scope.  The spec said that a lexical scope is an instance of Object, and so property lookup would find not just declared local variables, but any variables on Object.prototype.&lt;br /&gt;&lt;br /&gt;Third, some interpreters pooled regular expression objects.  This is problematic because regular expressions are stateful.   If a regular expression is being used in a global match, or is used without supplying a new string, then its behavior depends on lastIndex.  Which can be mutated by code called in between matches.&lt;br /&gt;&lt;br /&gt;Lastly, it was very hard for interpreters to optimize local variable access because of eval.  ES3 said that interpreters could raise an error any time eval called via a name other than "eval", but few did.  In the above code, not only can eval be used to steal data across scope boundaries, but it show why interpreters can't do lots of interesting optimizations unless they can prove that eval is never called.  Now, if eval is called by that name, and refers to the same function as the original global eval, then it reaches into the local scope.  Otherwise, all free variables are interpreted in the global scope.&lt;br /&gt;&lt;br /&gt;ES strict mode is an opt-in mode that removes a number of other sources of bugs and confusion.&lt;br /&gt;You opt in by putting the string literal "use strict", by itself, at the top of your program or function body.&lt;br /&gt;Any functions contained, and any code evaled inside a strict context is itself strict.&lt;br /&gt;Strict mode differs from normal mode in a few ways.  "this" is not coerced to an object in strict mode.&lt;br /&gt;&lt;br /&gt;In the Boolean.prototype.not example, this would normally be coerced to an Object, so !this is always false.  Not in strict mode.&lt;br /&gt;this can also be null or undefined.  It won't magically become the global scope, so code which inadvertently used call or apply with null won't accidentally clobber global definitions.  Because of this, in strict mode, there are strictly fewer type coercions.&lt;br /&gt;&lt;br /&gt;And, basic operations no longer fail silently.  Things like deleting a non-existent property or setting a read-only property will throw an exception instead.&lt;br /&gt;&lt;br /&gt;Where ES5 was concerned with fixing known problems, ES6 is concerned with defining a few features that let developers write programs that simply couldn't work under ES5 due to efficiency or scaling issues, or kludgey grammar.&lt;br /&gt;I'm going to walk through a number of ideas the committee is toying with.  Some of these are pretty likely to make it into the next version, and some are highly speculative, but I'd love to get feedback on what people like and don't like.  After that, I'll talk about strategies for incorporating new language features into code that needs to also run on older interpreters.&lt;br /&gt;&lt;br /&gt;One of the things that everyone wanted to get into ES5 but couldn't was let-scoping.    If you've seen "let is the new var" t-shirts, this is what they're talking about.  Right now, all variables declared in a function are visible everywhere in that function, modulo catch blocks.  This leads to a lot of confusion around closures and variables apparently declared in loops.  I'm sure you've all had trouble with something like this example where a closure accesses a loop counter i.  That problem will go away with let scoping.&lt;br /&gt;&lt;br /&gt;A much more controversial proposal is lambdas.  If you write a lot of code in JS in a functional style, this would be useful to you.  Most versions of lambdas are a reduced syntax for closures that repair the Tennent's correspondence violations that JS functions have.  this, arguments, break, continue, and return, all change meaning as soon as you put them inside a function.  With lambdas, that is not the case.  If anyone is familiar with Neal Gafter's closures for Java proposal, this is similar.&lt;br /&gt;&lt;br /&gt;Most everyone agreed that some support for classes is needed, but there's no concensus on exactly what that is.  The general feeling is that some syntactic sugar over existing things like constructors and prototypes is probably the best way.  This syntactic sugar approach would make it very easy to use classes in code, and down-compile to older versions of ES.&lt;br /&gt;&lt;br /&gt;ES has no IdentityHashMap type, or System.identityHashCode.  And it probably never will, but sometimes it's hard to write some algorithms without it -- e.g. keeping a list of visited nodes to avoid cycles.  Ephemeron tables hash by identity, but without exposing indeterminism.  There's no way to iterate over keys, so key order is not a source of indeterminism.  And all keys are weakly held, so they don't complicate garbage collection.  A value in an ephemeron table is only reachable by the garbage collector if the table and key are independently reachable.&lt;br /&gt;Something like this proposal seems to have fairly broad support.&lt;br /&gt;&lt;br /&gt;There seems to be general consensus that modules are needed, but there are active discussions of both means and goals.  Some questions raised are how this ineracts with browser fetching, whether modules should be parameterizable ; basically should modules be stateful, or should the state be moved to instances ; and is an isolation mechanism needed so that code can be isolated from changes to Object.prototype and the like.  Ihab Awad did a lot of spec writing on that, so can answer detailed questions afterwards.&lt;br /&gt;&lt;br /&gt;The committee is listening to proposals around domain-specific language support in ES.  DSLs like E4X and CSS selectors have been implemented as extensions or in libraries.  So they're definitely useful for creating content in other languages, and for query languages.  They could be used to implement new flow control constructs if done right.  In the first example here, someone wants to create a regular expression to match a mime-content boundary.  But the boundary string could contain special characters, so they use a DSL.  The DSL desugars to a function call that gets the literal string portions, and embedded expressions as lambdas.  If the re function is const, then interpreters can inline the result since all the parameters are statically known.&lt;br /&gt;These DSLs can also be used to do structured string interpolation -- the syntactic flexibility of perl string interpolations without the horrible XSS problems.&lt;br /&gt;And the last example shows a control structure.&lt;br /&gt;&lt;br /&gt;There's also a lot of support for value types.  Types that don't compare for equality using reference identity.  IBM very much wants decimal arithmetic in, and this is one way to do this.  It would also let structured string interpolation behave like real strings.&lt;br /&gt;&lt;br /&gt;So that lets user defined code implement new value types.  Proxies give user code great flexibility over reference types.  I mentioned that there is a known hole in getters and setters.  You can't intercept accesses to properties that you haven't defined.  Properties do that in a way that preserves the semantics of Object freezing, and avoids a lot of complexity around prototype chains.  Instead of defining a property handler of last resort on an existing object, proxies are new objects that delegate all property accesses to handler functions.  Those functions can in turn delegate to another object.&lt;br /&gt;&lt;br /&gt;Destructuring assignments are syntactic shorthand for unpacking data structures.  They are not a general purpose pattern based decomposition as in OCAML or Scala.&lt;br /&gt;&lt;br /&gt;Iterators and generators are another idea for which there is wide support but no definite plans.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-771203905539047358?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/771203905539047358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=771203905539047358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/771203905539047358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/771203905539047358'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/02/ecmascript-5-and-harmony.html' title='EcmaScript 5 and Harmony'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-4371562026132235797</id><published>2010-01-28T11:30:00.000-08:00</published><updated>2011-12-11T09:54:19.747-08:00</updated><title type='text'>Cryonics skepticism and the rockstar exemption</title><content type='html'>[Update 16 April 2010: After seeing &lt;a href="http://wondermark.com/614/"&gt;http://wondermark.com/614/&lt;/a&gt; I recant the below.  If I might live to see hover toasters, then sign me up!]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I was talking to a friend who has been looking into cryonics.  I'm skeptical for the reasons below.  This has nothing to do with the good faith of the cryonics companies around today, but with the incentives of future generations.&lt;br /&gt;&lt;br /&gt;The claim of cryonics as I understand it is that&lt;br /&gt;&lt;blockquote&gt;It is possible to freeze an ailing human body (or part thereof), wait for medical technology to progress to the point where it can be returned to good health, and then revive it.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;This is a reasonable course if all the following hold&lt;br /&gt;(1) that there is an appreciable chance of being revived&lt;br /&gt;(2) that the person revived will survive for an appreciable time after being revived&lt;br /&gt;(3) that the person revived is very similar to the person frozen&lt;br /&gt;(4) that the time at which the person is revived will appeal to the person being revived&lt;br /&gt;&lt;br /&gt;I think these 4 assumptions are unlikely to hold at the same time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Scenario A&lt;/span&gt;&lt;br /&gt;A person is frozen, and in their children's or grandchildren's lifetime are revived.  In this case, I think 2 is unlikely since medical technology will not have had time to advance much.  This may not hold for people suffering from very particular afflictions, especially if they are wealthy and create a foundation to use their wealth to seek targeted advances.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Scenario B&lt;/span&gt;&lt;br /&gt;A person is frozen, and in the distant future, medical technology has solved their affliction.  In this case, I think 1 is unlikely.&lt;br /&gt;I assert that never in human history, has human civilization produced a machine with a moving part that has continued to function for 100 years without regular maintenance.&lt;br /&gt;This means there is a trade-off between cost of maintenance and cost to revive.  Consider two ends of the spectrum.  If a cryogenically frozen person is buried in a particularly slow-moving glacier, then maintenance costs are low, but cost to revive is high.  If a frozen person is warehoused, then maintenance cost is high, but the cost to revive is lower.&lt;br /&gt;&lt;br /&gt;I argue that no-one who would be able to revive them would have economic incentives to do so with a few exceptions that I discuss later.&lt;br /&gt;If the frozen has no assets then noone has incentives to keep the machines running.&lt;br /&gt;Who has either legal standing to act on behalf of the frozen, or economic incentive to see someone successfully unfrozen?  Very few.&lt;br /&gt;The cryogenics company has an annuity as long as someone stays frozen. If no next of kin can be identified, the cost of losing an annuity due to death is probably lower than the cost of successfully reviving someone.  The cryogenics companies' business models are basically like a family that keeps cashing welfare checks for a grandmother who is disabled or dead.&lt;br /&gt;Lawyers working for the frozen's estate have mixed incentives.  Law firms conglomerate like other industries, so after a certain amount of time, the number of long term cryogenically frozen clients whose estates are not administered by a law firm that specializes in frozen clients will be small.  They can charge an annuity, and when it comes to decide whether or not to revive, they run the risk of killing a paying client and ending their annuity or continuing to collect a check.  A law firm that specializes in such things will have internal controls set up so that they act in the most risk-averse way -- they will never revive anyone unless someone else with legal standing threatens to sue.&lt;br /&gt;Who might have such standing?  The RIAA.  Since fashion is fickle and cyclic, the RIAA might succeed in getting frozen artists revived so that they can do reunion tours and then, oops their cancer comes back right on cue, and they have to go back to sleep.&lt;br /&gt;Finally, is there a marketing incentive?  Not in scenario B.  A cryogenics company will want people to have the impression that their latest&amp;amp;greatest are the most reliable, so they will bias to later models.  And they will want to use in their marketing literature pretty people who their current target markets can relate to, so will again bias to recent customers.&lt;br /&gt;&lt;br /&gt;The above is largely based on arguments from ignorance -- who might have economic incentives? -- but I believe such arguments are valid because I am discussing whether it is rational to do this today, not whether it might be rational for someone in the future.&lt;br /&gt;&lt;br /&gt;There are obviously incentives other than economic and legal.  If you are a famous scientist, politician, or religious figure, other&lt;br /&gt;incentives apply.  For scientists, the likelihood of being unfrozen decreases as your field progresses past your current skill.  As a political figure, (4) is problematic since you're just as likely to be revived to stand trial as to be lauded.  As with many things, the best course seems to be a god, but ancestor worship is unreliable since current ancestor worshipping cultures do not have to deal with the likelihood of their in-laws coming back from the grave unbidden.&lt;br /&gt;&lt;br /&gt;Finally, is a hugely rich person likely to be revived?  I doubt it.  They are an annuity while frozen, and an unknown political threat to the powers that be if unfrozen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-4371562026132235797?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/4371562026132235797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=4371562026132235797' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/4371562026132235797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/4371562026132235797'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2010/01/cryogenics-skepticism-and-rockstar.html' title='Cryonics skepticism and the rockstar exemption'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-6441825303486633176</id><published>2009-05-11T19:23:00.000-07:00</published><updated>2009-05-12T11:02:51.845-07:00</updated><title type='text'>Efficient Parsing in Javascript</title><content type='html'>I rewrote the Google Code &lt;a href="http://code.google.com/p/google-code-prettify/"&gt;source code syntax highlighter&lt;/a&gt; recently.  It decorates source code in a variety of languages and I learned a few things about parsing in Javascript that others might find useful.  Below I compare a few methods for parsing in Javascript and show benchmarks at the end.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Problem&lt;/h3&gt;I got some reports that the syntax highlighter for Google Code was slow on large input files, so I decided to rewrite it.&lt;br /&gt;&lt;br /&gt;The inner loop of the parser looked something like:&lt;pre&gt;var patterns = [&lt;br /&gt; // Not the real patterns:&lt;br /&gt; /^\s+/,                      // whitespace&lt;br /&gt; /^[a-z]\w*/i,                // An identifier&lt;br /&gt; /^\d+(?:\.\d+)?/,            // A number&lt;br /&gt; /^"(?:[^"\\]|\\[^\r\n])*"/,  // A string&lt;br /&gt; ...&lt;br /&gt;];&lt;br /&gt;while (input) {&lt;br /&gt; var token;&lt;br /&gt; for (var i = 0, n = patterns.length; i &lt; n; ++i) {&lt;br /&gt;   token = patterns[i].match(input);&lt;br /&gt;   if (token) { break; }&lt;br /&gt; }&lt;br /&gt; // do something with the token&lt;br /&gt; input = input.substring(token[0].length);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Diagnosis&lt;/h3&gt;I came up with a few hypotheses about what could be wrong:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;One or more of the patterns is trying to match the entire input before failing, making the loop O(n&lt;sup&gt;2&lt;/sup&gt;).&lt;/li&gt;&lt;li&gt;The &lt;code&gt;substring&lt;/code&gt; operation is doing an array copy.&lt;/li&gt;&lt;li&gt;The regexp implementation is doing an array copy for the post-match content ($' on perl) even though I never use it which would make the loop O(n&lt;sup&gt;2&lt;/sup&gt;)&lt;/li&gt;&lt;li&gt;All the small strings generated are causing the GC to thrash.&lt;/li&gt;&lt;li&gt;One or more of the regex patterns are worse than O(n) on size matched.&lt;/li&gt;&lt;/ul&gt;I ruled out (1) and (5) by testing with a simple pattern set &lt;code&gt;[/^\s+/, /^\S+/]&lt;/code&gt; and still saw O(n&lt;sup&gt;2&lt;/sup&gt;) behavior.  I was really surprised that it seemed to be O(n&lt;sup&gt;2&lt;/sup&gt;) even on non-IE 6 browsers, since I knew thought that most browsers newer than IE6 were much more efficient when it came to string operations.&lt;br /&gt;&lt;br /&gt;I couldn't find an easy way to differentiate between (2) and (3) but don't need to since addressing one would address the other.&lt;br /&gt;&lt;br /&gt;I ruled out (4) since that would predict that performance would be a step-function — linear with a good constant factor for small inputs, and linear with a bad constant factor for large inputs.  But I didn't see that.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Experiment&lt;/h3&gt;I tried merging the regular expressions into one so that I could do a global match — using one pass over the input to break it into all tokens.&lt;pre&gt;&lt;br /&gt;var uberPattern = new RegExp(&lt;br /&gt;   '/^(?'&lt;br /&gt;   + '\s+'                            // whitespace&lt;br /&gt;   + '|[a-zA-Z]\\w*'                  // An identifier&lt;br /&gt;   + '\\d+(?:\.\\d+)?'                // A number&lt;br /&gt;   + '"(?:[^"\\\\]|\\\\[^\\r\\n])*"'  // A string&lt;br /&gt;   + ')',&lt;br /&gt;   'g');  // global makes match return a list of all matches&lt;br /&gt;var tolens = input.match(uberPattern);&lt;br /&gt;for (var i = 0, n = tokens.length; i &lt; n; ++i) {&lt;br /&gt; // do something with the token&lt;br /&gt; input = input.substring(token[0].length);&lt;br /&gt;}&lt;/pre&gt;and this got rid of the O(n&lt;sup&gt;2&lt;/sup&gt;) behavior on all browsers I tested (IE6, Safari3.2 and Firefox 3.0).&lt;br /&gt;&lt;br /&gt;The do something bit requires that I know which pattern the token matched, so I still have to run through the individual patterns to classify this token, but this is applying the regexs to a much shorter string, and one that does not vary with input size.  Also, this classification can be memoized effectively since the majority of tokens in real code are short repeated tokens (single spaces, braces, keywords, etc.).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Solution&lt;/h3&gt;&lt;pre&gt;function makeParser(patterns) {&lt;br /&gt; // A poor man's compiler compiler that takes multiple regular expressions&lt;br /&gt; // and returns a RegExp that is not anchored at the start of the input, and&lt;br /&gt; // that globally matches the union of the languages matched by the individual&lt;br /&gt; // patterns.&lt;br /&gt; var uberPattern = &lt;a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/combineRegexs.js?spec=svn66&amp;amp;r=66"&gt;combineRegexs&lt;/a&gt;(patterns);&lt;br /&gt; return function parser(input) {&lt;br /&gt;   var tokens = input.match(uberPattern);&lt;br /&gt;   var classifications = {};&lt;br /&gt;   for (var i = 0, nTokens = tokens.length; i &lt; nTokens; ++i) {&lt;br /&gt;     var token = tokens[i];&lt;br /&gt;     var classification = -1;&lt;br /&gt;     if (hasOwnProperty(classifications, token)) {&lt;br /&gt;       classification = classifications[token];&lt;br /&gt;     } else {&lt;br /&gt;       for (var j = 0; j &lt; nPatterns; ++j) {&lt;br /&gt;         if (patterns[j].test(token)) {&lt;br /&gt;           classification = j;&lt;br /&gt;           break;&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;       classifications[token] = classification;&lt;br /&gt;     }&lt;br /&gt;     // do stuff with token and classification.&lt;br /&gt;   }&lt;br /&gt; };&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Faking lookbehind&lt;/h3&gt;There were a number of places where I needed lookbehind, but Javascript doesn't support that.  In javascript, determining wheether a solidus (&lt;code&gt;/&lt;/code&gt;) starts a regular expression or a division character requires knowing the preceding token†, so lookbehind comes in really handy there.&lt;br /&gt;&lt;small&gt;† — Not actually true since Javascript has no regular lexical grammar, but Waldemar Horwat found a grammar that is lexically regular and indistinguishable in all but a few, mostly useless, cases from the real EcmaScript grammar.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript"&gt;Steven Levinthan&lt;/a&gt; came up with a couple mechanisms for faking it though, and I already had a mechanism for embedding one language in another so that I could, e.g. decorate CSS in HTML style attributes and elements.  I reused this embedded language mechanism to let me do the equivalent of a regular expression replace by delegating to a small sub-grammar, and that gave me lookahead.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Benchmark Setup&lt;/h3&gt;I wrote a &lt;a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/tests/large_input_test.html"&gt;benchmark&lt;/a&gt; which creates large data file with respectively 512, 1024, 2048, ... rows.  It creates one datafile for JSON like&lt;pre&gt;[&lt;br /&gt; { "friendly": true, "blinking": "hell-yes", "greeting": "Howdy!" },&lt;br /&gt; { "friendly": true, "blinking": "hell-yes", "greeting": "Howdy!" },&lt;br /&gt; …&lt;br /&gt;]&lt;/pre&gt;and a similar JSON file.  It then times how long it takes to decorate each input and tabulates the results.&lt;br /&gt;&lt;br /&gt;The results show pretty strikingly that there was a definite O(n&lt;sup&gt;2&lt;/sup&gt;) behavior before, and the new method is both faster in terms of its constant factor, but is linear (or almost so on Safari).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Benchmark Results&lt;/h3&gt;I ran all tests on a 2.16 GHz MacBook Pro running Mac OS 10.5.6.  IE6 numbers are taken from IE running on VMWare Fusion.&lt;br /&gt;&lt;br /&gt;The tests take a while to run, and in some cases I had to click "Scripts on this page are taking a long time to run." dialogs which add noise to the results, but which I do not think invalidate them.  I ran fewer input sizes on the old version since it scales so badly, and on Firefox there is a &lt;a href="http://forums.mozillazine.org/viewtopic.php?f=23&amp;amp;t=633782"&gt;known bug&lt;/a&gt; that prevents certain uses of regular expressions on very large strings.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;IE6 under VMWare, New&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;2391&lt;/td&gt;&lt;td&gt;214.1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;4906&lt;/td&gt;&lt;td&gt;208.7&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;14343&lt;/td&gt;&lt;td&gt;142.8&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;471048&lt;/td&gt;&lt;td&gt;23282&lt;/td&gt;&lt;td&gt;175.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td&gt;942088&lt;/td&gt;&lt;td&gt;45047&lt;/td&gt;&lt;td&gt;181.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;16384&lt;/td&gt;&lt;td&gt;1884168&lt;/td&gt;&lt;td&gt;105047&lt;/td&gt;&lt;td&gt;156.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;859&lt;/td&gt;&lt;td&gt;596.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;1625&lt;/td&gt;&lt;td&gt;630.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;3281&lt;/td&gt;&lt;td&gt;624.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;278528&lt;/td&gt;&lt;td&gt;7344&lt;/td&gt;&lt;td&gt;557.7&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td&gt;557056&lt;/td&gt;&lt;td&gt;15813&lt;/td&gt;&lt;td&gt;518.1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;16384&lt;/td&gt;&lt;td&gt;1114112&lt;/td&gt;&lt;td&gt;35856&lt;/td&gt;&lt;td&gt;456.9&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;IE6 under VMWare, Old&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;12484&lt;/td&gt;&lt;td&gt;41.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;40906&lt;/td&gt;&lt;td&gt;25.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;166462&lt;/td&gt;&lt;td&gt;12.3&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;4391&lt;/td&gt;&lt;td&gt;116.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;20093&lt;/td&gt;&lt;td&gt;51.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;81000&lt;/td&gt;&lt;td&gt;25.3&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;Safari New&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;634&lt;/td&gt;&lt;td&gt;807.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;1307&lt;/td&gt;&lt;td&gt;783.5&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;2660&lt;/td&gt;&lt;td&gt;769.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;471048&lt;/td&gt;&lt;td&gt;5348&lt;/td&gt;&lt;td&gt;765.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td&gt;942088&lt;/td&gt;&lt;td&gt;11132&lt;/td&gt;&lt;td&gt;735.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;16384&lt;/td&gt;&lt;td&gt;1884168&lt;/td&gt;&lt;td&gt;23829&lt;/td&gt;&lt;td&gt;687.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;448&lt;/td&gt;&lt;td&gt;1142.9&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;451&lt;/td&gt;&lt;td&gt;2270.5&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;904&lt;/td&gt;&lt;td&gt;2265.5&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;278528&lt;/td&gt;&lt;td&gt;1773&lt;/td&gt;&lt;td&gt;2310.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td&gt;557056&lt;/td&gt;&lt;td&gt;3751&lt;/td&gt;&lt;td&gt;2184.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;16384&lt;/td&gt;&lt;td&gt;1114112&lt;/td&gt;&lt;td&gt;7376&lt;/td&gt;&lt;td&gt;2221.3&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;Safari Old&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;16720&lt;/td&gt;&lt;td&gt;30.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;58799&lt;/td&gt;&lt;td&gt;17.4&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;236828&lt;/td&gt;&lt;td&gt;8.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;13937&lt;/td&gt;&lt;td&gt;36.7&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;65313&lt;/td&gt;&lt;td&gt;15.7&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;233607&lt;/td&gt;&lt;td&gt;8.8&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;Firefox New&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;1153&lt;/td&gt;&lt;td&gt;444.1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;2315&lt;/td&gt;&lt;td&gt;442.3&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;5587&lt;/td&gt;&lt;td&gt;366.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;471048&lt;/td&gt;&lt;td&gt;9054&lt;/td&gt;&lt;td&gt;452.4&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;301&lt;/td&gt;&lt;td&gt;1701.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;604&lt;/td&gt;&lt;td&gt;1695.4&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;1204&lt;/td&gt;&lt;td&gt;1701.0&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;278528&lt;/td&gt;&lt;td&gt;3675&lt;/td&gt;&lt;td&gt;1114.6&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td&gt;557056&lt;/td&gt;&lt;td&gt;4834&lt;/td&gt;&lt;td&gt;1694.7&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;caption&gt;Firefox Old&lt;/caption&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;XML&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;58888&lt;/td&gt;&lt;td&gt;9836&lt;/td&gt;&lt;td&gt;52.1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;117768&lt;/td&gt;&lt;td&gt;40669&lt;/td&gt;&lt;td&gt;25.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;235528&lt;/td&gt;&lt;td&gt;155776&lt;/td&gt;&lt;td&gt;13.1&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th colspan="4"&gt;JSON&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;th&gt;Count&lt;/th&gt;&lt;th&gt;Length (B)&lt;/th&gt;&lt;th&gt;Time (ms)&lt;/th&gt;&lt;th&gt;Items Per Second&lt;/th&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;34816&lt;/td&gt;&lt;td&gt;6629&lt;/td&gt;&lt;td&gt;77.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;69632&lt;/td&gt;&lt;td&gt;27533&lt;/td&gt;&lt;td&gt;37.2&lt;/td&gt;&lt;/tr&gt;&lt;tr align="left"&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;139264&lt;/td&gt;&lt;td&gt;104282&lt;/td&gt;&lt;td&gt;19.6&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-6441825303486633176?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/6441825303486633176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=6441825303486633176' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6441825303486633176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/6441825303486633176'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2009/05/efficient-parsing-in-javascript.html' title='Efficient Parsing in Javascript'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4174477887223349138.post-7051137367293920017</id><published>2009-05-11T19:14:00.000-07:00</published><updated>2009-05-11T19:23:07.709-07:00</updated><title type='text'>Obligatory First Post</title><content type='html'>This blog will contain posts on computer science, cycling and other things that interest me.  It reflects my own opinions, which often differ from those of my employer.&lt;br /&gt;&lt;br /&gt;&lt;a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/us/"&gt;&lt;img alt="Creative Commons License" style="border-width: 0pt;" src="http://i.creativecommons.org/l/by-nc/3.0/us/88x31.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a cc="http://creativecommons.org/ns#" href="http://www.blogger.com/mikesamuel.blogspot.com" property="cc:attributionName" rel="cc:attributionURL"&gt;Mike Samuel&lt;/a&gt;'s &lt;span dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" property="dc:title" rel="dc:type"&gt;blog&lt;/span&gt; is licensed under a &lt;a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/us/"&gt;Creative Commons Attribution-Noncommercial 3.0 United States License&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4174477887223349138-7051137367293920017?l=mikesamuel.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mikesamuel.blogspot.com/feeds/7051137367293920017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4174477887223349138&amp;postID=7051137367293920017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/7051137367293920017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4174477887223349138/posts/default/7051137367293920017'/><link rel='alternate' type='text/html' href='http://mikesamuel.blogspot.com/2009/05/obligatory-first-post.html' title='Obligatory First Post'/><author><name>Mike Samuel</name><uri>http://www.blogger.com/profile/16315216210479061685</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://2.bp.blogspot.com/_6t_UumMM-Z0/Sgm8_cS9CVI/AAAAAAAAA6E/8uRhWoD5cyc/S220/eating.png'/></author><thr:total>0</thr:total></entry></feed>
