Skip to content

Instantly share code, notes, and snippets.

@v-kolesnikov
Forked from adam12/context.yml
Created July 10, 2018 09:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save v-kolesnikov/936f44f26ffb73e448503dc43175771f to your computer and use it in GitHub Desktop.
Save v-kolesnikov/936f44f26ffb73e448503dc43175771f to your computer and use it in GitHub Desktop.
ERB vs Erubis vs Erubi
list:
- name: Adobe Systems
name2: Adobe Systems Inc.
url: http://www.adobe.com
symbol: ADBE
price: 39.26
change: 0.13
ratio: 0.33
- name: Advanced Micro Devices
name2: Advanced Micro Devices Inc.
url: http://www.amd.com
symbol: AMD
price: 16.22
change: 0.17
ratio: 1.06
- name: Amazon.com
name2: Amazon.com Inc
url: http://www.amazon.com
symbol: AMZN
price: 36.85
change: -0.23
ratio: -0.62
- name: Apple
name2: Apple Inc.
url: http://www.apple.com
symbol: AAPL
price: 85.38
change: -0.87
ratio: -1.01
- name: BEA Systems
name2: BEA Systems Inc.
url: http://www.bea.com
symbol: BEAS
price: 12.46
change: 0.09
ratio: 0.73
- name: CA
name2: CA, Inc.
url: http://www.ca.com
symbol: CA
price: 24.66
change: 0.38
ratio: 1.57
- name: Cisco Systems
name2: Cisco Systems Inc.
url: http://www.cisco.com
symbol: CSCO
price: 26.35
change: 0.13
ratio: 0.5
- name: Dell
name2: Dell Corp.
url: http://www.dell.com/
symbol: DELL
price: 23.73
change: -0.42
ratio: -1.74
- name: eBay
name2: eBay Inc.
url: http://www.ebay.com
symbol: EBAY
price: 31.65
change: -0.8
ratio: -2.47
- name: Google
name2: Google Inc.
url: http://www.google.com
symbol: GOOG
price: 495.84
change: 7.75
ratio: 1.59
- name: Hewlett-Packard
name2: Hewlett-Packard Co.
url: http://www.hp.com
symbol: HPQ
price: 41.69
change: -0.02
ratio: -0.05
- name: IBM
name2: International Business Machines Corp.
url: http://www.ibm.com
symbol: IBM
price: 97.45
change: -0.06
ratio: -0.06
- name: Intel
name2: Intel Corp.
url: http://www.intel.com
symbol: INTC
price: 20.53
change: -0.07
ratio: -0.34
- name: Juniper Networks
name2: Juniper Networks, Inc
url: http://www.juniper.net/
symbol: JNPR
price: 18.96
change: 0.5
ratio: 2.71
- name: Microsoft
name2: Microsoft Corp
url: http://www.microsoft.com
symbol: MSFT
price: 30.6
change: 0.15
ratio: 0.49
- name: Oracle
name2: Oracle Corp.
url: http://www.oracle.com
symbol: ORCL
price: 17.15
change: 0.17
ratio: 1.0
- name: SAP
name2: SAP AG
url: http://www.sap.com
symbol: SAP
price: 46.2
change: -0.16
ratio: -0.35
- name: Seagate Technology
name2: Seagate Technology
url: http://www.seagate.com/
symbol: STX
price: 27.35
change: -0.36
ratio: -1.3
- name: Sun Microsystems
name2: Sun Microsystems Inc.
url: http://www.sun.com
symbol: SUNW
price: 6.33
change: -0.01
ratio: -0.16
- name: Yahoo
name2: Yahoo! Inc.
url: http://www.yahoo.com
symbol: YHOO
price: 28.04
change: -0.17
ratio: -0.6
require 'rubygems'
require 'benchmark/ips'
require 'erb'
require 'erubis'
require 'erubi'
require 'yaml'
require 'ostruct'
require 'benchmark'
# The Erubis website (http://www.kuwata-lab.com/erubis/) claims that Erubis is
# nearly 3x faster than ERB and even a bit faster then eRuby, which is written
# in C.
#
# This benchmark indicates that Erubis is only significantly faster than ERB
# during compilation. The actual evaluation of the compiled template is
# slightly slower than ERB.
#
# % ruby erb_vs_erubis.rb
# user system total real
# 1k erb (compile+eval) 1.000000 0.010000 1.010000 ( 0.999806)
# 1k erubis (compile+eval) 0.800000 0.000000 0.800000 ( 0.800763)
# 1k erb (eval) 0.470000 0.000000 0.470000 ( 0.468233)
# 1k erubis (eval) 0.490000 0.000000 0.490000 ( 0.490879)
# 1k fast erubis (eval) 0.400000 0.000000 0.400000 ( 0.406886)
#
# Examination of the original Erubis benchmark indicates that it tests the
# full compile+eval cycle, ergo the claim is only true when you fully compile
# and then eval a template. To get the same effective performance, compile an
# ERB template once, cache it, and then evaluate it multiple times.
#
# Do this:
#
# erb = ERB.new('tem<%= :plate %>')
# 1000.times { erb.result }
#
# Not this:
#
# 1000.times { ERB.new('tem<%= :plate %>').result }
#
# = Discussion
#
# The benchmarks make a lot of sense when you examine what ERB and Erubis do
# internally -- literally they slice up a template into ruby code which
# incrementally builds up the result. For example:
#
# ERB.new('got <%= :milk %>').src
# # => "_erbout = ''; _erbout.concat \"got \"; _erbout.concat(( :milk ).to_s); _erbout"
#
# Erubis::Eruby.new('got <%= :milk %>').src
# # => "_buf = ''; _buf << 'got '; _buf << ( :milk ).to_s;\n_buf.to_s\n"
#
# In both cases the source code is evaluated as ruby. Internally both use the
# same mechanism so it isn't surprising that they run at essentially the same
# speed.
#
# The minor slow down between erb and erubis indicates that String#concat is a
# bit faster than String#<<. The fairly significant increase between erb and
# 'fast erubis' occurs because 'fast erubis' uses string interpolation when
# possible, instead of concatenation. Examine the fast_erubis.src after
# running the benchmark to see the details.
#
# = Notes
#
# The trim option is set on the Eruby templates to make the output for
# ERB/Erubis identical (which I thought was fair). Without trim, Erubis
# evaluation is slightly faster because, AFAIK, the source is somewhat
# smaller.
#
# The template and context are the same as used in the original Erubis
# benchmark.
Benchmark.ips do |x|
m = 1
template_path = File.expand_path('../template.erb', __FILE__)
template = File.read(template_path)
context_path = File.expand_path('../context.yml', __FILE__)
context = OpenStruct.new(YAML.load_file(context_path)).instance_eval { binding }
x.report("#{m}k erb (compile+eval)") do
(m*1000).times do
ERB.new(template).result(context)
end
end
x.report("#{m}k erubis (compile+eval)") do
(m*1000).times do
Erubis::Eruby.new(template, :trim => false).result(context)
end
end
x.report("#{m}k erubi (compile+eval)") do
(m*1000).times do
eval(Erubi::Engine.new(template, :trim => false).src, context)
end
end
erb = ERB.new(template)
x.report("#{m}k erb (eval)") do
(m*1000).times do
erb.result(context)
end
end
erubis = Erubis::Eruby.new(template, :trim => false)
x.report("#{m}k erubis (eval)") do
(m*1000).times do
erubis.result(context)
end
end
fast_erubis = Erubis::FastEruby.new(template, :trim => false)
x.report("#{m}k fast erubis (eval)") do
(m*1000).times do
fast_erubis.result(context)
end
end
erubi = Erubi::Engine.new(template, :trim => false)
x.report("#{m}k erubi (eval)") do
(m*1000).times do
eval(erubi.src, context)
end
end
#
# For inspection
#
File.open('erb.html', 'w') {|io| io << erb.result(context) }
File.open('erb.src', 'w') {|io| io << erb.src }
File.open('erubis.html', 'w') {|io| io << erubis.result(context) }
File.open('erubis.src', 'w') {|io| io << erubis.src }
File.open('fast_erubis.html', 'w') {|io| io << fast_erubis.result(context) }
File.open('fast_erubis.src', 'w') {|io| io << fast_erubis.src }
File.open('erubi.html', 'w') {|io| io << eval(erubi.src, context) }
File.open('erubi.src', 'w') {|io| io << erubi.src }
x.compare!
end
require 'rubygems'
require 'memory_profiler'
require 'yaml'
require 'ostruct'
MemoryProfiler.report do
require 'erb'
require 'erubis'
require 'erubi'
template_path = File.expand_path('../template.erb', __FILE__)
template = File.read(template_path)
context_path = File.expand_path('../context.yml', __FILE__)
context = OpenStruct.new(YAML.load_file(context_path)).instance_eval { binding }
erubis = Erubis::Eruby.new(template, :trim => false)
erubis.result(context)
fast_erubis = Erubis::FastEruby.new(template, :trim => false)
fast_erubis.result(context)
erubi = Erubi::Engine.new(template, :trim => false)
eval(erubi.src, context)
end.pretty_print
<tbody>
<%
n = 0
for item in list
n += 1
%>
<tr class="<%= n % 2 == 0 ? 'even' : 'odd' %>">
<td style="text-align: center"><%= n %></td>
<td>
<a href="/stocks/<%= item['symbol'] %>"><%= item['symbol'] %></a>
</td>
<td>
<a href="<%= item['url'] %>"><%= item['name'] %></a>
</td>
<td>
<strong><%= item['price'] %></strong>
</td>
<% if item['change'] < 0.0 %>
<td class="minus"><%= item['change'] %></td>
<td class="minus"><%= item['ratio'] %></td>
<% else %>
<td><%= item['change'] %></td>
<td><%= item['ratio'] %></td>
<% end %>
</tr>
<%
end
%>
</tbody>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment