Class: Liquid::Profiler

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/liquid/profiler.rb

Overview

Profiler enables support for profiling template rendering to help track down performance issues.

To enable profiling, first require ‘liquid/profiler’. Then, to profile a parse/render cycle, pass the profile: true option to Liquid::Template.parse. After Liquid::Template#render is called, the template object makes available an instance of this class via the Liquid::Template#profiler method.

template = Liquid::Template.parse(template_content, profile: true)
output  = template.render
profile = template.profiler

This object contains all profiling information, containing information on what tags were rendered, where in the templates these tags live, and how long each tag took to render.

This is a tree structure that is Enumerable all the way down, and keeps track of tags and rendering times inside of {% include %} tags.

profile.each do |node|
  # Access to the token itself
  node.code

  # Which template and line number of this node.
  # If top level, this will be "<root>".
  node.partial
  node.line_number

  # Render time in seconds of this node
  node.render_time

  # If the template used {% include %}, this node will also have children.
  node.children.each do |child2|
    # ...
  end
end

Profiler also exposes the total time of the template’s render in Liquid::Profiler#total_render_time.

All render times are in seconds. There is a small performance hit when profiling is enabled.

Defined Under Namespace

Classes: Timing

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProfiler

Returns a new instance of Profiler.



102
103
104
105
106
107
108
109
110
# File 'lib/liquid/profiler.rb', line 102

def initialize
  @partial_stack = ["<root>"]

  @root_timing = Timing.new("", current_partial)
  @timing_stack = [@root_timing]

  @render_start_at = Time.now
  @render_end_at = @render_start_at
end

Class Method Details

.current_profileObject



98
99
100
# File 'lib/liquid/profiler.rb', line 98

def self.current_profile
  Thread.current[:liquid_profiler]
end

.profile_children(template_name) ⇒ Object



87
88
89
90
91
92
93
94
95
96
# File 'lib/liquid/profiler.rb', line 87

def self.profile_children(template_name)
  if Profiler.current_profile
    Profiler.current_profile.push_partial(template_name)
    output = yield
    Profiler.current_profile.pop_partial
    output
  else
    yield
  end
end

.profile_token_render(token) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/liquid/profiler.rb', line 76

def self.profile_token_render(token)
  if Profiler.current_profile && token.respond_to?(:render)
    Profiler.current_profile.start_token(token)
    output = yield
    Profiler.current_profile.end_token(token)
    output
  else
    yield
  end
end

Instance Method Details

#[](idx) ⇒ Object



130
131
132
# File 'lib/liquid/profiler.rb', line 130

def [](idx)
  @root_timing.children[idx]
end

#current_partialObject



149
150
151
# File 'lib/liquid/profiler.rb', line 149

def current_partial
  @partial_stack.last
end

#each(&block) ⇒ Object



126
127
128
# File 'lib/liquid/profiler.rb', line 126

def each(&block)
  @root_timing.children.each(&block)
end

#end_token(token) ⇒ Object



142
143
144
145
146
147
# File 'lib/liquid/profiler.rb', line 142

def end_token(token)
  timing = @timing_stack.pop
  timing.finish

  @timing_stack.last.children << timing
end

#lengthObject



134
135
136
# File 'lib/liquid/profiler.rb', line 134

def length
  @root_timing.children.length
end

#pop_partialObject



157
158
159
# File 'lib/liquid/profiler.rb', line 157

def pop_partial
  @partial_stack.pop
end

#push_partial(partial_name) ⇒ Object



153
154
155
# File 'lib/liquid/profiler.rb', line 153

def push_partial(partial_name)
  @partial_stack.push(partial_name)
end

#startObject



112
113
114
115
# File 'lib/liquid/profiler.rb', line 112

def start
  Thread.current[:liquid_profiler] = self
  @render_start_at = Time.now
end

#start_token(token) ⇒ Object



138
139
140
# File 'lib/liquid/profiler.rb', line 138

def start_token(token)
  @timing_stack.push(Timing.start(token, current_partial))
end

#stopObject



117
118
119
120
# File 'lib/liquid/profiler.rb', line 117

def stop
  Thread.current[:liquid_profiler] = nil
  @render_end_at = Time.now
end

#total_render_timeObject



122
123
124
# File 'lib/liquid/profiler.rb', line 122

def total_render_time
  @render_end_at - @render_start_at
end