<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEUFSHw-eip7ImA9WhBaEU8.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771</id><updated>2013-05-21T00:43:39.252-07:00</updated><category term="BayFP" /><category term="WBRU" /><category term="computer science" /><category term="concolic testing" /><category term="cs164" /><category term="functional reactive programming" /><category term="lambda calculus" /><category term="Parallel FRP" /><category term="web frameworks" /><category term="compilers" /><category term="security" /><category term="programming" /><category term="ECMAScript" /><category term="CFL-Reachability" /><category term="parallel browser" /><category term="Points-To Analysis" /><category term="bay area" /><category term="TA" /><category term="cognitive science" /><category term="ErlyWeb" /><category term="Java" /><category term="Prolog" /><category term="optimistic replication" /><category term="flapjax" /><category term="windows sucks" /><category term="CouchDB" /><category term="autotuning" /><category term="firefox" /><category term="programming language theory" /><category term="Rhino" /><category term="mobile computing" /><category term="software engineering" /><category term="garbage collection" /><category term="e-cash" /><category term="sk combinators" /><category term="Berkeley" /><category term="socio-plt" /><category term="refinement types" /><category term="machine learning" /><category term="programming languages" /><category term="JavaScript" /><category term="usability" /><category term="synthesis" /><category term="Erlang" /><title>The Good Soldier LMeyerov</title><subtitle type="html">a grad student's tale of survival in the face of absurd web programming models, systems insecure almost by design, disconnected language theories, and the berkeley meat grinder</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://lmeyerov.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>176</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/lmeyerov" /><feedburner:info uri="lmeyerov" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEQCSHg7fyp7ImA9WhBUGE0.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-2445867660218946105</id><published>2013-05-05T16:24:00.003-07:00</published><updated>2013-05-05T19:12:49.607-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-05T19:12:49.607-07:00</app:edited><title>Visualize Parallel Work Stealing in the Browser</title><content type="html">I try to write at least one interesting program every week. This weekend, to spice up my dissertation talk, I built an animated visualization of how my parallel CSS engine partitions a webpage via &lt;a href="http://en.wikipedia.org/wiki/Cilk"&gt;work stealing&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-y-GgQahXgkU/UYbmO-Be1GI/AAAAAAAABX8/Fza2SCKcCoY/s1600/workstealss.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://4.bp.blogspot.com/-y-GgQahXgkU/UYbmO-Be1GI/AAAAAAAABX8/Fza2SCKcCoY/s320/workstealss.tiff" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Work stealing is a great parallel task scheduling algorithm that provides dynamic load balancing and spatial locality. The idea is that each thread has a local queue of ready-to-fire tasks that it loops through, and if it ever runs out of local tasks, it will &lt;i&gt;steal&lt;/i&gt;&amp;nbsp;tasks from another thread's queue. The visualization shows how this works for a parallel top-down tree traversal over a webpage's HTML tree. In this case, a task is a node, and executing a task is denoted by changing the background color of that node to match the thread's color. The node's children are then added to the local queue for firing, and the process repeats. Whenever one thread steals a task from another, the webpage node corresponding to the stolen task has its border highlighted by the color of the thieving thread.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To try it it out, open your favorite website, paste the following code into the JavaScript console, and hit the start button:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="code"&gt;
&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;var s = document.createElement("script");&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;s.type = 'text/javascript';&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;s.src = 'https://raw.github.com/lmeyerov/devnull/master/one-offs/worksteal.js';&amp;nbsp;
  &lt;/span&gt;&lt;br /&gt;
&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;document.getElementsByTagName('head')[0].appendChild(s);
&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Alternatively, copy the following into your URL bar and hit start after it loads:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;javascript:(function(){var s = document.createElement("script"); s.type = 'text/javascript'; s.src = 'https://raw.github.com/lmeyerov/devnull/master/one-offs/worksteal.js'; document.getElementsByTagName('head')[0].appendChild(s); }())&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For this version, make sure you browser doesn't strip the "&lt;span style="color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;javascript:&lt;/span&gt;" at the front.&lt;br /&gt;
&lt;br /&gt;
The animation shows several important things for parallelization. First, the same thread will run many tasks that are near each other, which indicates good spatial locality. The evidence of this occurring is that many regions of the webpage will share the same color. Second, steals are infrequent, which keeps overheads low and again highlights locality benefits. This shows up in the page as very few stolen nodes (colored borders). To measure it, the per-thread percentage counters at top show the ratio of stolen nodes to non-stolen ones, and on most webpages, I get a pleasingly low 5% miss rate. &amp;nbsp;Finally, you can see a problem with the algorithm: the steal rate spikes at the beginning and end of a tree traversal. I made a simple optimization to the initial traversal -- I do a short sequential BFS traversal rather than immediately start with parallel DFS -- but did nothing here for the end.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
My layout engine actually uses a novel semi-static work stealer rather Cilk-style dynamic work stealing. The reason is that Cilk does not account for temporal locality, which is important in situations such as multiple traversals over a tree because they revisit the same nodes over time. With Cilk-style scheduling, which thread a node lands on can easily change across different traversals, which is a huge hit. Instead, my approach is to use work stealing once to partition the tree, and then reuse the precomputed schedule across different traversals: load balancing suffers a bit, but temporal locality goes up.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Enjoy!&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/Jh6B-Wq9U0g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/2445867660218946105/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=2445867660218946105" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2445867660218946105?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2445867660218946105?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/Jh6B-Wq9U0g/visualize-parallel-work-stealing-in.html" title="Visualize Parallel Work Stealing in the Browser" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-y-GgQahXgkU/UYbmO-Be1GI/AAAAAAAABX8/Fza2SCKcCoY/s72-c/workstealss.tiff" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2013/05/visualize-parallel-work-stealing-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUARng5fyp7ImA9WhBUFkk.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1618955734800630770</id><published>2013-05-03T21:11:00.000-07:00</published><updated>2013-05-03T22:10:47.627-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-03T22:10:47.627-07:00</app:edited><title>Monday, Monday, Monday! Dissertation Talk</title><content type="html">&lt;br /&gt;
About time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;Your message for list eecs-announce has been forwarded to editor(s):&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="p1"&gt;
&lt;b&gt;[Dissertation Talk] Parallelizing the Browser: Synthesis and Optimization of Parallel Tree Traversals&lt;/b&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br class="Apple-interchange-newline" /&gt;Speaker: Leo Meyerovich&lt;br /&gt;
Advisor: &amp;nbsp;Rastislav Bodik&lt;br /&gt;
Date: Monday, May 13th, 2013&lt;br /&gt;
Time: 3:30pm&lt;br /&gt;
Room: 373 Soda Hall&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
ABSTRACT:&lt;br /&gt;
From low-power phones to speed-hungry data visualizations, web browsers need a performance boost. Parallelization is an attractive opportunity because commodity client devices already feature multicore, subword-SIMD, and GPU hardware. However, a typical webpage will not strongly benefit from modern hardware because browsers were only designed for sequential execution. We therefore need to redesign browsers to be parallel. This thesis focuses on a browser component that we found to be particularly challenging: the layout engine.&lt;br /&gt;
&lt;br /&gt;
We address layout engine implementation by identifying its surprising connection with attribute grammars and then solving key ensuing challenges:&lt;br /&gt;
&lt;br /&gt;
1. We show how layout engines, both for documents and data visualization, can often be functionally specified in our extended form of attribute grammars.&lt;br /&gt;
&lt;br /&gt;
2. We introduce a synthesizer that automatically schedules an attribute grammar as a composition of parallel tree traversals. Notably, our synthesizer is fast, simple to extend, and finds schedules that assist aggressive code generation.&lt;br /&gt;
&lt;br /&gt;
3. We make editing parallel code safe by introducing a simple programming construct for partial behavioral specification: schedule sketching.&lt;br /&gt;
&lt;br /&gt;
4. We optimize tree traversals for SIMD, MIMD, and GPU architectures at tree load time through novel data representation and scheduling optimizations.&lt;br /&gt;
&lt;br /&gt;
Put together, we generated a parallel CSS document layout engine that can mostly render complex sites such as Wikipedia. Furthermore, we ran data visualizations in the browser that support interacting with over 100,000 data points in real time.&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/I4l4TW22j9Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1618955734800630770/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1618955734800630770" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1618955734800630770?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1618955734800630770?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/I4l4TW22j9Q/monday-monday-monday-dissertation-talk.html" title="Monday, Monday, Monday! Dissertation Talk" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2013/05/monday-monday-monday-dissertation-talk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04DRXc-cCp7ImA9WhBWFEo.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-65073785676686260</id><published>2013-04-07T15:54:00.000-07:00</published><updated>2013-04-08T19:52:54.958-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-08T19:52:54.958-07:00</app:edited><title>Parallel Parsing isn't Hard (Or, Parallel JSON via Web Workers!)</title><content type="html">&lt;b&gt;Generalized parallel parsing is hard.&amp;nbsp;&lt;/b&gt;Many a Ph.D. has been burned by attempting parallel parsing. Guy Steele wrote papers about it, and you'll find custom ones for favorite modern technology X for X = JavaScript, HTML, XML, etc. However, in practice, practical parallel parsing does not have to be so hard because parallel parsing research generally focuses on extreme cases. For example, our group examined &lt;i&gt;automatically generating&lt;/i&gt;&amp;nbsp;parallel parsers and handling &lt;i&gt;arbitrary&lt;/i&gt;&amp;nbsp;HTML.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Actual parallel parsing is easy.&lt;/b&gt;&amp;nbsp;Real applications provide significantly simplifying assumptions. Case in point: for our browser-based big data visualization framework, we needed to somehow load in big JSON arrays. Modern browsers provide a fast native function "JSON.parse :: String -&amp;gt; JSObj" that is fine for normal sized data sets, but parsing 9MB of sparse data takes over 1s, which requires a loading screen and eats your battery. The solution took ~2 days: on the server, split the data into multiple arrays, and on the client, use web workers to parse each array in parallel. Even though I'm controlling the parsing in JavaScript, the actual parsing is still being done natively by calling into JSON.parse for handling each fragment.&lt;br /&gt;
&lt;br /&gt;
Anyways, the proof is in the pudding. The relevant benchmarks are impact on file size and load time.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Benchmark 1: file size&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-zhRoLrU77vQ/UWH1B1sPMZI/AAAAAAAABS4/1mMx-zKEdiM/s1600/filesize.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="203" src="http://4.bp.blogspot.com/-zhRoLrU77vQ/UWH1B1sPMZI/AAAAAAAABS4/1mMx-zKEdiM/s320/filesize.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Splitting one of our sparse JSON data files into multiple chunks has no real hit to the file size, and due to some uninteresting &amp;nbsp;phenomena, actually helps when gzip is used. I'm also showing the benefit of compressing repeating zeros ("sparse json") for our particular data set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Benchmark 2: speedup&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-Vx7N4__a6t8/UWH1JIJh5WI/AAAAAAAABTA/nRsSuIpBp2M/s1600/speedup.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="197" src="http://2.bp.blogspot.com/-Vx7N4__a6t8/UWH1JIJh5WI/AAAAAAAABTA/nRsSuIpBp2M/s320/speedup.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
For the second benchmark, I'm testing loading the data set from a local hard drive when using different formats. The first two columns are sequential data formats, and with the second column primarily demonstrating the benefit of doing preprocessing for my particular application. The blue part of each column shows, in ms, how much time is spent reading the file from disk and parsing it.&lt;br /&gt;
&lt;br /&gt;
The important part is comparing the blue of the third column against the blue part of the second: using workers to parse JSON chunks is 2x faster than parsing the file in one sequential go.&lt;br /&gt;
&lt;br /&gt;
For further parallel speedups, it is important to realize that this application hit &lt;a href="http://en.wikipedia.org/wiki/Amdahl's_law"&gt;Amdahl's Law&lt;/a&gt;. In particular, the sequential stuff, like the black subcolumns, must be parallelized. The blue columns also have sequential code due to APIs I'm using. First, Safari does not have zero-copy message passing (&lt;i&gt;&lt;a href="http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast"&gt;transferable objects&lt;/a&gt;&lt;/i&gt;), so a sequential copy is made in communicating a parsed fragment back to the master. Second, I'm actually creating a big typed array, so even current web worker APIs do not help: I want to the Buffer &lt;i&gt;into&lt;/i&gt;&amp;nbsp;the worker, not get a new buffer out of one, which means I have to do a sequential copy even in Firefox and Chrome. Basically, we're seeing the web's poor support of message &amp;nbsp;passing forcing a lot of slow, sequential copies.&lt;br /&gt;
&lt;br /&gt;
Finally, I only benchmarked the case of local file loads. Our application, ultimately, will be used online with a server providing the data on-the-fly. The optimizations I showed should still help even if the application is network bound: they &lt;i&gt;also&lt;/i&gt;&amp;nbsp;enable pipeline parallelism. By splitting the JSON, parsing one chunk is now done in parallel with&amp;nbsp;downloading&amp;nbsp;the next. Modern webpages alternate between waiting on the network and the CPU, which this solution&amp;nbsp;elegantly&amp;nbsp;addresses.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
So there you have it -- parallel parsing, &lt;i&gt;in practice&lt;/i&gt;, should be easy. I did a constrained case of handling big JSON arrays. Even for more general JSON, it should only take a day more of work: partition the JSON via work stealing -- I successfully did a similar thing in my thesis for HTML in a few hundred lines of C++.&lt;br /&gt;
&lt;br /&gt;
If you'd like the code, it'll be part of our &lt;a href="http://sc-lang.com/"&gt;Superconductor&lt;/a&gt; (automatically GPU-accelerated web programming framework for big data visualization) release next month. Ping me if you'd be interested in working on parallel parsing of arbitrary JSON -- it should be awesome!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;UPDATE&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
I more carefully measured the overheads &amp;nbsp;and also did a couple more optimizations. The chart below shows the new results. It also now includes the message passing overheads in gray, where ~90% of it would go away in Chrome with &lt;i&gt;transferable objects&lt;/i&gt;&amp;nbsp;and the other 10% might be eliminated with ownership transfer of buffer views (sub-buffers), not just buffers.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-JT6C455xbvs/UWN-6k3F0hI/AAAAAAAABTw/Wln_5G3pcHA/s1600/speedup4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="297" src="http://1.bp.blogspot.com/-JT6C455xbvs/UWN-6k3F0hI/AAAAAAAABTw/Wln_5G3pcHA/s320/speedup4.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Two big &amp;nbsp;things are going on:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;The workers now perform decompression rather than the master. However, decompressing in the worker has a cost: &amp;nbsp;each worker now returns an inflated result message. Safari does not have ownership transfer so almost 100ms is spent copying the message back to the main thread rather than passing a pointer. &lt;br /&gt;&lt;br /&gt;The overhead is still worth it -- the blue region shrunk a lot, even if there is now a big gray region. (The gray region is in both because the sequential job runs in a worker in order to avoid pressuring the UI thread.) If/when Safari gets transferrable objects, 90% of the gray bars will disappear.&lt;/li&gt;
&lt;li&gt;Faster reduction of worker results into the final GPU buffer. Typed arrays support method&lt;b&gt;&amp;nbsp;set &lt;/b&gt;that can also help such reductions. It acts like a memcpy,&amp;nbsp;so &lt;b&gt;result.set(chunk, len)&lt;/b&gt;&amp;nbsp;copies array buffer "chunk" into array buffer "result" starting at byte offset "len" into "result." It only takes about 13ms. If the typed array spec was extended so that disjoint sub-buffers could be transferred across workers, the other 10% of the gray bars would disappear.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/d6z-H2ibTGY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/65073785676686260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=65073785676686260" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/65073785676686260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/65073785676686260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/d6z-H2ibTGY/parallel-parsing-isnt-hard-or-parallel.html" title="Parallel Parsing isn't Hard (Or, Parallel JSON via Web Workers!)" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-zhRoLrU77vQ/UWH1B1sPMZI/AAAAAAAABS4/1mMx-zKEdiM/s72-c/filesize.png" height="72" width="72" /><thr:total>4</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2013/04/parallel-parsing-isnt-hard-or-parallel.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYESHwzeyp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-7788115074971859600</id><published>2013-01-26T20:34:00.004-08:00</published><updated>2013-01-26T23:35:09.283-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:35:09.283-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Adoption-Oriented Languages</title><content type="html">&lt;b&gt;Language design decisions should not just increase adoption &lt;i&gt;but also&amp;nbsp;exploit adoption&lt;/i&gt;&lt;/b&gt;. For example, I just measured how popular languages can rely upon Stackoverflow as a code assistant. The chart below shows that increased language popularity on SourceForge (x axis) leads to faster answer times for questions asked on Stackoverflow (colored bins on the y axis):&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/-Gw6ibx2uTfo/UQTRechBYDI/AAAAAAAABLM/tX08VYh_xlU/s1600/answertime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-Gw6ibx2uTfo/UQTRechBYDI/AAAAAAAABLM/tX08VYh_xlU/s320/answertime.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;Stackoverflow Time-to-Answer vs. Sourceforge.net Language Popularity.&amp;nbsp;&lt;/b&gt;&lt;i&gt;Raw data grabbed a&amp;nbsp;&lt;a href="http://data.stackexchange.com/stackoverflow/query/93755/time-to-answer-by-language-difficulty-since-2010"&gt;stackoverflow query&lt;/a&gt;&amp;nbsp;that modifies&amp;nbsp;&lt;a href="http://blog.guillermowinkler.com/blog/2012/10/30/how-long-waiting-for-an-answer-in-stackoverflow/"&gt;G. Winker's&lt;/a&gt;, and language rankings from&amp;nbsp;&lt;a href="http://lmeyerov.blogspot.com/2012/08/quantifying-social-influences-on.html"&gt;our previous analysis&lt;/a&gt;.&lt;/i&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Top 10 languages have questions answered within 5 hours over 80% of the time, but for languages worse than Top 50, that shrinks to only 50% of the time. In terms of a simple blocker at work, that's a big deal: you can reliably ask a question, go work on something else, and come back to the answer!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Of course, measuring response time vs. popularity is up to interpretation: it could be that as adoption increaess, people ask easier questions. However, I suspect the chart is actually undercounting the adoption benefit: the more questions are answered, the more people don't need to wait for answers because they can just search for old ones! As one measure, we see that a language's popularity relates to its answer corpus size:&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/-hhxwVMoGNe8/UQTRr3Prm5I/AAAAAAAABLU/FvkMw-kaQkc/s1600/answertime2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-hhxwVMoGNe8/UQTRr3Prm5I/AAAAAAAABLU/FvkMw-kaQkc/s320/answertime2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;&amp;nbsp;Stackoverflow Answer Corpus Size vs. Sourceforge.net Language Popularity.&lt;/b&gt; &lt;i&gt;Same dataset as above.&amp;nbsp;
&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
I had to switch to a log-scale axis for answers! For popular languages, search becomes a valuable tool because Stackoverflow alone provides a FAQ of 100,000 solutions. An enterprising individual might want to further examine the duplicate rate, which I suspect would provide an insightful indicator for the likelihood of a query already being answered by a previous response.


&lt;br /&gt;
&lt;br /&gt;
Open source library repos are another case of a feature that improves with adoption: the library of builtins is ever expanding. Likewise, one of my favorite research projects is &lt;a href="http://research.cs.wisc.edu/cbi/"&gt;cooperative bug isolation&lt;/a&gt;, which exploits the adoption of a program to help narrow down causes of bugs. (AFAICT, most software companies do some form of tracking error and performance dumps.) A/B testing for feature design is also increasingly common. As another example, in academia, code completion tools are also &amp;nbsp;increasingly incorporating corpus-based solutions. A corpus can provide more value than type and namespace based solutions because, for example, synthesized code completions will resemble what people would actually write.&lt;br /&gt;
&lt;br /&gt;
I started sketching out the notion of &lt;b&gt;adoption-oriented language design&lt;/b&gt;&lt;i style="font-weight: bold;"&gt;&amp;nbsp;&lt;/i&gt;in a &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/isat2013.pdf"&gt;position paper last week&lt;/a&gt;. I struggled to think of features that &lt;i&gt;couldn't &lt;/i&gt;be designed to&amp;nbsp;strengthen with adoption. For example, verification, testing, security, program synthesis, and optimization could all be designed to &lt;i&gt;automatically&lt;/i&gt; exploit adoption of either the language, the library, or a program. &amp;nbsp;What strikes me is how little adoption is exploited today. &lt;b&gt;Outside of the cases, am I missing any that are commonly practiced, or should be?&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/jmUXMCqh86Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/7788115074971859600/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=7788115074971859600" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7788115074971859600?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7788115074971859600?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/jmUXMCqh86Q/adoption-oriented-languages.html" title="Adoption-Oriented Languages" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-Gw6ibx2uTfo/UQTRechBYDI/AAAAAAAABLM/tX08VYh_xlU/s72-c/answertime.png" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2013/01/adoption-oriented-languages.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMFRng-cCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1611823033002294769</id><published>2013-01-20T19:43:00.000-08:00</published><updated>2013-01-26T23:06:57.658-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:06:57.658-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><title>Superconductor Language in Action: Easy Big Data Viz in Your Browser</title><content type="html">Exciting news: we'll be talking about Superconductor at the &lt;a href="http://fluentconf.com/fluent2013"&gt;O'Reilly Fluent conference&lt;/a&gt;! This will be the first time we show it outside of small seminars, and will hopefully coincide with our open source release. This video proposing our session gives a feel for what Superconductor can do. The link skips right into the demo:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;a href="http://www.youtube.com/watch?v=H1aHul6UaV4&amp;amp;feature=youtu.be&amp;amp;t=40s"&gt;&lt;img src="http://img.youtube.com/vi/H1aHul6UaV4/0.jpg" /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br /&gt;
The basic idea is that you write a normalish webpage (HTML5, JS, JSON, CSS) for including and manipulating your big data viz, except:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Instead of relying up on the browser to run it (parse, layout, render, &amp;amp; animate), you load in our GPU-accelerated JavaScript libraries for the heavy lifting. Behind the scenes, we automatically exploit workers, WebCL, WebGL, etc.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Instead of using JavaScript for fancy layouts, you load in a widget made with our declarative layout DSL (or use it to define your own). Our parallel program synthesizer automatically finds the parallelism in the widget specs and our code generators output GPU code based on it.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
We're finally ramping up on a paper with the end-to-end system details; this will be the first time we discuss running inside of a commercial browser and using GPUs. Papers have a ridiculous delay period, so of you'll be at SIGGRAPH (LA), &lt;a href="http://ppopp2013.ics.uci.edu/"&gt;PPOPP&lt;/a&gt;&amp;nbsp;(Shenzen, China), or Intel's TechFest (Portland), you'll be able to catch a demo before then.&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/piAPfDdVh8M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1611823033002294769/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1611823033002294769" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1611823033002294769?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1611823033002294769?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/piAPfDdVh8M/superconductor-language-in-action-easy.html" title="Superconductor Language in Action: Easy Big Data Viz in Your Browser" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2013/01/superconductor-language-in-action-easy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMHQn45eip7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-7660801575260877723</id><published>2012-12-26T19:10:00.006-08:00</published><updated>2013-01-26T23:07:13.022-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:07:13.022-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="flapjax" /><title>Reactive Objects and Arrays via Direct Proxies</title><content type="html">Arrays are a crucial building block for programming. Consequently, an essential question for functional reactive programming is how to react to imperative array updates. Designing a clean interface gets bogged down in issues like identity, API consistency, and efficient incrementalization. I used a recent extension to JavaScript, &lt;a href="http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies"&gt;Direct Proxies&lt;/a&gt;&amp;nbsp;(Firefox-only), &amp;nbsp;to &lt;a href="http://jsfiddle.net/lmeyerov/v9SRR/"&gt;sketch a transparent dual-mode model&lt;/a&gt;&amp;nbsp;(JSFiddle)&amp;nbsp;for &lt;a href="http://flapjax-lang.org/"&gt;Flapjax&lt;/a&gt;. I made a reactive&amp;nbsp;array interface that covers the entire Array interface and supports both &lt;i&gt;instant&lt;/i&gt; and &lt;i&gt;batched&lt;/i&gt; updates. A fun holiday break from &lt;a href="http://www.youtube.com/watch?v=H1aHul6UaV4&amp;amp;feature=youtu.be&amp;amp;t=40s"&gt;Superconductor&lt;/a&gt; :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Update: I generalized the code in two ways: it works with object instances and also allows choosing whether the prototype is &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Array&lt;/span&gt; or &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Behavior&lt;/span&gt;.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Transparency&lt;/b&gt;&lt;/h3&gt;
&lt;br /&gt;
The idea is to create a reactive array that is tied to an existing normal array:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;var arr = ['init'],&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;var arrB = bindB(arr);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
From then on, interactions with one array are automatically reflected from one to the other. (In particular, &amp;nbsp;&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB&lt;/span&gt; uses &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arr&lt;/span&gt; as its backing store and proxies interactions to it):&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;// assert(arr[0] == arrB[0]);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arr.push('a'); &amp;nbsp;//&amp;nbsp;assert(arr.length == fxArr.length);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB.push('b'); //&amp;nbsp;assert(arr.length == fxArr.length);&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
By defining traps for JavaScript's meta-object&amp;nbsp;&lt;a href="http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies"&gt;proxy protocol&lt;/a&gt;, I guarantee that all of JavaScript's array methods are supported by the reactive array &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB&lt;/span&gt;. All in all, for normal JavaScript, it should not matter if you pass around&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;arr&lt;/span&gt;&amp;nbsp;or&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;arrB&lt;/span&gt;: they act on the same underlying data.&lt;br /&gt;
&lt;br /&gt;
(Full transparency might be wrong. I'll raise a semantic issue at the end about what if you *do* want to distinguish reactive arrays vs. flat ones using operators such as &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;instanceof.&lt;/span&gt;In my implementation, I let you pick as an optional parameter to &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;bindB&lt;/span&gt;.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Functional Reactivity and Instant Reactions&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;
Now the cool thing is that array mutations can be &lt;i&gt;automatically&lt;/i&gt; reacted to using normal functional reactive programming constructs.&lt;br /&gt;
&lt;br /&gt;
For example, we can declare a live counter of the array size:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;insertDomB(arrB.liftB(function (av) { return av.length; }));&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The above snippet is the usual functional reactive code that is a joy to read. It displays the length of the array. Whenever &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB&lt;/span&gt; updates, the GUI will automatically update to show the correct length.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The new ability here is that wrapped array mutations automatically trigger reactions:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB[30] = 20; //updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB.push('hello');&amp;nbsp;//updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
I'm calling these &lt;i style="font-weight: bold;"&gt;instant&lt;/i&gt;&amp;nbsp;reactions because each mutation registers an update event. In the above statements, two update events will be fired, one for each statement.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The original array and reactive array refer to the same data, but differ on how they interact with the event system. Updates to the original array do not trigger reactions:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arr.push('world'); &amp;nbsp;//no screen update&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Maintaining non-triggering behavior of the original array is important so that non-reactive code not ready for the extended behavior does not trigger massive DOM updates. In places where it is safe to do the switch,&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;arrB&lt;/span&gt;&amp;nbsp;can be swapped in.&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
Batched Reactions&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
A nice pattern falls out of the wrapped and unwrapped view of the array. When many updates to an array should happen, we can batch them for a single subsequent response:&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;function addSome(n, arrB) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;//batched update&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; for (var i = 0; i &amp;lt; n; i++) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;arrB.last.push(i);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; }&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; //notification&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; if (n &amp;lt; 0)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;arrB[0] = arrB.last[0];&amp;nbsp;//updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;addSome(10, arrB);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The "arrB.last.push(i)" calls trigger no reactions, while the assignment to&amp;nbsp;arrB[0] triggers an instant&amp;nbsp;reaction. This pattern of silent array updates followed by an instant reaction on the reactive view is a &lt;i&gt;&lt;b&gt;batched reaction&lt;/b&gt;&lt;/i&gt;. It is largely an optimization, but if you create local invariants inside the body of addSome, you can also use the pattern for &amp;nbsp;(non-nested)&amp;nbsp;&lt;b&gt;&lt;i&gt;transactional&lt;/i&gt; &lt;i&gt;reactions&lt;/i&gt;&lt;/b&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Object Instances and Meta Protocols&lt;/h3&gt;
&lt;/div&gt;
In response to Shriram's comment, the technique here is a late-bound dual to &lt;a href="http://cs.brown.edu/~sk/Publications/Papers/Published/ick-adapt-oo-fwk-frp/"&gt;his work in making legacy classes reactive&lt;/a&gt;. For Racket's class system, he showed how to make a reactive subclass: the case of arrays would act like "&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;var myArrB = new ArrayB(1, 2, 3); assert(myArrB instanceof Array)&lt;/span&gt;". The dual problem examined in my post is where an instance of a class must be made reactive ("&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;var myArr = [1,2,3]; ...; var myArrB = bindB(myArr)&lt;/span&gt;"). It is an important practical distinction because the developer writing "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;var myArrB = bindB(myArr)&lt;/span&gt;" might not have control over "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;var myArr = [1,2,3]&lt;/span&gt;" nor "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;.&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;.&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;.&lt;/span&gt;".&lt;br /&gt;
&lt;br /&gt;
His connection is important for two reasons: it provides a principle for how bound arrays should act (as subclass instances) and, more generally, shows that the same approach can be used for making object instances reactive.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;1. Design principle of subclassing.&amp;nbsp;&lt;/i&gt;Given an array, his connection tells us that reactive version should act as a subclass of &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Array&lt;/span&gt;. As seen above, this works for methods like &lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;push&lt;/span&gt; and [] (&lt;i&gt;get&lt;/i&gt;). However, the desired object protocol behavior is not obvious. For example, should "&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;assert(myArrB instanceof Array)&lt;/span&gt;" &amp;nbsp;succeed? By the subclass reasoning, yes!&lt;br /&gt;
&lt;br /&gt;
Unfortunately, setting&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;myArrB&amp;nbsp;&lt;/span&gt;to be an instance of Array breaks introspection within the Flapjax library. To add dependencies to an object, Flapjax checks whether it can register event listeners. For example, "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;liftB(&lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;function (v) { return v.length; },&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;myArrB&lt;/span&gt;&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;)&lt;/span&gt;" triggers a check&amp;nbsp;"&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;arg2 instanceof Behavior&lt;/span&gt;": if&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;myArrB &lt;/span&gt;is an Array and not a Behavior, Flapjax will not register listeners on it! Some examples still work, such as&amp;nbsp;&amp;nbsp;"&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;myArrB.liftB(function (v) { return v.length; })&lt;/span&gt;", because the check is elided. For now, I support two constructor options:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;var xB = bindB(arr);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;assert(xB instanceof Array); //indistinguishable from Array&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;xB.liftB(function (v) { return v.length; }); //only supports chained reaction&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;var yB = bindB(arr, true);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;assert(xB instanceof Behavior); //distinguishable from Array&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;yB.liftB(function (v) { return v.length; }); //chained reactions&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;liftB(function (v) { return v.length; },&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;yB&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;); //and as arguments&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
The non-default constructor is more readily distinguished from an Array, and Flapjax uses this ability to &amp;nbsp;out-of-the-box to to react to it. If code consuming "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;myArrB&lt;/span&gt;" does not need "&lt;span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"&gt;myArrB instanceof Array&lt;/span&gt;", I suggest the second, non-default form.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;2. Generalization to Objects. &lt;/i&gt;The motivation of this post was to handle array instances, but as Shriram implies, those are a special form of object instances. We get the simpler case of objects for free!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;var o = {};&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;var p = bindB(o);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;insertDomB(DIV("o has x: ", p.liftB(function (v) { return v.x ? true : false; })));&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;//display shows false&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;p.x = 1; // o.x == 1 and display updates to show true&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;delete p.x; //o.x == undefined and display updates to show false&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The code snippet above shows creating a reactive view of an object. The original object is the backing store for the view, and edits to the reactive view automatically trigger DOM updates. As with arrays, when reactions occur can be controlled by choosing to edit the raw object or the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
Via proxies, I was able to make imperative arrays play nicely along their &lt;i&gt;entire&lt;/i&gt;&amp;nbsp;API with our FRP library and support both instant and batched/transactional updates. &amp;nbsp;You can play with this in Firefox via my &lt;a href="http://jsfiddle.net/lmeyerov/v9SRR/"&gt;JSFiddle&lt;/a&gt;. There is more to do (for example, the direct proxy API precludes behavioral indices &amp;nbsp;like fxArr[secondsB]), but the flexibility of this approach is handy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
APPENDIX&lt;/h4&gt;
&lt;div&gt;
&lt;br style="color: #666666; font-family: Inconsolata, Monaco, Consolas, 'Andale Mono', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; font-size: 12px; line-height: 15px;" /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;function&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;bindB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;asObj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #88ff88; font-weight: bold; line-height: 15px;"&gt;{&amp;nbsp;&lt;/span&gt;&lt;span class="js-comment" style="color: #aa7700; line-height: 15px;"&gt;//Behavior prototype by default&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;function&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;close&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;f&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;that&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;{&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;typeof&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;f&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;==&amp;nbsp;&lt;/span&gt;&lt;span class="js-string" style="color: #aa2222; line-height: 15px;"&gt;'function'&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;?&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;function&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;{&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;f&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;apply&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;that&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;arguments&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;}&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;f&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;}&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;resE&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;receiverE&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;resB&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resE&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;startsWith&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;protocol&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;{&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;set&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;function&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;_&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;v&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;{&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;[&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;]&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;v&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resE&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;sendEvent&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;arr&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;}&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;get&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;function&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;_&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-variabledef" style="color: blue; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;{&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;==&amp;nbsp;&lt;/span&gt;&lt;span class="js-string" style="color: #aa2222; line-height: 15px;"&gt;"toSource"&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;close&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-property" style="line-height: 15px;"&gt;toSource&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;[&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;]&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;Behavior&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;prototype&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;close&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;Behavior&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;.&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;prototype&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;[&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;]&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;[&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;p&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;]&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;}&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;}&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class="js-keyword" style="color: #770088; line-height: 15px;"&gt;new&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="line-height: 15px;"&gt;Proxy&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;asObj&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; line-height: 15px;"&gt;?&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;obj&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;resB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class="js-localvariable" style="color: #004499; line-height: 15px;"&gt;protocol&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="js-punctuation" style="color: #88ff88; font-weight: bold; line-height: 15px;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;span class="whitespace" style="color: #666666; line-height: 15px;"&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: xx-small;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="whitespace" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="js-keyword" style="color: #770088; font-size: xx-small; line-height: 15px;"&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="font-size: xx-small; line-height: 15px;"&gt;arr&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;[&lt;/span&gt;&lt;span class="js-string" style="color: #aa2222; font-size: xx-small; line-height: 15px;"&gt;'init'&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;]&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;;&lt;/span&gt;&lt;br style="color: #666666; line-height: 15px;" /&gt;&lt;span class="js-keyword" style="color: #770088; font-size: xx-small; line-height: 15px;"&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="font-size: xx-small; line-height: 15px;"&gt;fxArr&amp;nbsp;&lt;/span&gt;&lt;span class="js-operator" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class="js-variable" style="font-size: xx-small; line-height: 15px;"&gt;bindB&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;(&lt;/span&gt;&lt;span class="js-variable" style="font-size: xx-small; line-height: 15px;"&gt;arr&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;)&lt;/span&gt;&lt;span class="js-punctuation" style="color: #666666; font-size: xx-small; line-height: 15px;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/pMZRdy8xGJY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/7660801575260877723/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=7660801575260877723" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7660801575260877723?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7660801575260877723?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/pMZRdy8xGJY/mixing-functionalimperative-reactive.html" title="Reactive Objects and Arrays via Direct Proxies" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/12/mixing-functionalimperative-reactive.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMARHw7eCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-7845714969033129711</id><published>2012-11-29T12:40:00.002-08:00</published><updated>2013-01-26T23:07:25.200-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:07:25.200-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Google Tech Talk Video on Socio-PLT: Quantitative and Social Theories of Programming Language Adoption</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
My Google Tech Talk on the Socio-PLT work was recorded and posted. It starts with the quantitative stuff + questions on it, and then switches to the social theories: pick your poison.&amp;nbsp;Enjoy!&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://1.gvt0.com/vi/v2ITaI4y7_0/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/v2ITaI4y7_0&amp;fs=1&amp;source=uds" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/v2ITaI4y7_0&amp;fs=1&amp;source=uds" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/-6tndnylIwg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/7845714969033129711/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=7845714969033129711" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7845714969033129711?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/7845714969033129711?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/-6tndnylIwg/google-tech-talk-video-on-socio-plt.html" title="Google Tech Talk Video on Socio-PLT: Quantitative and Social Theories of Programming Language Adoption" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/11/google-tech-talk-video-on-socio-plt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMBRH0yeCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1995979060293577683</id><published>2012-11-28T11:42:00.005-08:00</published><updated>2013-01-26T23:07:35.390-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:07:35.390-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="flapjax" /><title>Temp URLs for Flapjax documentation</title><content type="html">The Flapjax server is a bit wonky right now, so if you are looking for online documentation, check out the following:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://webcache.googleusercontent.com/search?q=cache:XUANgrdCLJIJ:www.flapjax-lang.org/docs/+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=us"&gt;google cache of current docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/flapjax/docs/index.html"&gt;new docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Of course, you can always check the &lt;a href="https://github.com/brownplt/flapjax"&gt;git repo&lt;/a&gt; for the latest.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hope that helps!&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/5rtdW0hne_s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1995979060293577683/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1995979060293577683" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1995979060293577683?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1995979060293577683?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/5rtdW0hne_s/temp-urls-for-flapjax-documentation.html" title="Temp URLs for Flapjax documentation" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/11/temp-urls-for-flapjax-documentation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMCRX4zfip7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1586115978738928734</id><published>2012-11-22T13:34:00.004-08:00</published><updated>2013-01-26T23:07:44.086-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:07:44.086-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>What Women Want</title><content type="html">&lt;a href="http://www.quora.com/Computer-Programming/Which-programming-language-is-the-most-female-friendly"&gt;Trending on Quora&amp;nbsp;&lt;/a&gt;is the question, "Which programming language is the most female friendly?"I do not know (I can provide primary sources who will verify this), but based on our survey of 802 men and 154 women, I can answer which languages females prefer over males.&amp;nbsp;To learn how to think about these questions, see my recent&amp;nbsp;&lt;a href="http://www.youtube.com/watch?v=v2ITaI4y7_0"&gt;Google Tech Talk&lt;/a&gt;&amp;nbsp;or the links below.&lt;br /&gt;
&lt;br /&gt;
Gayle presciently suggests that "Python is also a no-no because, I mean, you just named a language after a snake. Ick! And, I mean, do I need to call out the Freudian imagery there?" Go Gayle -- there is indeed a 3% drop!&amp;nbsp;However, despite Gayle's insight that "All women love shiny objects," that does not help Ruby. Our numbers show a 7% drop for Ruby, so Ruby's&amp;nbsp;&lt;a href="http://martinfowler.com/bliki/SmutOnRails.html"&gt;bad press&lt;/a&gt;&amp;nbsp;might be representative.&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/-iqZg33DLmyA/UK6Y-KCBOCI/AAAAAAAABJU/CBqISFarOqk/s1600/stats.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="271" src="http://1.bp.blogspot.com/-iqZg33DLmyA/UK6Y-KCBOCI/AAAAAAAABJU/CBqISFarOqk/s400/stats.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Overall, we saw little difference among the top 10 languages known by males and females. The ordering is fairly stable, and overall knowledge is similar (see the pink trendline). A few language jumps stand out: C, PHP, C#, and Ruby drop for female knowledge, while &amp;nbsp;Excel rises.&lt;br /&gt;
&lt;br /&gt;
&lt;br class="Apple-interchange-newline" /&gt;
If you're curious, check out our&amp;nbsp;&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/plateau2012.pdf"&gt;methodology&lt;/a&gt;, more of our&amp;nbsp;&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/icse13b.pdf"&gt;statistics&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/data/all.tar.gz"&gt;raw data&lt;/a&gt;, and what a language designed for women&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/L%C3%A1adan"&gt;might look like&lt;/a&gt;. Long story short, for the above statistics, we had good respondents: mostly educated, mostly employed, and biases because we polled students taking a free UC Berkeley online Ruby course on software as a service.&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/-BpzlKq1Eu4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1586115978738928734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1586115978738928734" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1586115978738928734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1586115978738928734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/-BpzlKq1Eu4/what-women-want.html" title="What Women Want" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-iqZg33DLmyA/UK6Y-KCBOCI/AAAAAAAABJU/CBqISFarOqk/s72-c/stats.png" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/11/what-women-want.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMMSXszfSp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1506498498250841429</id><published>2012-11-03T21:00:00.000-07:00</published><updated>2013-01-26T23:08:08.585-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:08:08.585-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><category scheme="http://www.blogger.com/atom/ns#" term="synthesis" /><title>Asymptotic Productivity of a Language Feature</title><content type="html">Good news: our big data visualization DSL has a new name (Superconductor!), runs in a browser, and even more unusual, &lt;i&gt;a per-feature asymptotic analysis&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
We built a synthesizer for Superconductor that automatically maps widget code down into parallel algorithms, but synthesis isn't magic: the more you want it to do, the longer it has to run. Synthesis is essentially a search that automates manual thinking a programmer would have performed. This introduces a new way of thinking about the benefit of language features. Features have a cost, and instead of being in runtime complexity, it is now in compilation speed, which is arguably a formal proxy for developer time. The new language design question is how to tame these costs by isolating them, and when pricey features are still desirable, how to provide levers.&lt;br /&gt;
&lt;br /&gt;
Consider two of the following features in our language:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Automatic full tree traversals.&amp;nbsp;&lt;/b&gt;For a particular top-down parallel traversal over a document, what parts of the (declarative) computation can be safely mapped into it? Not forcing the programmer to figure this out ends up being O(A^2) in the number of static object fields being computed. It took a bit of work (iterative refinement and topological sorting), but well worth it!&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Automatic subtree traversals. &lt;/b&gt;Sometimes, different parts of a tree have different types of data dependencies. For example, text in CSS is represented as a subtree of the document, and several computations over it are inherently sequential such as line wrapping. The tree traversal that encounters text does not need to be sequential, however: for each traversal, we can run different types of subtrees with different types of traversals, and thereby exploit parallelism within some subtrees and even by running disjoint subtrees concurrently. The feature to automatically infer subtree traversals blows up in the number of types of nodes (classes). Basically, each partitioning of the classes is a different way of statically characterizing a different subtree (and matched with a traversal type, a prospective parallelization scheme).&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Synthesis is fast enough that automatic parallelization of full tree traversals are effectively free. However,&amp;nbsp;specializing for per-subtree traversal schedules is only fast for programs with few types of nodes. Subtree traversals are useful in practice (such as if you enjoy stylized text on a webpage!), so we still need to support it. What is a language designer to do?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Deprioritization. Of parallelization can occur without using a slow feature, it will. In this case, the search will look for a full tree traversal before trying subtree ones. O(A^2) asymptotics are actually preserved, even if the full tree traversal is impossible: if there is no full tree traversal, we guarantee there is no subtree traversal, and therefore can stop compilation and terminate with an error. Enumerating all parallelizations will reveal a subtree traversal if it exists, this will not be exercised during most development.&lt;/li&gt;
&lt;li&gt;Sketching. We use sketching for targeted opt-in prioritization of slow features. If you know the third tree traversal of the algorithm should use subtree traversals, say so, and even better, give a hint as to how to group the classes. If you do that, synthesis will still handle mapping individual computations into the traversals, including the subtree ones, and compilation is still O(A^2)!&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
Asymptotics of synthesis is an intriguing way to characterize language features, and perhaps a step towards representing developer effort. It defines how much is 'unsaid' in a precise way, how hard is the 'exercise for the reader'. There is still more to be desired -- the asymptotics is subject to the synthesis algorithm and translation of the features into it -- but I found it to be a neat, and an insightful indicator for productivity.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/T_rfG-DoBxA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1506498498250841429/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1506498498250841429" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1506498498250841429?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1506498498250841429?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/T_rfG-DoBxA/asymptotic-productivity-of-language.html" title="Asymptotic Productivity of a Language Feature" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/11/asymptotic-productivity-of-language.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMNSHo_cSp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-339997137263113605</id><published>2012-08-31T09:17:00.005-07:00</published><updated>2013-01-26T23:08:19.449-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:08:19.449-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Quantifying Social Influences on Language Adoption</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-Uupc-pje_gY/UEDfEJmzWBI/AAAAAAAABI0/2KPKVEhgKA4/s1600/features.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;br class="Apple-interchange-newline" /&gt;&lt;span id="goog_47211661"&gt;&lt;/span&gt;&lt;span id="goog_47211662"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://4.bp.blogspot.com/-y_tA0ZqTnZI/UEDhRb2g9CI/AAAAAAAABI8/wNaGHGKMndg/s1600/features.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="218" src="http://4.bp.blogspot.com/-y_tA0ZqTnZI/UEDhRb2g9CI/AAAAAAAABI8/wNaGHGKMndg/s640/features.tiff" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;b&gt;Average influences for picking a language at work&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
As alluded to in the previous post, Ari and I have been hard at work at quantitatively analyzing how programming languages get adopted &amp;nbsp;-- or fail to. &amp;nbsp;For example, the above chart shows that for commercial projects, &amp;nbsp;social factors (open source libraries, legacy code, and familiarity) matter much more than language support (correctness, simplicity, development speed, tools, language features, ...). This chart is also fascinating because we see that developers act differently depending on the company size.&lt;br /&gt;
&lt;br /&gt;
Check out &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/icse13.pdf"&gt;our draft "Social Influences on Language Adoption"&lt;/a&gt;&amp;nbsp;for more fun charts where we performed and analyzed large surveys and also looked at 10 years of the SourceForge repository with over 200,000 projects. As another example, we validated some of our suspicions in the &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/onward2012.pdf"&gt;sociology survey&lt;/a&gt; that DSLs can be understood in terms of competing niches (e.g., popularity comes from spreading to other niches, not being the best in the niche). We'd love comments! More is in the pipeline -- we'll be releasing the raw data and also a small writeup about the methodological hazards we had to circumvent for this type of research.&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/uHB2N4RMI1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/339997137263113605/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=339997137263113605" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/339997137263113605?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/339997137263113605?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/uHB2N4RMI1E/quantifying-social-influences-on.html" title="Quantifying Social Influences on Language Adoption" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-y_tA0ZqTnZI/UEDhRb2g9CI/AAAAAAAABI8/wNaGHGKMndg/s72-c/features.tiff" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/08/quantifying-social-influences-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIESHk9fip7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-2874124168593444022</id><published>2012-07-27T16:22:00.002-07:00</published><updated>2013-01-26T23:08:29.766-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:08:29.766-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Socio-PLT camera-ready and a glimpse at the next step</title><content type="html">Our Onward! 2012 draft about matching problems in programming languages to social theories about adoption made a stir -- and &lt;a href="http://lmeyerov.blogspot.com/2012/06/socio-plt-quantifying-language.html"&gt;solicited some great comments&lt;/a&gt;. We're cleaning up the &lt;a href="http://www.cs.princeton.edu/~asrabkin/papers/onward12.pdf"&gt;camera ready&lt;/a&gt;, so if there are any final comments, we'd love to incorporate them for the 'final' print version. It's a controversial topic!&lt;br /&gt;
&lt;br /&gt;
As a follow-up, we've been doing some heavy quantitative analysis of extrinsic (social) and intrinsic factors in language adoption. &amp;nbsp;These charts should give you a taste:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://i.imgur.com/SZSzE.png?1" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="146" src="http://i.imgur.com/SZSzE.png?1" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;Fig 1: Factors in Picking a Language for A Recent Project&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://i.imgur.com/3XDYv.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://i.imgur.com/3XDYv.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;Fig 2:&lt;/b&gt;&amp;nbsp;&lt;b&gt;Language Popularity on SourceForge&lt;/b&gt;.&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The first figure is cool in that it shows that social factors are more important than intrinsic features when picking a language. &lt;i&gt;Language designers are community builders.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The second figure starts questioning the social structure. Popularity, city populations, etc. often follow power laws, and therefore growth gets modeled by some intuitive generative processes. However, SourceForge for ~200,000 projects followed an exponential curve. What type of processes can make more sense there?&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Anyways, hope the&amp;nbsp;&lt;a href="http://www.cs.princeton.edu/~asrabkin/papers/onward12.pdf"&gt;camera ready&lt;/a&gt;&amp;nbsp;&lt;span style="background-color: white;"&gt;looks good and the quantitatve analysis sparks thought :)&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/2gnSYEl5GKo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/2874124168593444022/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=2874124168593444022" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2874124168593444022?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2874124168593444022?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/2gnSYEl5GKo/socio-plt-camera-ready-and-glimpse-at.html" title="Socio-PLT camera-ready and a glimpse at the next step" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/07/socio-plt-camera-ready-and-glimpse-at.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIGQHc8cCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-5701130968666625904</id><published>2012-07-06T11:54:00.002-07:00</published><updated>2013-01-26T23:08:41.978-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:08:41.978-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><category scheme="http://www.blogger.com/atom/ns#" term="synthesis" /><title>Synthesis over Parallel Patterns: A Leap Beyond Parallel Frameworks, Types, and Annotations</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-FNKpOhUuTw4/T_ckUdlMfXI/AAAAAAAABH0/tHrv18wF7Dw/s1600/about.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="138" src="http://3.bp.blogspot.com/-FNKpOhUuTw4/T_ckUdlMfXI/AAAAAAAABH0/tHrv18wF7Dw/s320/about.tiff" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
We've been struggling with explaining the theoretical PL parts of our language research, but I think we're finally circling in. Basically, we found attribute grammars OK for defining the functional behavior of CSS and simple enough for running basic compiler analyses, but the formalism is poor for programming over the parallel patterns used for efficient runtime evaluation. That's where our language extensions for synthesizing over parallel patterns comes in.&lt;br /&gt;
&lt;br /&gt;
Synthesizing over / into parallel patterns breaks down to three high-level issues:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;&lt;b&gt;The low-level language of patterns. &lt;/b&gt;&amp;nbsp;The low-level language has to thoroughly express how our crazy-optimized tree traversals can be used. Think of it as the assembly language for parallel algorithms.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;&lt;b&gt;The usable high-level language.&lt;/b&gt; Writing in assembly sucks. Unlike traditional higher-level languages, which suffer from &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;leaky abstractions&lt;/a&gt;, ours is a superset of the low-level one: you can always pick the right level. We do this by adding the simple notion of a&amp;nbsp;&lt;i&gt;hole.&amp;nbsp;&lt;/i&gt;Assemble the patterns where and how you want, but whatever patterns are inferable&amp;nbsp;or unimportant, just leave a hole and let the compiler figure it out.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;&lt;b&gt;The compilation technique&lt;/b&gt; for going from the high-level pattern language to the low-level one. I'll try to give a more detailed explanation in a future post. &amp;nbsp;In a sense, our algorithm is a form of &lt;a href="http://techreports.lib.berkeley.edu/accessPages/EECS-2008-176.html"&gt;CEGIS&lt;/a&gt; (counter-example guided inductive synthesis) that searches over ways to complete a partial program. Every time there is a potential candidate, it checks if any input would trigger a bug in the candidate, and if so, prunes out this and any other completion with the same sort of breakage. Ours is a bit cooler than usual because we have a domain-specific constraint solver, use &lt;i&gt;symbolic&lt;/i&gt; counter examples ones that give asymptotic progress on the search, and we get a queryable debugger for free.&amp;nbsp;&lt;/span&gt;All for another day :)&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;span style="background-color: white;"&gt;First, however, a recap of our use of attribute grammars for the functional specification language, all of which sits besides the pattern specification language.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Background: Attribute Grammars&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
The functional behavior in our language is specified with attribute grammars. &amp;nbsp;For example, to define CSS, you'll say the width of an HBox is the sum of its children. That says nothing about when it is evaluated. Later, via our pattern specification layer, you can control that as well.&amp;nbsp;&lt;span style="background-color: white;"&gt;In theory, other logical specification languages other than attribute grammars can be used, all the way up to your traditional favorite imperative language (see &lt;a href="http://people.csail.mit.edu/asolar/iap2009/"&gt;Sketch&lt;/a&gt;). However, the road from attribute grammars is clear, with most other alternative surface layers adding a painful indirection.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
A traditional attribute grammar would let you declaratively define the horizontal box layout widget as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
HBox -&amp;gt; Node Node 
{ HBox.width := max(HBox0.minWidth, Node1.width + Node2.width); ... }
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Under our extensions (object-orientation, loops, etc.), we would instead write:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
class HBox (paintRect) : Node
&amp;nbsp; attributes:
&amp;nbsp; &amp;nbsp; input minWidth
&amp;nbsp; &amp;nbsp; var intrinsWidth
&amp;nbsp; children:
&amp;nbsp; &amp;nbsp; childs : [ Node ]
&amp;nbsp; constraints
&amp;nbsp; &amp;nbsp; width = max(minWidth, intrinsWidth)
&amp;nbsp; &amp;nbsp; loop childs:
&amp;nbsp; &amp;nbsp; &amp;nbsp; intrinsWidth = fold 0 .. childs[i - 1].width&lt;/div&gt;
&lt;br /&gt;
Hopefully the mapping is intuitive. Our extensions are nice, for example, because we support lists of children. Instead of making an awkward NodeList tree schema with a traditional grammar, you can just have a list of Nodes ("childs : [Node]") in our modernized form (think EBNF). &amp;nbsp;&lt;span style="background-color: white;"&gt;In the end, after some compiler translation, it's the same thing. After reductions, traditional AG compiler checks ensure that every variable is assigned exactly once (well-defined and non-ambiguous spec) and can generate a schedule that orders the assignments. Code generation (e.g., of a layout engine) is a direct step after getting the schedule. &amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="background-color: white;"&gt;In the example, our compiler realizes the width of an HBox should be computed after the loop. More subtle, when and how to perform the loops is determined as well. For example, this grammar defines a tree where some nodes have interface Node, such as HBox ones. The width of these nodes will be computed in a bottom-up or inorder traversal over the entire tree: for an inorder traversal, the compiler would insert a "recur" right before the computation of "intrinsWidth." Writing loopy code in our language is cathartic for this reason. You just say a statement occurs in some loop, and the compiler will figure out in which loop and when, and reason about both local loops over the children of a node and global loops over the tree.&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="background-color: white;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br class="Apple-interchange-newline" /&gt;To learn more about attribute grammars and our use of them for layout language specifications, I previously wrote about our&amp;nbsp;&lt;a href="http://lmeyerov.blogspot.com/2012/03/declarative-loops-or-functional-isnt.html"&gt;declarative looping construct&lt;/a&gt;&amp;nbsp;and an early experience in&amp;nbsp;&lt;a href="http://lmeyerov.blogspot.com/2012/03/modeling-language-experience-report.html"&gt;mechanizing CSS's automatic table layout specification&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The Low-Level Pattern Language&lt;/b&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;Our conceptually deep extension really starts with being able to express this new fragment:&lt;/span&gt;&lt;br /&gt;
&lt;div class="code"&gt;
&lt;span style="background-color: white;"&gt;schedule:&lt;/span&gt;
&lt;span style="background-color: white;"&gt;&amp;nbsp; (bottomUp ((HBox (intrinsWidth width))) ) ; ??&lt;/span&gt;&lt;/div&gt;
I'll get into the "??" bit later, but some of the low-level language shows through here: a &lt;i&gt;bottomUp&lt;/i&gt;&amp;nbsp;(parallel postorder) tree traversal. Both bottom up and inorder tree traversals are valid passes for laying out any tree in this widget language, so our declarative pattern scheduling construct lets you pick which one. Most layout languages have many passes: if there was another class in this language, whatever pass comes after the semicolon would presumably handle whatever it needs to solve.&lt;br /&gt;
&lt;br /&gt;
Our schedules are expressive and fine-grained. The one above says exactly what attributes will be solved in the first bottomUp pass. Furthermore, the compiler will check that these attributes really will be solved in such a traversal. This is great if someone changes code elsewhere that has a non-local impact on the dependency structure, which is quite common in practice. The patterns can be complicated as well, such as using a (sequential) inorder traversal for some subtrees while doing an overall parallel bottom up, so help with reasoning about dependency validity is huge.&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="background-color: white;"&gt;The amazing expressive bit about parallel pattern languages comes next, however.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;High-Level Pattern Language: Declarative Scheduling with Holes&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Imagine our HBox widget is being added to a parallel library. There might be some other traversals that happen after, but we want to guarantee that it will solve in the first one. The sequencing operator ";" runs one pattern after another. Powerfully, instead of saying what pattern to use next, we leave a hole, "??". It might be instantiated as another pattern, say "topDown", or even another composition of patterns, say "topDown ; bottomUp". The synthesizer will figure out what is valid. These can quite non-obvious. For example, we repeatedly found inorder tree traversals that sequentialize a computation can often be eliminated. Instead, a global parallel (topdown or bottomup) traversal is run, and only certain &lt;i&gt;subtrees&lt;/i&gt; will be run as sequential &lt;i&gt;subtraversals&lt;/i&gt;. &lt;br /&gt;
&lt;br /&gt;
Holes can be anywhere (see the last line of the grammar above). If we don't care at all, we might replace the entire schedule with "??". More commonly, we'll specify something like that a bottomUp should be first and then trust the synthesizer to compute the right attributes in it: "(bottomUp ??) ; ??".&lt;br /&gt;
&lt;br /&gt;
Not shown in the grammar above, and generally only rarely exploited, arbitrary Prolog expressions can actually be used to constrain the holes. For example, the schedule may be one where the last traversal is an inorder one that makes sequential rendering calls. Writing "?? ; (Inorder ??)" is incorrect because it presupposes there is a preceding traversal. Prolog, for all its oddities, ended up being a great for such constraints.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Synthesizing over Parallel Patterns&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
The above declarative pattern language let's us automatically use efficient parallel patterns&amp;nbsp;with details where you care and holes where you don't. Synthesis over parallel patterns is powerful and expressive leap over say "@parallel" loop annotations in C++, map/reduce/etc. skeletons in cloud computing, and type-directed data parallelism in Haskell:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Our synthesizer&amp;nbsp;&lt;i&gt;finds&lt;/i&gt;&amp;nbsp;complicated parallel pattern usages. Not discussed, it doubles as a&amp;nbsp;&lt;i&gt;parallelism inspecter/debugger&lt;/i&gt;. (Topic for another day: the algorithms under the patterns, such as my cool &lt;i&gt;semi-static&lt;/i&gt;&amp;nbsp;extension to work stealing that gives temporal locality and drops overheads).&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;Our synthesizer&amp;nbsp;&lt;/span&gt;&lt;i style="background-color: white;"&gt;automatically generates code&lt;/i&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;to exploit the parallelism based on an &lt;i&gt;orthogonal specification&lt;/i&gt;. No need to group code in the spec based on the parallelization scheme!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Our low-level pattern language lets programmers&amp;nbsp;communicate&amp;nbsp;to&amp;nbsp;each other&amp;nbsp;and the&amp;nbsp;compiler&amp;nbsp;the &lt;i&gt;precise&lt;/i&gt; parallelization scheme.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Our&amp;nbsp;high-level pattern language (holes via synthesis) lets programmers communicate at an &lt;i&gt;arbitrarily high level.&lt;/i&gt;&amp;nbsp;Combined with the above, we get some very different styles of parallel programming: sometimes we roll in the mud, sometimes we don't.&lt;/li&gt;
&lt;li&gt;&lt;span style="background-color: white;"&gt;Our synthesizer &lt;/span&gt;&lt;i style="background-color: white;"&gt;checks and&amp;nbsp;rejects&lt;/i&gt;&lt;span style="background-color: white;"&gt;&amp;nbsp;invalid schedules. This is good both when designing the initial code and especially essential when maintaining it. Editing someone else's parallel code is normally terrible: now we can both precisely learn about and check against the previous versions!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
It'll be fascinating to see if the community can get such &lt;i&gt;declarative schedule synthesis&lt;/i&gt;&amp;nbsp;for applying patterns beyond the tree traversal scenario. For example, I bet most graph computations (e.g., stencils) can have their level of abstraction similarly raised through our basic model.&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/IJLRJjgPk9Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/5701130968666625904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=5701130968666625904" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/5701130968666625904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/5701130968666625904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/IJLRJjgPk9Q/synthesis-over-parallel-patterns.html" title="Synthesis over Parallel Patterns: A Leap Beyond Parallel Frameworks, Types, and Annotations" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-FNKpOhUuTw4/T_ckUdlMfXI/AAAAAAAABH0/tHrv18wF7Dw/s72-c/about.tiff" height="72" width="72" /><thr:total>1</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/07/synthesis-over-parallel-patterns.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIHQ3szfCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-6601689487423386994</id><published>2012-06-06T15:36:00.005-07:00</published><updated>2013-01-26T23:08:52.584-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:08:52.584-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Socio-PLT: Quantifying Language Perception</title><content type="html">We finally released our &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/index.html"&gt;interactive visualizations for exploring programmer beliefs about programming languages&lt;/a&gt;. We've been scouring several large data sets -- 10 years of SourceForge repo data, mass surveys of thousands of programmers each, etc. -- so visualizations like these help us get a grip on what's going on. Beyond revealing many surprises, such as static typing anti-correlating with code reuse, they are fun to play with.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/index.html"&gt;Check it out!&lt;/a&gt;&amp;nbsp;(Animations are fastest in Chrome/Safari)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;img border="0" height="281" src="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/zoom.png" width="320" /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/5lHvmvaVOyA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/6601689487423386994/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=6601689487423386994" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6601689487423386994?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6601689487423386994?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/5lHvmvaVOyA/socio-plt-quantifying-language.html" title="Socio-PLT: Quantifying Language Perception" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/06/socio-plt-quantifying-language.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIARnsyeyp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-2915586796249183033</id><published>2012-04-08T18:47:00.007-07:00</published><updated>2013-01-26T23:09:07.593-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:09:07.593-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt" /><title>Socio-PLT: Principles for Programming Language Adoption</title><content type="html">Ari and I are getting ready to send out our first paper on &lt;b&gt;&lt;i&gt;socio-PLT&lt;/i&gt;&lt;/b&gt;, the sociology of programming languages. We've been performing qualitative and quantitative analysis of language adoption, and I've been thinking about how to apply sociological principles to the design of my own languages. This paper 1) overviews some of my favorite cases that I gleaned from reviewing relevant sociology  research over the past few years and 2) connects it to programming language design, both in the scientific design of existing features and the principled and creative design of new ones. Basically, it shows how understanding results from sociology can influence your approach to language design :)&lt;br /&gt;
&lt;br /&gt;
I just &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf"&gt;put up a draft&lt;/a&gt; and would love comments. I suspect the paper may be controversial, but I would like it to be so for the right reasons :) Did we misrepresent anyone or leave out any awesome case studies? Was anything belabored and boring, or terse and tantalizingly vague? This is still in the draft state, so we have a lot to do and would appreciate feedback :)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf"&gt;&lt;b&gt;Socio-PLT: Principles for Programming Language Adoption&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;
&lt;blockquote&gt;
&lt;br /&gt;
Why does one programming language fail and another succeed? What does this tell us about programming language design, implementation, and principles? To help answer these and other questions, we argue for examining the sociological basis  of programming language theory: &lt;i&gt;socio-PLT&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
This paper presents a survey for programming language adoption principles drawn from various  sociological fields. For example, many programming language features provide benefits that programmers cannot directly and immediately observe and therefore may not find compelling. From clean water to safe sex, the health community has long examined how to surmount similar observability barriers. We discuss how principles and techniques drawn from social sciences such as economics, public health, and historical linguistics relate to programming languages. Finally, we examine implications of our approach, such as for the design space of language features and even the expectations of scientific research into programming languages.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
Looking forward to your thoughts! (&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf"&gt;draft pdf&lt;/a&gt;)&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/OH_75EVw85c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/2915586796249183033/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=2915586796249183033" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2915586796249183033?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2915586796249183033?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/OH_75EVw85c/socio-plt-principles-for-programming.html" title="Socio-PLT: Principles for Programming Language Adoption" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>9</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/04/socio-plt-principles-for-programming.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACQH88fSp7ImA9WhNaEks.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-2761097867189524420</id><published>2012-03-10T00:18:00.007-08:00</published><updated>2013-01-26T20:59:21.175-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T20:59:21.175-08:00</app:edited><title>Languages for Bad Programmers</title><content type="html">&lt;i&gt;&lt;b&gt;Bad programmers are linguistic victims and good programmers are masochists.&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Brett Victor is going viral with an&amp;nbsp;&lt;a href="http://www.ritholtz.com/blog/2012/02/bret-victor-inventing-on-principle/" style="font-family: Georgia, serif;"&gt;inspiring video on language and tool design&lt;/a&gt; (and philosophy). The language community has actually already made some strong strides in the directions he wants. Some of my favorite research is in  &lt;a href="http://www.blogger.com/www.youtube.com/watch?v=faJ8N0giqzw" style="font-family: Georgia, serif;"&gt;tangible programming&lt;/a&gt;, &amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Live_coding" style="font-family: Georgia, serif;"&gt;live coding&lt;/a&gt;, and &lt;a href="http://www.lambdacs.com/debugger/"&gt;omniscient debuggers&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://patricklam.ca/" style="font-family: Georgia, serif; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;Patrick Lam&lt;/a&gt;&lt;span style="font-weight: normal;"&gt; picked up on something else. As part of Brett Victor's philosophy that every code artifact should be directly (physically) manipulatable and understood, Brett believes requiring indirect manipulation and indirect understanding to be language design flaws. In particular, programming should not require mentally simulating an abstract Von Neumann machine that steps through your program. Not everyone agrees: Pat observed that, on the list of &lt;/span&gt;&lt;a href="http://badprogrammer.infogami.com/" style="font-family: Georgia, serif; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;signs of being a bad programmer&lt;/a&gt;&lt;span style="font-weight: normal;"&gt;, the very first warning that you are a bad programmer if you cannot "run the program in your head". &lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;span style="font-family: Georgia, serif; font-weight: normal;"&gt;Here's the thought. &lt;/span&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;What would a language for bad programmers look like?&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: Georgia, serif; font-weight: normal;"&gt; Looking at the list of hacky "bad" programming practices, can you imagine a future where language and tool support will advance enough that they're the acceptable norm? &lt;/span&gt;&lt;span style="font-weight: normal;"&gt;The "bad" habits actually form an admirable set of goals for the language research community:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Warning sign:&lt;/span&gt;&lt;/b&gt; Cannot simulate the program in their head.&lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Goal:&lt;/span&gt; &lt;/b&gt;Get the computer to do the simulation.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Have a poor understanding of the language's programming model.&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Goal:&lt;/span&gt; &lt;/b&gt;If I make basic grammatical mistakes when I speak, people correct me -- why doesn't the compiler?&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Chronically poor knowledge of the platform's features. Symptoms: reinvent language and framework code, "Email me teh code, plz" messages on forums, etc. &lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Goal:&lt;/span&gt; &lt;/b&gt;Instead of viewing code copying as a bug, it's a design goal: I suspect *most* code today is duplicated, so I look forward to the future where the emphasis is on searching and synthesizing code rather than learning and writing it.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Struggle to comprehend pointers. Symptoms: failure to implement a linked list, allocates arbitrarily big arrays, inability to find pointer arithmetic bugs, etc. &lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Goal:&lt;/span&gt; &lt;/b&gt;raise the level of abstraction so programmers don't have to think about these issues.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;&lt;span style="color: red;"&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Have difficulty seeing through recursion.&lt;br /&gt;&lt;b&gt;&lt;span style="color: blue;"&gt;Goal:&lt;/span&gt; &lt;/b&gt;Thinking concretely should be fine, and the tools should walk you through the base cases and generalization.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
You can apply similar reasoning to the category of "mediocre programmers" and, my favorite, "pinball programmers". Pinball programmers struggle with edge cases, or simply do not care. They can be a security disaster.&lt;b&gt; Again, however.... so what? These types of problems are exactly what we built computers to solve: rote grunt work.&lt;/b&gt;&lt;/div&gt;
&lt;div style="font-weight: normal;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-weight: normal;"&gt;The shocking conclusion of the bad programmer essay is the signs that you shouldn't be a programmer. If you cannot determine the order of program execution, cannot think abstractly, poorly organize your code as an ever-expanding ball of mud, believe the code and runtime are unreliable, or simply don't care about much of the code quality, you shouldn't be a programmer. Hogwash!&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: Georgia, serif;"&gt;&lt;b&gt;If these traits are required for programming, our ability to write code that keeps growing in ambition by  magnitudes seems doomed&lt;/b&gt;. &lt;/span&gt;&lt;span style="font-family: Georgia, serif; font-weight: normal;"&gt;I can fairly neatly bucket these warning signs as &lt;i&gt;inevitable programming realities&lt;/i&gt; (massive and concurrent code on unreliable hardware) and &lt;i&gt;goals&lt;/i&gt; ("search, don't sort"; declare what instead of how).&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-weight: normal;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="font-weight: normal;"&gt;
Maybe the programmers aren't really all that bad. It sounds like today's languages are the stupid ones.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(Updated 1/26/2013 with minor editing.)&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/lV8-pEN1Crw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/2761097867189524420/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=2761097867189524420" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2761097867189524420?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2761097867189524420?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/lV8-pEN1Crw/languages-for-bad-programmers.html" title="Languages for Bad Programmers" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/03/languages-for-bad-programmers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkICSHg-eCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-1536252878005933288</id><published>2012-03-07T20:57:00.004-08:00</published><updated>2013-01-26T23:09:29.650-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:09:29.650-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><category scheme="http://www.blogger.com/atom/ns#" term="synthesis" /><title>Loop synthesis: more declarative than functional programming?</title><content type="html">As part of the FTL language, I've been playing with the idea of declarative loops. For example, I'd like to write:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
&lt;br /&gt;
for i in range(0, n):&lt;br /&gt;
b[i + 1] = g(a[i]); &lt;br /&gt;
a[i - 1] = f(b[i - 4]);&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
First, the synthesizer should figure out that the problem is under-constrained. It should report that the following values are undefined:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
&lt;br /&gt;
a[0..2] = ??&lt;br /&gt;
b[0] = ??&lt;br /&gt;
a[n] = ??&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
If, as suggested by the synthesizer, I refined the program to be consistent:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
&lt;br /&gt;
a[0..2] = 0&lt;br /&gt;
b[0] = 0&lt;br /&gt;
a[n] = 0&lt;br /&gt;
for i in range(0, n):&lt;br /&gt;
b[i + 1] = g(a[i]); &lt;br /&gt;
a[i - 1] = f(b[i - 4]);&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
I'd like to get:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="code"&gt;
&lt;br /&gt;
a[0] = 0&lt;br /&gt;
a[1] = 0&lt;br /&gt;
a[2] = 0&lt;br /&gt;
b[0] = 0&lt;br /&gt;
b[1] = g(a[0])&lt;br /&gt;
b[2] = g(a[1])&lt;br /&gt;
b[3] = g(a[2])&lt;br /&gt;
for (int i = 3; i &amp;lt; n - 1; i++) {&lt;br /&gt;
a[i] = f(b[i - 3]);&lt;br /&gt;
b[i + 1] = g(a[i])&lt;br /&gt;
a[n] = 0&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the synthesizer performed loop peeling -- it figured out to do loop peeling to emit assignments for b[1], b[2], and b[3]. Furthermore, it reordered the assignments in the loop and performed loop skewing -- it changed the indices of the assignments, such as from a[i - 1] to a[i], to ensure an array value is written before it is read.&lt;br /&gt;
&lt;br /&gt;
Milind and I just worked out most of the theory for this today. You can think of it as a generalization of attribute grammar synthesis to loop code. Basically, if we assume the input code is singly assigned -- array values should have one unique value -- this is a matter of unrolling the intermediate steps of the loop, scheduling their dependency graph, and reconstructing the Von Neumann-friendly loop. The weekend may be busy :)&lt;br /&gt;
&lt;br /&gt;
A fun question is whether a functional program could declaratively handle the above. For example, it could expand the for loop into a dependency graph and then use demand-driven evaluation. However, there are two problems. First, the interpretation of indices would have to change: my code correctly skewed the loop indices to make sure "a[i - 1]" and "b[i - 4]" are never negative. Second, the loop would be unsafe: in my approach, the synthesizer can statically check that the array is fully defined. Either way, traditional functional languages force programmers to explicitly handle these (arguably) low-level loop details. Go synthesis!&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/KLm2iDwxVVI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/1536252878005933288/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=1536252878005933288" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1536252878005933288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/1536252878005933288?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/KLm2iDwxVVI/declarative-loops-or-functional-isnt.html" title="Loop synthesis: more declarative than functional programming?" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>2</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/03/declarative-loops-or-functional-isnt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIMRnszeSp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-6207887177589871181</id><published>2012-03-04T15:37:00.012-08:00</published><updated>2013-01-26T23:09:47.581-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:09:47.581-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><category scheme="http://www.blogger.com/atom/ns#" term="synthesis" /><title>Modeling language experience report: synthesizing CSS's automatic table layout solver</title><content type="html">&lt;a href="http://2.bp.blogspot.com/-DDDnneRbmgU/T1QDV-bEmuI/AAAAAAAAAvM/BRi0Febgxts/s1600/table.tiff" style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5716197503108684514" src="http://2.bp.blogspot.com/-DDDnneRbmgU/T1QDV-bEmuI/AAAAAAAAAvM/BRi0Febgxts/s400/table.tiff" style="cursor: hand; cursor: pointer; display: block; height: 165px; margin: 0px auto 10px; text-align: center; width: 161px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style="font-size: 100%; text-align: center;"&gt;
&lt;b&gt;Table rendered using an automatically synthesized layout solver.&lt;/b&gt;&lt;/div&gt;
&lt;div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;
&lt;span style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;&lt;span style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;Model-driven languages handle complexity in implementing a language. For example, after designing a language feature, you want it to work with the optimizer, parser, IDE, etc. As the language gets more complicated, such as we've seen with the increasing scope of the CSS layout language, the implementation burden gets so high that many seemingly small language extensions and tool improvements require understanding a lot of the eco-system. With modeling languages, we can use synthesizers and code generators to correctly write features, avoid duplication of work, and basically handle more code than you could manually. For example, we don't want to manually teach the Firebug debugger about CSS semantics nor, when parallelizing for multicore or SIMD hardware, do we want to manually look at every edge case in the layout specification.&lt;br /&gt;&lt;br /&gt;We picked attribute grammars as the basic specification language for our parallel browser layout language work. However,  this begs the question: are attribute grammars expressive enough to actually handle layout languages?** Previously, we wrote (and automatically parallelized) various visualizations, so we know attribute grammar can be used for &lt;/span&gt;&lt;i style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;future&lt;/i&gt;&lt;span style="font-size: 100%;"&gt;&lt;span style="font-size: 100%;"&gt; languages. We're now going after the elephant in the room: CSS. As a fun start, &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;Ras and I just put together an &lt;/span&gt;&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/pbrowser/pubfiles/tables/tablesidealClean3.html" style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;experience report&lt;/a&gt;&lt;span style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt; about our successful experience with synthesizing an implementation of the 'automatic table layout' specification. &lt;/span&gt;&lt;br /&gt;
&lt;div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;
&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family: Georgia, serif; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"&gt;
&lt;span style="font-size: 100%;"&gt;In short, it works. The table above was rendered using an automatically generated layout engine. Furthermore, our synthesizer found a multicore implementation for it. Neat :)&lt;/span&gt;&lt;br /&gt;
&lt;div style="font-size: 100%;"&gt;
&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-size: 100%;"&gt;
&lt;span style="font-size: 100%;"&gt;Stay tuned for more and we'll welcome any challenge problems :) Props to Ras, Matt, and Sam for help in revising that report!&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-size: 100%;"&gt;
&lt;span style="font-size: 100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
**: More specifically, can we do this with statically scheduled attribute grammars? I'm distinguishing against 'demand-driven' and other approaches that essentially reduce to the Turing tar pit via general lazy functional programming. &lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/v9p89m_NA4Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/6207887177589871181/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=6207887177589871181" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6207887177589871181?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6207887177589871181?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/v9p89m_NA4Q/modeling-language-experience-report.html" title="Modeling language experience report: synthesizing CSS's automatic table layout solver" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-DDDnneRbmgU/T1QDV-bEmuI/AAAAAAAAAvM/BRi0Febgxts/s72-c/table.tiff" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/03/modeling-language-experience-report.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQFQnw6cCp7ImA9WhRbFk0.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-8824986813202364209</id><published>2012-02-06T22:44:00.000-08:00</published><updated>2012-02-07T00:28:33.218-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-07T00:28:33.218-08:00</app:edited><title>Rich macros in ANTLR grammars</title><content type="html">For the lastest extension to FTL, my declarative user interface language, I wanted to add some code sharing abilities: traits and file includes. These are purely syntactic AST transformations but tricky for tools like ANTLR because the transformations are non-local.&lt;br /&gt;&lt;br /&gt;For example, I wanted to be able to write the following code in FTL:&lt;br /&gt;&lt;div class="code"&gt;trait ChildCount {&lt;br /&gt; attributes {&lt;br /&gt;   var numChildren : int;&lt;br /&gt; }&lt;br /&gt; constraints {&lt;br /&gt;   loop boxes {&lt;br /&gt;     numChildren := fold 0 .. $-.numChildren + 1;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class HBox(ChildCount) : Node {&lt;br /&gt; children {&lt;br /&gt;   boxes : [ Node ];&lt;br /&gt; }&lt;br /&gt; attributes {&lt;br /&gt;   var render : Scene;&lt;br /&gt; }&lt;br /&gt; constraints {&lt;br /&gt;   render := text(10, 10, numChildren, #FF0);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Desugaring would eliminate the traits through a global transformation. In this case, it yields:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;class HBox : Node {&lt;br /&gt; children {&lt;br /&gt;   boxes : [ Node ];&lt;br /&gt; }&lt;br /&gt; attributes {&lt;br /&gt;   var render : Scene;&lt;br /&gt; }&lt;br /&gt; constraints {&lt;br /&gt;   render := text(10, 10, numChildren, #FF0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; attributes {&lt;br /&gt;   var numChildren : int;&lt;br /&gt; }&lt;br /&gt; constraints {&lt;br /&gt;   loop boxes {&lt;br /&gt;     numChildren := fold 0 .. $-.numChildren + 1;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(I'm glossing over hygiene etc. for the purposes of this post).&lt;br /&gt;&lt;br /&gt;I got a fairly good start based &lt;a href="http://www.ibm.com/developerworks/aix/library/au-c_plusplus_antlr/index.html"&gt;on&lt;/a&gt; &lt;a href="http://www.antlr.org/pipermail/antlr-interest/2009-September/035854.html"&gt;these&lt;/a&gt; &lt;a href="http://www.antlr.org/wiki/pages/viewpage.action?pageId=557057"&gt;posts&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Eventually, I realized I had two problems:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Given a usage of a trait (as a parse tree) and the trait's expansion (as a string), how do I make desugared parse tree? While it may be possible to do the expansion earlier (e.g., lexing), this is a cleaner step. For example, the error handling is better: we get clean parse errors for the unexpanded form (e.g., trait was not found or is in the wrong place) and for bad expansions (e.g., the trait references an identifier unavailable at its point of use).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How do I incorporate the new parse into the semantics actions associated with the parser? For example, if the parser counts the number of nodes, it should be of the final desugared parse tree. Counting the original nodes would be wrong, as would the sum of the original + new.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;The final solution was pretty simple at heart:&lt;br /&gt;&lt;br /&gt;First, I told ANTLR to store the traits:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;Trait :&lt;br /&gt; 'trait' id '{' body[false,null] '}'&lt;br /&gt; { traits.put($id.text, $body.text); }&lt;br /&gt; ;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Second, I used a &lt;i&gt;tree rewrite rule&lt;/i&gt; that replaces uses of traits with   &lt;i&gt;subtrees that are programmatically constructed in a semantic action&lt;/i&gt; through invocations of &lt;i&gt;sub-rule parser methods&lt;/i&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;classTrait :&lt;br /&gt; 'class' c=id '(' tId=id ')' ':' typeId=id&lt;br /&gt;   {&lt;br /&gt;     FtlClass cls = new FtlClass($cName.text);&lt;br /&gt;     String traitBodyStr = traits.get($tId.text);&lt;br /&gt;   }&lt;br /&gt;  '{' body[true, cls] '}'&lt;br /&gt;   {&lt;br /&gt;    CharStream inputstream = null;&lt;br /&gt;    inputstream = new ANTLRStringStream(traitBodyStr);&lt;br /&gt;    ALEParser innerparser = new ALEParser(new CommonTokenStream(new ALELexer(inputstream)));&lt;br /&gt;    CommonTree traitBody = (CommonTree)(innerparser.body(true, cls).getTree());&lt;br /&gt;    transferStatePost(innerparser);&lt;br /&gt;  }&lt;br /&gt;  -&amp;gt; ^('class' $c ':' $typeId '{' body {traitBody} '}')&lt;br /&gt;  ;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The idea is that for a class using a trait, we lookup the trait (traitBodyStr), create a new parse subtree from it (traitBody), and replace it with a new subtree (righthand side of -&amp;gt;) that incorporates a programmatically generated subtree (&lt;i&gt;traitBody&lt;/i&gt;). &lt;br /&gt;&lt;br /&gt;A subtle but important practical point is that, for the programmatic call to a sub-rule parser -- &lt;i&gt;body(true,cls)&lt;/i&gt; -- innerparser is a new parser with its own state. We can pass parameters to it such as (true, cls) or initialize the parser state to mimic the current one (e.g., duplicate the symbol table), and get them back out. In this case, I needed some post-parsing parser state, so I added my custom method &lt;i&gt;transferStatePost&lt;/i&gt; to handle it.&lt;br /&gt;&lt;br /&gt;Bonus for any compiler DSL writers: could you synthesize the tree rewrite rule from my example? :)&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/w7gS-vIZwp8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/8824986813202364209/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=8824986813202364209" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/8824986813202364209?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/8824986813202364209?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/w7gS-vIZwp8/rich-macros-in-antlr-grammars.html" title="Rich macros in ANTLR grammars" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/02/rich-macros-in-antlr-grammars.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkINSXg6cCp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-8360239699012335055</id><published>2012-01-31T01:12:00.001-08:00</published><updated>2013-01-26T23:09:58.618-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:09:58.618-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><title>The fallacy of race to halt: power measurements from vectorizing webpage layout and binary search</title><content type="html">&lt;a href="http://3.bp.blogspot.com/-gtrv6G4stSI/TyewrwZOwjI/AAAAAAAAAfo/ZsqAmHj3C6w/s1600/power2.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5703721718859612722" src="http://3.bp.blogspot.com/-gtrv6G4stSI/TyewrwZOwjI/AAAAAAAAAfo/ZsqAmHj3C6w/s400/power2.png" style="cursor: hand; cursor: pointer; display: block; height: 211px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://1.bp.blogspot.com/-q_q8CNIWKBE/Tyewr0g0c2I/AAAAAAAAAfc/DHlE48kB1Ys/s1600/power1.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5703721719965184866" src="http://1.bp.blogspot.com/-q_q8CNIWKBE/Tyewr0g0c2I/AAAAAAAAAfc/DHlE48kB1Ys/s400/power1.png" style="cursor: hand; cursor: pointer; display: block; height: 255px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;
An important rule of optimization is that you don't know if it worked until you've measured it. Parallel algorithms research, until recently, has violated this rule. Researchers typically report speedup (old time / new time) or scaling (sequential time / parallel time), but that is wrong. The main reason we even care about parallel algorithms is that parallel hardware &lt;i&gt;might&lt;/i&gt; provide more performance per Watt (PPW) &lt;i&gt;if we use it properly&lt;/i&gt;. Otherwise, we should just turn up the clock rate and forget about it. &lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
One of the most efficient forms of parallelism is SIMD, so I finally had a good opportunity to measure PPW vs. speedup for an algorithms paper we're finishing. For example, for our SIMD webpage layout algorithm performance (top picture),  our 5x of speedup comes with an 8.5x PPW increase.  Likewise, we sped up the binary search algorithm you learn in school by 15.8x and with a corresponding improvement on PPW of 13.1x. The biggest PPW wins were consistently from SIMD evaluation. &lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The surprise is that not all speedups improve PPW. We often assume work-efficient algorithms (parallel asymptotics do not dominate sequential ones) will, at worst, not impact PPW. Such "race to halt" reasoning is a good intuition, but even "intuitive" cases can break it. For example, take a closer look at our binary search results. Cache line blocking, a common high performance computing trick for better data prefetching, gives speedups for our binary search algorithm (both eager and optimistic speculative variants), but decreases PPW for the optimistic case.  Measuring cache line blocking energy consumption clearly shows it hurts  performance -- but based on speedup numbers and conventional wisdom, I wouldn't have bet that way.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;i&gt;Addendum&lt;/i&gt;&lt;/b&gt;: At a lab-wide meeting where I gave an impromptu talk about these results, a surprising discussion ensued. What performance numbers do we actually care about? For example, I originally reported the increase in performance per Watt achieved over 1 second (so improvement of # queries / joules in that time period). However, in many scenarios, if I changed 1 second to be the time for 20 queries or some other fixed amount, PPW could be very different. The machine might go into a power-wasting turbo mode for such a short time interval and PPW would plummet. Switching to performance per Joule (or total Joules for a task) has similar issues. So what are we optimizing for, really?&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/A3mMpVKtJzU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/8360239699012335055/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=8360239699012335055" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/8360239699012335055?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/8360239699012335055?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/A3mMpVKtJzU/fallacy-of-race-to-halt-power.html" title="The fallacy of race to halt: power measurements from vectorizing webpage layout and binary search" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-gtrv6G4stSI/TyewrwZOwjI/AAAAAAAAAfo/ZsqAmHj3C6w/s72-c/power2.png" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/01/fallacy-of-race-to-halt-power.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGQH0zfSp7ImA9WhRUFEo.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-2343945608945847117</id><published>2012-01-24T22:51:00.001-08:00</published><updated>2012-01-24T22:52:01.385-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-24T22:52:01.385-08:00</app:edited><title>Note to self</title><content type="html">Note to self: remember to include the phrase "We are 4.9x faster than FAST, the recent binary search algorithm ..." into the paper rewrite.&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/soMST7Fp1fk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/2343945608945847117/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=2343945608945847117" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2343945608945847117?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/2343945608945847117?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/soMST7Fp1fk/note-to-self.html" title="Note to self" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2012/01/note-to-self.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AHRX46fSp7ImA9WhRWEkU.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-6883585647744659591</id><published>2011-12-30T13:44:00.000-08:00</published><updated>2011-12-30T13:48:54.015-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-30T13:48:54.015-08:00</app:edited><title>Natbib for LNCS / splncs.bst</title><content type="html">It took me awhile to find this, but if you want to use \citeauthor, \citet macros from natbib, etc. for Springer / LNCS papers, use &lt;a href="http://phaseportrait.blogspot.com/2011/02/natbib-compatible-bibtex-style-bst-file.html"&gt;this package&lt;/a&gt;. If you aren't using these macros, you should: it will avoid heartache from misspelling author names. If you are not mentioning author names, this may also help put you into the habit.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;\documentclass{llncs}&lt;br /&gt;\usepackage[numbers]{natbib}&lt;br /&gt;\bibliographystyle{splncsnat}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Springer, please fix this!&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/Hv0PQaQxhCc" height="1" width="1"/&gt;</content><link rel="related" href="http://phaseportrait.blogspot.com/2011/02/natbib-compatible-bibtex-style-bst-file.html" title="Natbib for LNCS / splncs.bst" /><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/6883585647744659591/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=6883585647744659591" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6883585647744659591?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6883585647744659591?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/Hv0PQaQxhCc/natbib-for-lncs-splncsbst.html" title="Natbib for LNCS / splncs.bst" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2011/12/natbib-for-lncs-splncsbst.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEGR3w7eip7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-324712449523146221</id><published>2011-12-25T14:59:00.000-08:00</published><updated>2013-01-26T23:10:26.202-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:10:26.202-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><category scheme="http://www.blogger.com/atom/ns#" term="synthesis" /><title>FTL: Fast Tree Language for synthesizing a parallel layout engine</title><content type="html">&lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/pbrowser/pubfiles/spiraldemo2/364.html" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5690215430624033122" src="http://1.bp.blogspot.com/-1FnhUDcReBE/Tve0yT3KuWI/AAAAAAAAAWk/Qb9Qql-eKgQ/s400/files3.tiff" style="cursor: pointer; display: block; height: 400px; margin: 0px auto 10px; text-align: center; width: 382px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
A radial layout widget declaratively specified in FTL being used to visualize file directory structure. Achieves 22fps through quadcore layout and GPU rendering. Check out the &lt;a href="http://www.eecs.berkeley.edu/~lmeyerov/projects/pbrowser/pubfiles/spiraldemo2/364.html"&gt;HTML5 version and source code&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
We finally submitted &lt;a href="http://eecs.berkeley.edu/~lmeyerov/projects/pbrowser/pubfiles/ftl.pdf"&gt;a paper about FTL&lt;/a&gt;, our language for specifying layout languages and synthesizing a parallel evaluator. The paper is dense, so we'd appreciate feedback on what to cut and what to expand :)&lt;br /&gt;
&lt;br /&gt;
Our systems goes all the way from a high-level language specification to an optimized browser layout engine. We had to solve two basic problems:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Strongly scaling the parallel tree traversals.&lt;/span&gt; Our specification analysis will take a language specification, such as for CSS, and find a sequence of parallel tree traversals that will lay out any document (the tree) in that language. However, we couldn't find any existing algorithms that would give you a 2x speedup on 2 cores, 4x speedup on 4 cores, etc. We ended up A) finding a mix of existing data layout optimizations (pointer compression, blocking, etc.) and B) inventing our own runtime task scheduler (semi-static scheduling that &lt;span style="font-style: italic;"&gt;simulates&lt;/span&gt; work stealing to precompute a partitioning). Scaling plummets if you drop either. More fun, due to the locality benefits of data layout optimizations, we achieve superlinear speedups -- 9.2.x on 8 cores!&lt;/li&gt;
&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Generating the &lt;span style="font-style: italic;"&gt;right&lt;/span&gt; sequence of tree traversals.&lt;/span&gt; While our system will automatically find parallelism in a declarative specification, it won't find all. For example, specifying how a box lays out its children by using absolute coordinates creates a global dependency, but specifying them as coordinates relative to the box and then stitching them together to get the absolute ones will break the dependency enough for our analysis. Programmers can write queries about the set of schedules inferable from a specification to help debug this sort of problem. &lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
We found reasoning about schedules to be such a helpful programming tool that we incorporated it into our specification language. For example, it's very convenient to make rendering calls within a specification, e.g., "box(self.x,self.y,self.w,self.h,self.color)". The specification must take care to say what order to render boxes, such as the foreground text being above the background. Z indices are ambiguous due to overlap and monadically passing around the dependency is really painful. We can take a lesson from the current informal CSS standard, which specifies the document traversal order and then locally defines order within each node. Our solution is to allow functional specifications (the grammar) to be refined with traversal order constraints ("do rendering in an inorder traversal"). We can also catch specification changes that violate such a constraint!&lt;br /&gt;
&lt;br /&gt;
Synthesizing schedules yields extra benefits. When synthesizing an implementation that talks to legacy code, this has the added benefit of making it easy to avoid parallel calls into non-reentrant libraries. Furthermore, many different traversals will implement the same specification: our synthesizer can generate them and autotune over them.&lt;br /&gt;
&lt;br /&gt;
I'm working with some great undergrads to move forward on several fronts. At MSR, I wrote a proof-of-concept manual implementation that uses SIMD instructions for further speedups within a core: we're now automating it as a new FTL backend. Next, Thibaud Hottelier is writing a visualization language based on bidirectional constraints that compiles to FTL, which our undergrads are using to write some stunning demos. I already wrote one to animate inspecting file sizes on your hard drive (see picture above): we get 22fps for animating 20,000 files, and we should handle bigger data sets once I fix some segfaults. [For reference -- the HTML5 version is 8fps and, on my phone, 1fps]. Finally, we're pushing FTL's expressive limits by formalizing the CSS standard in it. Fun times ahead!&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/oJ1DedgrDwU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/324712449523146221/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=324712449523146221" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/324712449523146221?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/324712449523146221?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/oJ1DedgrDwU/ftl-fast-tree-language-for-synthesizing.html" title="FTL: Fast Tree Language for synthesizing a parallel layout engine" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-1FnhUDcReBE/Tve0yT3KuWI/AAAAAAAAAWk/Qb9Qql-eKgQ/s72-c/files3.tiff" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2011/12/ftl-fast-tree-language-for-synthesizing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEHSXY9fSp7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-6266688877065559265</id><published>2011-09-12T12:40:00.000-07:00</published><updated>2013-01-26T23:10:38.865-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-26T23:10:38.865-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser" /><title>What to Implement</title><content type="html">&lt;div style="text-align: center;"&gt;
&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;
&lt;a href="http://4.bp.blogspot.com/-_VdG3Fz1vqY/Tm5j9Mg3YSI/AAAAAAAAARE/rsL7erljXJ8/s1600/propertydistribution.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5651564485378793762" src="http://4.bp.blogspot.com/-_VdG3Fz1vqY/Tm5j9Mg3YSI/AAAAAAAAARE/rsL7erljXJ8/s400/propertydistribution.png" style="cursor: hand; cursor: pointer; display: block; height: 400px; margin: 0px auto 10px; text-align: center; width: 284px;" /&gt;&lt;/a&gt;&lt;br /&gt;
A big chunk of the coding side of my thesis is writing a declarative spec of CSS and then  automatically generating a fast/correct/instrumentable/etc. implementation from it. However, how much do I really need to implement? More generally, if you're making a tool to compute over webpage style, how much do you really care about? E.g., if you make a proxy-based layout optimizer, which features are important? Full compliance, ACID tests, etc. are often an overkill.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To help pick a subset to focus on, I ran a bunch of popular pages through my parallel browser skeleton and counted dynamic occurrences of CSS attributes. For example, if a browser or user defined style property is that images inside paragraphs get a blue border ("p img { border: blue; }"), and a gallery has 2 such pictures, that counts as 2 hits on feature "border". &lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For many features, the options -- e.g., blue vs. red, 10" vs. 20% -- are easy to handle. For others, the cases are a big deal: e.g., a table ("display: table") vs. word-wrapping box ("display: block"). So, for some of the more common features, I also broke down the cases. &lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The diagrams below show first the features and then, for a couple, the cases. It might be interesting to also do a log plot (power law, anyone?). Basically, you can get legible (but wonky) looking sites without much. To get pixel perfect... not so much.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://3.bp.blogspot.com/-ZrJMgQ2sLG4/Tm5kXv28mPI/AAAAAAAAARc/sSP7NF6eL5Q/s1600/position.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5651564941543250162" src="http://3.bp.blogspot.com/-ZrJMgQ2sLG4/Tm5kXv28mPI/AAAAAAAAARc/sSP7NF6eL5Q/s400/position.png" style="cursor: pointer; display: block; height: 241px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://3.bp.blogspot.com/-_CyEblMl3UY/Tm5kUDy2h1I/AAAAAAAAARU/IIEl2fUjgUc/s1600/float.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5651564878175307602" src="http://3.bp.blogspot.com/-_CyEblMl3UY/Tm5kUDy2h1I/AAAAAAAAARU/IIEl2fUjgUc/s400/float.png" style="cursor: pointer; display: block; height: 241px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/-pzTZYgCO0jE/Tm5kPO19InI/AAAAAAAAARM/AmatCgH411Q/s1600/display.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5651564795241767538" src="http://2.bp.blogspot.com/-pzTZYgCO0jE/Tm5kPO19InI/AAAAAAAAARM/AmatCgH411Q/s400/display.png" style="cursor: pointer; display: block; height: 397px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
**Note: this isn't terribly scientific. The sample size is small and on popular, professionally engineered sites. Likewise, many of the features are 'default' features set by the browser, and may even correspond to doing nothing. For a bigger scale, also check out Opera's &lt;a href="http://dev.opera.com/articles/view/mama/"&gt;MAMA&lt;/a&gt; analysis.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/zJglB-hboqI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/6266688877065559265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=6266688877065559265" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6266688877065559265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/6266688877065559265?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/zJglB-hboqI/what-to-implement.html" title="What to Implement" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-_VdG3Fz1vqY/Tm5j9Mg3YSI/AAAAAAAAARE/rsL7erljXJ8/s72-c/propertydistribution.png" height="72" width="72" /><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2011/09/what-to-implement.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8CRXcyeSp7ImA9WhdSFUU.&quot;"><id>tag:blogger.com,1999:blog-1440405560330732771.post-4429028021545946709</id><published>2011-07-25T01:25:00.000-07:00</published><updated>2011-07-25T01:34:24.991-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-25T01:34:24.991-07:00</app:edited><title>Advanced, Submitted... Time for new things!</title><content type="html">I passed my quals, and Todd Mytkowicz and I just submitted a fun paper on using SIMD instructions where you shouldn't. Maybe now I can start doing research again..&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Particularly fun in our submission is a 4x speedup on a canonically sequential algorithm as well as some more browser hardware acceleration tricks. Weirdest yet, in our approach, the clustering ratio of how well you can relate objects in a data parallel computation is inversely proportional to our expected vector etc. speedup! Somehow, it all makes sense. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sadly, we couldn't do our 2 coolest algorithms: one for legal reasons, the other because the vector hardware I have is missing a permute instruction. So goes.&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/lmeyerov/~4/kd0rscfNxUw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://lmeyerov.blogspot.com/feeds/4429028021545946709/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1440405560330732771&amp;postID=4429028021545946709" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/4429028021545946709?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1440405560330732771/posts/default/4429028021545946709?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/lmeyerov/~3/kd0rscfNxUw/advanced-submitted-time-for-new-things.html" title="Advanced, Submitted... Time for new things!" /><author><name>Leo Meyerovich</name><uri>https://plus.google.com/103801708355476093134</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-FpcQMZG-pO4/AAAAAAAAAAI/AAAAAAAABKA/S81Ob5j3LwE/s512-c/photo.jpg" /></author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1" /><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD" /><feedburner:origLink>http://lmeyerov.blogspot.com/2011/07/advanced-submitted-time-for-new-things.html</feedburner:origLink></entry></feed>
