Browse files

Update for 0.10 release

  • Loading branch information...
1 parent 8399e00 commit c58a7441b801133db725bb791bf15473912f2e4a @mightybyte mightybyte committed Dec 9, 2012
@@ -0,0 +1,65 @@
+| title: Heist with a >3000x performance improvement
+| author: Doug Beardsley <>
+| published: 2012-12-09T20:55:00+0100
+| updated: 2012-12-09T20:55:00+0100
+| summary: Release notes for Heist 0.10
+The Snap team is excited to announce the release of Heist 0.10. For this
+massively backwards-incompatible release we went back to the drawing board and
+re-wrote Heist from the ground up with performance in mind. But was Heist
+actually slow? Nobody has actually complained about it, but yes, Heist was
+slow. was until now.
+Note that this chart is log scale. The difference is so drastic that if the
+chart was linear scale, the bars for Heist 0.10 wouldn't even show up! The
+three pages benchmarked are taken directly from, so they are
+real-world examples. Heist 0.10 gives an improvement of more than 3000x for
+snaplets.tpl, 2000x for about.tpl, and 700x for faq.tpl. The improvement for
+faq.tpl is smaller because most its content is statically generated by pandoc,
+so Heist only has to traverse a small DOM compared to the other two templates.
+To understand what happened here, we need to go back to the beginning. When
+we originally wrote Heist, speed was not our goal. Instead we wanted to see
+how far a simple concept like binding Haskell code to HTML nodes could take us
+in solving the problem with HTML boilerplate. Now, two and a half years
+later, we've discovered that it's an incredibly powerful and enjoyable model
+for web programming.
+Heist achieves this by traversing the DOM, executing splices to generate
+replacement nodes, and recursively traversing those nodes until all splices
+have been executed. A significant part of Heist's power lies in the fact that
+this transformation happens at runtime every time a template is served, so the
+splice computations are running in your web server monad and have access to
+all the data from the HTTP request. Once this transformation is complete, the
+resulting DOM is rendered to a ByteString and served back in the HTTP
+response. This is really slow when compared with concatenative template
+systems like StringTemplate that just blast out interleaved static and dynamic
+chunks of data. Therefore it should be no surprise that splicing is slow, as
+it allows for much more expressiveness and power.
+However, we realized that a lot of the transformations could be done at load
+time and be preprocessed to an intermediate representation. This consists of
+static ByteStrings interleaved with deferred dynamic computations that still
+give you the power of being able to access the web server's runtime monad.
+This "compiled splice" as we call it works quite a bit differently from the
+old model of splices. It is also strictly less powerful, so we kept the
+ability to use the old "interpreted splice" model if you really need the power
+and can afford the performance penalty.
+While we were making backwards incompatible changes, we decided to clean up
+everything. This included reorganizing the modules and any other changes we
+felt would improve the overall quality and readability of the code base. It
+will be a bit of work to migrate existing code to Heist 0.10, but the old
+interpreted splices are still available and allow you do a gradual transition.
+We also added a new feature called attribute splices that allows you to
+abstract attributes in ways that weren't possible before.
+For more detailed information about the new features, check out the tutorials
+in the [heist section](/docs#heist) of our docs page. After you have read
+those and are ready to upgrade your site, you might want to follow our [migration
+to help you with the transition to 0.10. The migration guide is a github
+wiki, so feel free to help us make it clearer and more complete.
@@ -20,10 +20,10 @@ Executable snap-website
- data-lens-template >= 2.1 && < 2.2,
heist >= 0.10 && < 0.11,
+ lens >= 3.7 && < 3.8,
MonadCatchIO-transformers >= 0.2 && < 0.4,
mtl >= 2 && <3,
@@ -3,64 +3,67 @@
<div id="about" class="section left">
<div class="inner">
- <h2>Tutorials</h2>
+ <h2 id="snap">Snap</h2>
<div id="docdls">
<dt><a href="docs/quickstart">Quick Start</a></dt>
- <a class="book" href="docs/quickstart">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="docs/quickstart"><img src="/media/css/book.png" /></a>
A guide to getting Snap installed.</dd>
<dt><a href="docs/tutorials/snap-api">Snap API Introduction</a></dt>
- <a class="book" href="docs/tutorials/snap-api">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="docs/tutorials/snap-api"><img src="/media/css/book.png" /></a>
A quick tutorial on the Snap API. Covers installation, the
&ldquo;snap&rdquo; command-line tool, and a walkthough of the
Snap starter application.</dd>
- <dt><a href="docs/tutorials/heist">Heist Template Tutorial</a></dt>
- <dd>
- <a class="book" href="docs/tutorials/heist">
- <img src="/media/css/book.png" />
- </a>
- A tutorial for the Heist HTML templating library.</dd>
<dt><a href="docs/tutorials/snaplets-tutorial">Snaplets Tutorial</a></dt>
- <a class="book" href="docs/tutorials/snaplets-tutorial">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="docs/tutorials/snaplets-tutorial"><img src="/media/css/book.png" /></a>
Guide to using snaplets to build reusable web components.</dd>
<dt><a href="docs/tutorials/snaplets-design">Snaplets Design</a></dt>
- <a class="book" href="docs/tutorials/snaplets-design">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="docs/tutorials/snaplets-design"><img src="/media/css/book.png" /></a>
Description of the snaplets internal design and motivation.</dd>
+ <h2 id="heist">Heist</h2>
+ <div id="docdls">
+ <dl>
+ <dt><a href="docs/tutorials/heist">Heist Template Tutorial</a></dt>
+ <dd>
+ <a class="book" href="docs/tutorials/heist"><img src="/media/css/book.png" /></a>
+ A tutorial for the Heist HTML templating library. This tutorial
+ applies to Heist 0.8 and earlier.</dd>
+ <dt><a href="docs/tutorials/compiled-splices">Compiled Splices Tutorial</a></dt>
+ <dd>
+ <a class="book" href="docs/tutorials/compiled-splices"><img src="/media/css/book.png" /></a>
+ Discusses compiled splices, which were introduced in Heist 0.10.</dd>
+ <dt><a href="docs/tutorials/attribute-splices">Attribute Splices Tutorial</a></dt>
+ <dd>
+ <a class="book" href="docs/tutorials/attribute-splices"><img src="/media/css/book.png" /></a>
+ How to use attribute splices (also introduced in Heist 0.10).</dd>
+ </dl>
+ </div>
<div class="inner">
- <h2>Resources</h2>
+ <h2 id="resources">Resources</h2>
<div id="docdls">
<dt><a href="docs/style-guide">Haskell Style Guide</a></dt>
- <a class="book" href="docs/style-guide">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="docs/style-guide"><img src="/media/css/book.png" /></a>
A guide to the Haskell source style we're using for the project.</dd>
<dt><a href="/benchmarks">Benchmarks</a></dt>
- <a class="book" href="/benchmarks">
- <img src="/media/css/book.png" />
- </a>
+ <a class="book" href="/benchmarks"><img src="/media/css/book.png" /></a>
Some benchmark results comparing Snap to several other
web frameworks.</dd>
@@ -70,7 +73,7 @@
<div id="about" class="section left">
<div class="inner">
- <h2>API Documentation</h2>
+ <h2 id="api">API Documentation</h2>
<div id="docdls">
@@ -0,0 +1,58 @@
+Attribute Splices
+Attribute splices are new in Heist 0.10. They solve the problem of wanting to
+be able to dynamically make empty attributes appear or disappear with a splice
+without binding a splice to the whole tag. This issue comes up most
+frequently when dealing with empty attributes such as HTML's "disabled" or
+> module Heist.Tutorial.AttributeSplices where
+> import Heist.Tutorial.Imports
+Consider a page with several radio buttons. You want the correct one to be
+selected based on the value of a parameter in the HTTP request. The HTML
+would look something like this:
+ <input type="radio" name="color" value="red" checked>Red</input>
+ <input type="radio" name="color" value="green">Green</input>
+ <input type="radio" name="color" value="blue">Blue</input>
+We want to automatically generate the "checked" attribute appropriately. This
+could be done with a splice bound to the input tag, but there might be a
+number of other input tags on the page, so your splice would at best be
+executed on more tags than necessary and at worst not have the granularity
+necessary to work properly. The ${} syntax for splices inside of attribute
+values also won't work because it can only affect an attribute's value. It
+can't make the attribute disappear entirely. This problem can be solved
+nicely with attribute splices that have the following type:
+< type AttrSplice m = Text -> m [(Text, Text)]
+An attribute splice is a computation in the runtime monad that takes the value
+of the attribute it is bound to as its argument and returns a list of
+attributes to substitute back into the tag. Here's how we might implement a
+splice to solve the above problem.
+> autocheckedSplice :: Text -> StateT Text IO [(Text, Text)]
+> autocheckedSplice v = do
+> val <- get -- app-specific retrieval of the appropriate value here
+> let checked = if v == val
+> then [("checked","")]
+> else []
+> return $ ("value", v) : checked
+In this toy example we are using `StateT Text IO` as our "runtime" monad where
+the Text state holds the value of the radio button that should be checked. We
+assume that the current value we're checking against is passed as the bound
+attribute's value, so we compare that against the value to be checked. Then
+we return a list with the appropriate value and the checked attribute if
+necessary. We bind this splice to the "autocheck" attribute by adding it to
+the hcAttributeSplices list in HeistConfig.
+To make everything work we use the following markup for our radio buttons:
+ <input type="radio" name="color" autocheck="red">Red</input>
+ <input type="radio" name="color" autocheck="green">Green</input>
+ <input type="radio" name="color" autocheck="blue">Blue</input>
Oops, something went wrong.

0 comments on commit c58a744

Please sign in to comment.