哈姆雷特模板的编译时与运行时成本

时间:2015-06-08 23:44:47

标签: haskell yesod hamlet

对于Hamlet模板机制,我理解模板在编译时被解析,导致源代码包含对blaze-html组合器的调用(以及可能因插值而导致的其他表达式)。因此,插值发生的点(子树)在编译时是已知的。

在运行时,我们需要计算插值(当然), 并且"插上它"在树中,即应用html组合器。 他们都是?实际上,这些应用程序中的一些可以在编译时进行评估(那些在它们下面没有插值的应用程序)。这会发生吗?

3 个答案:

答案 0 :(得分:7)

自从我处理代码以来已经有一段时间了,所以不要将其视为自动化(如Daniel所说,-ddump-simpl这是一个很好的调用)。但我不相信我们正在使用blaze-html组合器,只是数据类型。 Hamlet本身在编译时尽可能地连接字符串,以避免运行时的成本。我知道,当我上次进行基准测试(多年前授予的基准测试)时,优化确实得到了很好的回报。

答案 1 :(得分:5)

可能不是:你要求的声音很像部分评估(不要与部分应用混淆),这是一个编译器性能雷区,因此经常避免。但你可以自己检查一下;使用-ddump-simpl和您的首选优化级别来查看GHC生成的核心。

答案 2 :(得分:3)

正如迈克尔所说,"哈姆雷特本身在编译时尽可能地连接字符串,以避免在运行时花费这些成本。"

对于本书中的例子,

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包含以下内容:

               (>>
                  @ 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>"#)))

确实,这不是HTML的语法树(最后一行 - 字符串包含结束标记和下一个开始标记)。

这个哈姆雷特的功能应该更多地宣传!