Slide 1

Slide 1 text

A Quest for the Ultimate Template Engine Akira Matsuda

Slide 2

Slide 2 text

Today's Talk My personal story About Ruby template engines

Slide 3

Slide 3 text

me from: Japan name: Akira Matsuda GitHub: amatsuda I Do: Ruby, Rails !

Slide 4

Slide 4 text

Template Engines Text Files + Ruby => HTML On Rails (ActionView) app/views/*.html.*

Slide 5

Slide 5 text

My first Ruby Template Engine Was Of course, ERB

Slide 6

Slide 6 text

ERB: The Default One Included in the Matz Ruby package as a stdlib Still a part of DHH's "omakase"

Slide 7

Slide 7 text

The Syntax <% @users.each do |user| %> <%= user.name %> <% end %>

Slide 8

Slide 8 text

The syntax looked familiar to me I used to be an ASP programmer I used to be a PHP programmer I used to be a JSP programmer

Slide 9

Slide 9 text

The ERB Syntax The spec is called eRuby

Slide 10

Slide 10 text

Crated By @shugo Copied ePerl syntax

Slide 11

Slide 11 text

Problem ERB sometimes sucks Because HTML sucks

Slide 12

Slide 12 text

We are humans <% @users.each do |user| %> <%= user.name %> <% end %>

Slide 13

Slide 13 text

We make mistakes <% @users.each do |user| %> <%= user.name %> <% end %>

Slide 14

Slide 14 text

Broken HTML Sometimes works Sometimes does not work

Slide 15

Slide 15 text

I Was Always Wondering Why doesn't the Framework validate the response HTML?

Slide 16

Slide 16 text

Then One Day, I met Haml

Slide 17

Slide 17 text

Haml

Slide 18

Slide 18 text

Haml Templating Haiku Beautiful DRY Well-indented Clear markup

Slide 19

Slide 19 text

Valid HTML! Parses the markup then compiles it into an HTML Ensures that the output is always valid HTML This was a revolution!

Slide 20

Slide 20 text

Syntax %tbody - @users.each do |user| %tr %td= user.name

Slide 21

Slide 21 text

I was fascinated No more broken HTML! Since then, I have never looked back on ERB

Slide 22

Slide 22 text

Then One Day, A Rails newbie came to me and said, "why is Haml so slow?" My app responds very quickly as an API server, but rendering the same set of data into an HTML is too slow

Slide 23

Slide 23 text

His Claim app/views/recipes/ index.???.json #=> fast app/views/recipes/ index.html.haml #=> slow

Slide 24

Slide 24 text

The Rails newbie's name was

Slide 25

Slide 25 text

@mineroaoki

Slide 26

Slide 26 text

@mineroaoki A Ruby committer The author of Net::HTTP, FileUtils, Ripper, Racc, TMail, etc. The author of legendary Ruby book "Ruby Hacking Guide"

Slide 27

Slide 27 text

History of Minero Aoki 1999: Became a Ruby Committer 2002: Wrote RHG while he was a student ..2013: Had been doing something else, wearing suit 2013: Came back to the Ruby world as a Rails programmer

Slide 28

Slide 28 text

RHG Even @ko1 learned Ruby implementation through this book English version is available online: http://ruby-hacking-guide.github.io/

Slide 29

Slide 29 text

I thought, Yeah, Haml might not be as fast as ERB Because of its syntax, parsing & compiling should be slow, but who cares?

Slide 30

Slide 30 text

He is a super hacker But a newbie Maybe his template is slow just because his Haml code sucks Or maybe what he meant was "ActionView is slow"?

Slide 31

Slide 31 text

Parsing & compiling Haml might be slow Because Haml is so complex But compiled code will be cached by ActionView

Slide 32

Slide 32 text

Parsing & compiling Haml might be slow But who cares?

Slide 33

Slide 33 text

A Rails tips If you feel like your view is slow, it might be because of url_for

Slide 34

Slide 34 text

Benchmark Let's quickly make sure that Haml is as fast as ERB in production

Slide 35

Slide 35 text

generate scaffold % rails g scaffold user name age:integer email phone

Slide 36

Slide 36 text

Preparing 1,000 Records (1..1000).each do |i| User.create! name: 'User %05d' % i, age: i, email: 'user%[email protected]' % i, phone: "#{i}-#{i}" end

Slide 37

Slide 37 text

Run it in production mode Make the rst request from the browser

Slide 38

Slide 38 text

Make Requests With curl or ab or httperf or whatever

Slide 39

Slide 39 text

From the Log File I, [2015-03-09T18:34:26.780189 #57017] INFO -- : Completed 200 OK in 312ms (Views: 307.5ms | ActiveRecord: 3.9ms) I, [2015-03-09T18:34:27.103951 #57017] INFO -- : Completed 200 OK in 319ms (Views: 314.8ms | ActiveRecord: 3.9ms) I, [2015-03-09T18:34:27.366058 #57017] INFO -- : Completed 200 OK in 258ms (Views: 254.7ms | ActiveRecord: 2.9ms) I, [2015-03-09T18:34:27.658356 #57017] INFO -- : Completed 200 OK in 289ms (Views: 285.7ms | ActiveRecord: 2.5ms) I, [2015-03-09T18:34:27.953852 #57017] INFO -- : Completed 200 OK in 290ms (Views: 287.2ms | ActiveRecord: 2.4ms) I, [2015-03-09T18:34:28.216769 #57017] INFO -- : Completed 200 OK in 258ms (Views: 255.1ms | ActiveRecord: 2.6ms) I, [2015-03-09T18:34:28.560278 #57017] INFO -- : Completed 200 OK in 339ms (Views: 334.9ms | ActiveRecord: 3.6ms)

Slide 40

Slide 40 text

grep the View Rendering Time And Summarize

Slide 41

Slide 41 text

The Result (100 requests) ERB: 27135.9 msec Haml: 29116.8 msec

Slide 42

Slide 42 text

OMG

Slide 43

Slide 43 text

Haml is slow! It turned out that Haml is 7% slower in production runtime!

Slide 44

Slide 44 text

It's true that Haml is slow So what shall we do?

Slide 45

Slide 45 text

What shall we do? 1. Do Nothing

Slide 46

Slide 46 text

Do Nothing Let it be slow Who cares? We're Ruby programmers!

Slide 47

Slide 47 text

"Premature optimization is the root of all evil" There must be so many other reasons that make your Rails app slow DB network Business logic

Slide 48

Slide 48 text

While rendering is 7% slower Throughput from the client will be 1-2% difference

Slide 49

Slide 49 text

We're Ruby programmers If you really care about the app's performance, your app should've written in C What we should care is the balance

Slide 50

Slide 50 text

The Balance Between Performance And Productivity Maintainability Developers' Sanity

Slide 51

Slide 51 text

The Recipe for the ...

Slide 52

Slide 52 text

Our Recipe If your application is not fast enough, just add more servers.

Slide 53

Slide 53 text

What shall we do? 1. Do Nothing 2. Switch Back to ERB

Slide 54

Slide 54 text

2. Switch back to ERB

Slide 55

Slide 55 text

Seriously Syntax matters

Slide 56

Slide 56 text

The Balance User Experience: Developer Happiness: 㽉

Slide 57

Slide 57 text

What shall we do? 1. Do Nothing 2. Switch Back to ERB 3. Find Something Else

Slide 58

Slide 58 text

3. Find Something Else

Slide 59

Slide 59 text

What would you do to find something?

Slide 60

Slide 60 text

We do this.

Slide 61

Slide 61 text

google: haml slow

Slide 62

Slide 62 text

Google says, "I heard that Slim is faster than Haml, so it must be a good one" "I read someone's blog that shows Slim is faster than Haml, so I switched to Slim"

Slide 63

Slide 63 text

Slim? Similar to Haml Built on top of Temple

Slide 64

Slide 64 text

Syntax

Slide 65

Slide 65 text

Hello, World! | Hello, World!

Slide 66

Slide 66 text

Hello, World! h1 Hello, World!

Slide 67

Slide 67 text

To Me, Syntax matters And the syntax looks weird

Slide 68

Slide 68 text

"Faster than Haml" Seems like a good marketing Some people may choose Python over Ruby Some people may choose JRuby over CRuby because b() runs faster on JRuby

Slide 69

Slide 69 text

You can choose Slim If you're OK with the syntax

Slide 70

Slide 70 text

What shall we do? 1. Do Nothing 2. Switch Back to ERB 3. Find Something Else 4. Improve Haml

Slide 71

Slide 71 text

4. Improve Haml

Slide 72

Slide 72 text

Faster Is Better, Of Course Even if speed is not a critical problem

Slide 73

Slide 73 text

I don't know why but I had a commit bit When I PRed one line of code

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

The diff

Slide 76

Slide 76 text

I Had to Do This Because, Our super large legacy Rails app was still on Ruby 1.8 at that moment...

Slide 77

Slide 77 text

Maybe They Didn't Want to Work on 1.8.7 Anymore So they gave me the commit right

Slide 78

Slide 78 text

Then I got a mail

Slide 79

Slide 79 text

Looks like I'm responsible

Slide 80

Slide 80 text

So, I started reading Haml

Slide 81

Slide 81 text

Pushed some nitpicks

Slide 82

Slide 82 text

The real problem Compiled ruby code

Slide 83

Slide 83 text

Hello! in ERB ERB.new("<% 'Hello!' %>").src

Slide 84

Slide 84 text

Hello! in ERB #=> "#coding:UTF-8\n_erbout = ''; 'Hello!' ; _erbout.force_encoding(__EN CODING__)"

Slide 85

Slide 85 text

Hello! in Haml Haml::Engine.new("= 'Hello!'").compiler.precompile d_with_ambles([])

Slide 86

Slide 86 text

Hello! in Haml begin;extend Haml::Helpers;_hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, {:autoclose=>["area", "base", "basefont", "br", "col", "command", "embed", "frame", "hr", "img", "input", "isindex", "keygen", "link", "menuitem", "meta", "param", "source", "track", "wbr"], :preserve=>["textarea", "pre", "code"], :attr_wrapper=>"'", :ugly=>false, :format=>:html5, :encoding=>"UTF-8", :escape_html=>false, :escape_attrs=>true, :hyphenate_data_attrs=>true, :cdata=>false});_erbout = _hamlout.buffer;@output_buffer = output_buffer ||= ActionView::OutputBuffer.new rescue nil;;_hamlout.push_text("#{_hamlout.format_script_false_false_ false_false_false_true_false(( 'Hello!' ));}\n", 0, false);_erbout;ensure;@haml_buffer = @haml_buffer.upper if @haml_buffer;end;

Slide 87

Slide 87 text

Lovely Haiku!

Slide 88

Slide 88 text

Let's see how we can improve this the Ruby code

Slide 89

Slide 89 text

What shall we do? 1. Do Nothing 2. Switch Back to ERB 3. Find Something Else 4. Improve Haml 5. Fork Haml

Slide 90

Slide 90 text

5. Fork Haml

Slide 91

Slide 91 text

We need to care about compatibility

Slide 92

Slide 92 text

I concluded that I can not make Haml as fast as ERB without breaking compatibility

Slide 93

Slide 93 text

So, I made a fork

Slide 94

Slide 94 text

HamlX As I announced at RubyConf 2014

Slide 95

Slide 95 text

Current Status of HamlX Still not done

Slide 96

Slide 96 text

Benchmark

Slide 97

Slide 97 text

The Result (100 requests) ERB: 27135.9 msec Haml: 29116.8 msec HamlX: 27407.7 msec

Slide 98

Slide 98 text

What shall we do? 1. Do Nothing 2. Switch Back to ERB 3. Find Something Else 4. Improve Haml 5. Fork Haml 6. Create a New Haml Implementation

Slide 99

Slide 99 text

6. Create a new Haml implementation

Slide 100

Slide 100 text

My co-worker at Cookpad

Slide 101

Slide 101 text

@eagletmt

Slide 102

Slide 102 text

@eagletmt eagle? tomato?

Slide 103

Slide 103 text

After my presentation at RubyConf

Slide 104

Slide 104 text

He started creating his own version

Slide 105

Slide 105 text

My Approach Haml minus slow parts

Slide 106

Slide 106 text

His Approach From the bottom up!

Slide 107

Slide 107 text

His Concept Slim is faster than Haml because Slim is built on Temple Slim and Haml's syntax is similar Why don't we make a Haml compiler on top of Temple?

Slide 108

Slide 108 text

The Creator of Temple Says, Nathan Weizenbaum (the maintainer of Haml) told me targeting Haml could be difficult, but I’m quite optimistic. It’s better to try, fail and learn, than not try at all. http://timelessrepo.com/temple#another_abstraction_haml_and_html

Slide 109

Slide 109 text

I actually tried! But gave up.

Slide 110

Slide 110 text

But @egletmt did it. Because he is a better hacker than me Or maybe because he is young and brave

Slide 111

Slide 111 text

eagletmt/fast_haml

Slide 112

Slide 112 text

Already gemified % gem i fast_haml

Slide 113

Slide 113 text

Benchmark

Slide 114

Slide 114 text

The Result (100 requests) ERB: 27135.9 msec Haml: 29116.8 msec HamlX: 27407.7 msec FastHaml: 23769.8 msec

Slide 115

Slide 115 text

Possibly Faster Than Slim

Slide 116

Slide 116 text

Still an Experimental Project Nobody uses this in production, I guess

Slide 117

Slide 117 text

I know that the name is terrible "Naming matters."

Slide 118

Slide 118 text

Worth Trying This If you're really sure that your system's bottleneck lies in the template engine If you want to experience the world's fastest Template engine

Slide 119

Slide 119 text

A Quest for the Ultimate Template Engine

Slide 120

Slide 120 text

The Ultimate Template Engine Developer Experience Sane Syntax End User Experience Runtime Performance

Slide 121

Slide 121 text

We're getting close! Stay tuned!

Slide 122

Slide 122 text

Or, YOU can do it, of course.

Slide 123

Slide 123 text

YOU can do it! YOU can patch YOU can create your own engine Rather than just sitting and waiting and complaining