Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compile-time vs. run-time cost of Hamlet templates

For the Hamlet template mechanism, I understand that the template is parsed at compile time, resulting in source code that contains calls to blaze-html combinators (and possibly other expressions because of interpolation). So the points (subtrees) where interpolation happens are known at compile-time.

At run-time, we need to compute the interpolated value (of course), and "plug it" in the tree, that is, apply the html combinators. All of them? Actually some of these applications could be evaluated at compile-time (those that have no interpolation below them). Does this happen?

like image 863
d8d0d65b3f7cf42 Avatar asked Jun 08 '15 23:06

d8d0d65b3f7cf42


3 Answers

It's been a while since I worked on the code, so don't take this as authoratative (like Daniel mentioned, -ddump-simpl is a good call here). But I don't believe we're using the blaze-html combinators, just the data type. Hamlet itself concatenates strings as much as possible at compile time to avoid that cost at runtime. I know when I last benchmarked (which granted was years ago), that optimization did pay off pretty well.

like image 60
Michael Snoyman Avatar answered Nov 11 '22 02:11

Michael Snoyman


Probably not: what you are asking for sounds a lot like partial evaluation (not to be confused with partial application), which is a bit of a compiler-performance minefield, hence often avoided. But you can check for yourself; use -ddump-simpl with your preferred optimization level to see the core that GHC generates.

like image 5
Daniel Wagner Avatar answered Nov 11 '22 03:11

Daniel Wagner


as Michael says "Hamlet itself concatenates strings as much as possible at compile time to avoid that cost at runtime."

For the example from the book,

main = putStrLn $ renderHtml [shamlet|
<p>Hello, my name is #{name person} and I am #{show $ age person}.
<p>
    Let's do some funny stuff with my name: #
    <b>#{sort $ map toLower (name person)}
<p>Oh, and in 5 years I'll be #{show ((+) 5 (age person))} years old.
|]
  where
    person = Person "Michael" 26

-ddump-simpl contains this:

               (>>
                  @ Text.Blaze.Internal.MarkupM
                  Text.Blaze.Internal.$fMonadMarkupM
                  @ ()
                  @ ()
                  (id
                     @ (Text.Blaze.Internal.MarkupM ())
                     (. @ Data.Text.Internal.Text
                        @ Text.Blaze.Internal.Markup
                        @ String
                        Text.Blaze.Internal.preEscapedText
                        Data.Text.pack
                        (GHC.CString.unpackCString#
                           ".</p>\n\
                           \<p>Let's do some funny stuff with my name: <b>"#)))

Indeed, that's not the syntax tree of the HTML (last line - the string contains a closing tag and the next opening tag).

This Hamlet feature should be advertised more!

like image 3
d8d0d65b3f7cf42 Avatar answered Nov 11 '22 02:11

d8d0d65b3f7cf42