Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3150301

Browse files
committed
Tons of various performance tweaks
1 parent cb72efc commit 3150301

File tree

8 files changed

+539
-313
lines changed

8 files changed

+539
-313
lines changed

bin/profile

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,21 @@ require "bundler/inline"
66
gemfile do
77
source "https://rubygems.org"
88
gem "stackprof"
9+
gem "prettier_print"
910
end
1011

1112
$:.unshift(File.expand_path("../lib", __dir__))
1213
require "syntax_tree"
1314

14-
GC.disable
15-
1615
StackProf.run(mode: :cpu, out: "tmp/profile.dump", raw: true) do
17-
filepath = File.expand_path("../lib/syntax_tree/node.rb", __dir__)
18-
SyntaxTree.format(File.read(filepath))
16+
Dir[File.join(RbConfig::CONFIG["libdir"], "**/*.rb")].each do |filepath|
17+
SyntaxTree.format(SyntaxTree.read(filepath))
18+
end
1919
end
2020

21-
GC.enable
22-
2321
File.open("tmp/flamegraph.html", "w") do |file|
2422
report = Marshal.load(IO.binread("tmp/profile.dump"))
23+
StackProf::Report.new(report).print_text
2524
StackProf::Report.new(report).print_d3_flamegraph(file)
2625
end
2726

lib/syntax_tree.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# frozen_string_literal: true
22

3-
require "delegate"
43
require "etc"
54
require "json"
65
require "pp"
@@ -10,7 +9,6 @@
109

1110
require_relative "syntax_tree/formatter"
1211
require_relative "syntax_tree/node"
13-
require_relative "syntax_tree/parser"
1412
require_relative "syntax_tree/version"
1513

1614
require_relative "syntax_tree/basic_visitor"
@@ -20,6 +18,8 @@
2018
require_relative "syntax_tree/visitor/match_visitor"
2119
require_relative "syntax_tree/visitor/pretty_print_visitor"
2220

21+
require_relative "syntax_tree/parser"
22+
2323
# Syntax Tree is a suite of tools built on top of the internal CRuby parser. It
2424
# provides the ability to generate a syntax tree from source, as well as the
2525
# tools necessary to inspect and manipulate that syntax tree. It can be used to

lib/syntax_tree/formatter.rb

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ module SyntaxTree
44
# A slightly enhanced PP that knows how to format recursively including
55
# comments.
66
class Formatter < PrettierPrint
7+
# It's very common to use seplist with ->(q) { q.breakable_return }. We wrap
8+
# that pattern into an object to cut down on having to create a bunch of
9+
# lambdas all over the place.
10+
class BreakableReturnSeparator
11+
def call(q)
12+
q.breakable_return
13+
end
14+
end
15+
16+
# Similar to the previous, it's common to ->(q) { q.breakable_space }. We
17+
# also wrap that pattern into an object to cut down on lambdas.
18+
class BreakableSpaceSeparator
19+
def call(q)
20+
q.breakable_space
21+
end
22+
end
23+
24+
BREAKABLE_RETURN_SEPARATOR = BreakableReturnSeparator.new
25+
BREAKABLE_SPACE_SEPARATOR = BreakableSpaceSeparator.new
26+
727
# We want to minimize as much as possible the number of options that are
828
# available in syntax tree. For the most part, if users want non-default
929
# formatting, they should override the format methods on the specific nodes
@@ -75,8 +95,7 @@ def format(node, stackable: true)
7595
doc =
7696
if leading.last&.ignore?
7797
range = source[node.location.start_char...node.location.end_char]
78-
separator = -> { breakable(indent: false, force: true) }
79-
seplist(range.split(/\r?\n/, -1), separator) { |line| text(line) }
98+
seplist(range.split(/\r?\n/, -1), Formatter::BREAKABLE_RETURN_SEPARATOR) { |line| text(line) }
8099
else
81100
node.format(self)
82101
end
@@ -108,5 +127,42 @@ def parent
108127
def parents
109128
stack[0...-1].reverse_each
110129
end
130+
131+
# This is a simplified version of prettyprint's group. It doesn't provide
132+
# any of the more advanced options because we don't need them and they take
133+
# up expensive computation time.
134+
def group
135+
contents = []
136+
doc = Group.new(0, contents: contents)
137+
138+
groups << doc
139+
target << doc
140+
141+
with_target(contents) { yield }
142+
groups.pop
143+
doc
144+
end
145+
146+
# A similar version to the super, except that it calls back into the
147+
# separator proc with the instance of `self`.
148+
def seplist(list, sep = nil, iter_method = :each) # :yield: element
149+
first = true
150+
list.__send__(iter_method) do |*v|
151+
if first
152+
first = false
153+
elsif sep
154+
sep.call(self)
155+
else
156+
comma_breakable
157+
end
158+
yield(*v)
159+
end
160+
end
161+
162+
# This is a much simplified version of prettyprint's text. It avoids
163+
# calculating width by pushing the string directly onto the target.
164+
def text(string)
165+
target << string
166+
end
111167
end
112168
end

0 commit comments

Comments
 (0)