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 node itself
  node.code

  # Which template and line number of this node.
  # The top-level template name is `nil` by default, but can be set in the Liquid::Context before rendering.
  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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProfiler

Returns a new instance of Profiler.



75
76
77
78
79
# File 'lib/liquid/profiler.rb', line 75

def initialize
  @root_children = []
  @current_children = nil
  @total_time = 0.0
end

Instance Attribute Details

#total_timeObject (readonly) Also known as: total_render_time

Returns the value of attribute total_time.



72
73
74
# File 'lib/liquid/profiler.rb', line 72

def total_time
  @total_time
end

Instance Method Details

#[](idx) ⇒ Object



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

def [](idx)
  children[idx]
end

#childrenObject



98
99
100
101
102
103
104
105
# File 'lib/liquid/profiler.rb', line 98

def children
  children = @root_children
  if children.length == 1
    children.first.children
  else
    children
  end
end

#each(&block) ⇒ Object



107
108
109
# File 'lib/liquid/profiler.rb', line 107

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

#lengthObject



115
116
117
# File 'lib/liquid/profiler.rb', line 115

def length
  children.length
end

#profile(template_name, &block) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/liquid/profiler.rb', line 81

def profile(template_name, &block)
  # nested renders are done from a tag that already has a timing node
  return yield if @current_children

  root_children = @root_children
  render_idx = root_children.length
  begin
    @current_children = root_children
    profile_node(template_name, &block)
  ensure
    @current_children = nil
    if (timing = root_children[render_idx])
      @total_time += timing.total_time
    end
  end
end

#profile_node(template_name, code: nil, line_number: nil) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/liquid/profiler.rb', line 119

def profile_node(template_name, code: nil, line_number: nil)
  timing = Timing.new(code: code, template_name: template_name, line_number: line_number)
  parent_children = @current_children
  start_time = monotonic_time
  begin
    @current_children = timing.children
    yield
  ensure
    @current_children = parent_children
    timing.total_time = monotonic_time - start_time
    parent_children << timing
  end
end