sass-prof 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -8
- data/lib/sass-prof.rb +32 -201
- data/lib/sass-prof/config.rb +22 -0
- data/lib/sass-prof/formatter.rb +68 -0
- data/lib/sass-prof/profiler.rb +93 -0
- data/lib/sass-prof/reporter.rb +30 -0
- data/lib/sass-prof/version.rb +2 -4
- data/sass-prof.gemspec +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bdc582c7241e357559c9cb8fe3ca8a9d8ca5eb2
|
4
|
+
data.tar.gz: 5a65fa2fba5c17ddb3f71fc08a3af4bba6ae7c97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f80bd2249c8002050c28609f79de4860e0a679ed321a857d28c78e5d1ef3b5fe556311b69e8febd6363fe3acff61d67549d0fa0569c2263fe50e0d9c0a0c4d39
|
7
|
+
data.tar.gz: 3d9eb5c378eceae90768bd047fd111402b99ad91f0877d39a4753f0f8a1f62c9ec2337770ff8e99f1446e8adda73912a3c57362a40ed9fcf4a59e5d80f6c51b6
|
data/README.md
CHANGED
@@ -26,8 +26,8 @@ You may specify a few options within your `config.rb`, such as directing output
|
|
26
26
|
```ruby
|
27
27
|
require "sass-prof"
|
28
28
|
|
29
|
-
#
|
30
|
-
prof =
|
29
|
+
# Configuration object
|
30
|
+
prof = SassProf::Config
|
31
31
|
|
32
32
|
# Directs all output to a log file
|
33
33
|
# Default is `false`
|
@@ -52,7 +52,7 @@ prof.max_execution_time = 15
|
|
52
52
|
# Default is `true`
|
53
53
|
prof.color = true
|
54
54
|
|
55
|
-
# Execution time
|
55
|
+
# Execution time floating point precision
|
56
56
|
# Default is `15`
|
57
57
|
prof.precision = 5
|
58
58
|
```
|
@@ -66,8 +66,3 @@ _Please note: your compile times **will be slower** due to the overhead of **Sas
|
|
66
66
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
67
67
|
4. Push to the branch (`git push origin my-new-feature`)
|
68
68
|
5. Create a new Pull Request
|
69
|
-
|
70
|
-
## Todo
|
71
|
-
|
72
|
-
- [ ] Add proper rspec tests
|
73
|
-
- [ ] Add support for `@mixin`'s
|
data/lib/sass-prof.rb
CHANGED
@@ -2,219 +2,50 @@
|
|
2
2
|
|
3
3
|
require "terminal-table"
|
4
4
|
|
5
|
+
require "sass-prof/config"
|
6
|
+
require "sass-prof/reporter"
|
7
|
+
require "sass-prof/formatter"
|
8
|
+
require "sass-prof/profiler"
|
9
|
+
|
10
|
+
# Monkey patch Sass to utilize Profiler
|
5
11
|
module Sass
|
6
|
-
|
7
|
-
|
8
|
-
module Config
|
9
|
-
attr_accessor :t_max
|
10
|
-
attr_accessor :max_width
|
11
|
-
attr_accessor :output_file
|
12
|
-
attr_accessor :quiet
|
13
|
-
attr_accessor :color
|
14
|
-
attr_accessor :precision
|
15
|
-
|
16
|
-
alias_method :max_execution_time=, :t_max=
|
17
|
-
alias_method :max_execution_time, :t_max
|
18
|
-
|
19
|
-
@t_max = 100
|
20
|
-
@max_width = false
|
21
|
-
@output_file = false
|
22
|
-
@quiet = false
|
23
|
-
@color = true
|
24
|
-
@precision = 15
|
25
|
-
|
26
|
-
extend self
|
27
|
-
end
|
12
|
+
class Tree::Visitors::Perform
|
13
|
+
alias_method :__visit_function, :visit_function
|
28
14
|
|
29
|
-
|
30
|
-
|
15
|
+
def visit_function(node)
|
16
|
+
prof = ::SassProf::Profiler.new(node.dup, :function, node.args.dup,
|
17
|
+
@environment)
|
18
|
+
prof.start
|
31
19
|
|
32
|
-
|
20
|
+
value = __visit_function node
|
33
21
|
|
34
|
-
|
35
|
-
row = Prof::Formatter.truncate_row row if Prof::Config.max_width
|
36
|
-
@rows << row
|
37
|
-
end
|
22
|
+
prof.stop
|
38
23
|
|
39
|
-
|
40
|
-
|
41
|
-
end
|
24
|
+
value
|
25
|
+
end
|
42
26
|
|
43
|
-
|
44
|
-
log_report if Prof::Config.output_file
|
45
|
-
puts Prof::Formatter.to_table @rows
|
46
|
-
end
|
27
|
+
alias_method :__visit_mixindef, :visit_mixindef
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
29
|
+
def visit_mixindef(node)
|
30
|
+
prof = ::SassProf::Profiler.new(node.dup, :mixin, node.args.dup,
|
31
|
+
@environment)
|
32
|
+
prof.start
|
54
33
|
|
55
|
-
|
56
|
-
end
|
34
|
+
value = __visit_mixindef node
|
57
35
|
|
58
|
-
|
59
|
-
|
60
|
-
COLORS = Hash.new("37").merge({
|
61
|
-
:black => "30",
|
62
|
-
:red => "31",
|
63
|
-
:green => "32",
|
64
|
-
:yellow => "33",
|
65
|
-
:blue => "34",
|
66
|
-
:purple => "35",
|
67
|
-
:cyan => "36",
|
68
|
-
:white => "37",
|
69
|
-
})
|
70
|
-
|
71
|
-
def colorize(string, color)
|
72
|
-
return string.to_s unless Prof::Config.color
|
73
|
-
|
74
|
-
"\e[0;#{COLORS.fetch(color)}m#{string}\e[0m"
|
75
|
-
end
|
76
|
-
|
77
|
-
def to_table(rows)
|
78
|
-
pr = Prof::Config.precision / 3 - 5 # 5 is to account for whitespace
|
79
|
-
t_ms = rows.map { |c|
|
80
|
-
c[1].gsub(/\e\[(\d+)(;\d+)*m/, "").to_f }.reduce :+
|
81
|
-
|
82
|
-
t_ss, t_ms = t_ms.divmod 1000
|
83
|
-
t_mm, t_ss = t_ss.divmod 60
|
84
|
-
|
85
|
-
# Add total execution time footer
|
86
|
-
rows << :separator
|
87
|
-
rows << [
|
88
|
-
"Total",
|
89
|
-
"%.#{pr}fm %.#{pr}fs %.#{pr}fms" % [t_mm, t_ss, t_ms],
|
90
|
-
"",
|
91
|
-
""
|
92
|
-
]
|
93
|
-
|
94
|
-
table = Terminal::Table.new({
|
95
|
-
:headings => ["File", "Execution Time", "Action", "Signature"],
|
96
|
-
:rows => rows
|
97
|
-
})
|
98
|
-
|
99
|
-
table
|
100
|
-
end
|
101
|
-
|
102
|
-
def truncate_row(row)
|
103
|
-
max_width = Prof::Config.max_width
|
104
|
-
tr_row = []
|
105
|
-
|
106
|
-
row.map do |col|
|
107
|
-
clean_width = col.gsub(/\e\[(\d+)(;\d+)*m/, "").length
|
108
|
-
diff = col.length - clean_width
|
109
|
-
|
110
|
-
if clean_width > max_width
|
111
|
-
tr_row << (col[0..max_width + diff] << "\e[0m...")
|
112
|
-
else
|
113
|
-
tr_row << col
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
tr_row
|
118
|
-
end
|
119
|
-
|
120
|
-
extend self
|
121
|
-
end
|
36
|
+
prof.stop
|
122
37
|
|
123
|
-
|
124
|
-
attr_accessor :function, :action, :args, :env
|
125
|
-
|
126
|
-
def initialize(function, action, args = nil, env = nil)
|
127
|
-
@function = function
|
128
|
-
@action = action
|
129
|
-
@args = args
|
130
|
-
@env = env
|
131
|
-
@t_total = 0
|
132
|
-
@t_then = 0
|
133
|
-
@t_now = 0
|
134
|
-
end
|
135
|
-
|
136
|
-
def start
|
137
|
-
@t_then = Time.now
|
138
|
-
end
|
139
|
-
|
140
|
-
def stop
|
141
|
-
@t_now = Time.now
|
142
|
-
t_delta = (@t_now.to_f - @t_then.to_f) * 1000.0
|
143
|
-
@t_then, @t_total = @t_now, t_delta
|
144
|
-
|
145
|
-
create_fn_report
|
146
|
-
end
|
147
|
-
|
148
|
-
private
|
149
|
-
|
150
|
-
def create_fn_report
|
151
|
-
fn_report = [fn_source, fn_execution_time, fn_action,
|
152
|
-
fn_signature]
|
153
|
-
|
154
|
-
Prof::Report.add_row fn_report unless Prof::Config.quiet
|
155
|
-
|
156
|
-
if @t_total > Prof::Config.t_max && action == :invoke
|
157
|
-
raise RuntimeError.new Prof::Formatter.colorize(
|
158
|
-
"Max execution time of #{Prof::Config.t_max}ms reached for function"\
|
159
|
-
" `#{fn_name}()` (took #{@t_total.round(3)}ms)", :red)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def fn_execution_time
|
164
|
-
color = @t_total > Prof::Config.t_max ? :red : :green
|
165
|
-
t_exec = "%.#{Prof::Config.precision}f" % @t_total
|
166
|
-
Prof::Formatter.colorize t_exec, color
|
167
|
-
end
|
168
|
-
|
169
|
-
def fn_name
|
170
|
-
case
|
171
|
-
when function.respond_to?(:name)
|
172
|
-
function.name
|
173
|
-
else
|
174
|
-
"Unknown function"
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def fn_args
|
179
|
-
return nil if args.nil?
|
180
|
-
|
181
|
-
if args.is_a? Array
|
182
|
-
args.map { |a| a.inspect }.join(", ")
|
183
|
-
else
|
184
|
-
args.to_s[1...args.length-2]
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def fn_source
|
189
|
-
return Prof::Formatter.colorize("Unknown file", :red) unless env
|
190
|
-
|
191
|
-
orig_filename = env.options.fetch :original_filename, "Unknown file"
|
192
|
-
filename = env.options.fetch :filename, "Unknown file"
|
193
|
-
|
194
|
-
Prof::Formatter.colorize "#{File.basename(orig_filename)}:"\
|
195
|
-
"#{File.basename(filename)}", :yellow
|
196
|
-
end
|
197
|
-
|
198
|
-
def fn_action
|
199
|
-
Prof::Formatter.colorize action.capitalize, :yellow
|
200
|
-
end
|
201
|
-
|
202
|
-
def fn_signature
|
203
|
-
"#{Prof::Formatter.colorize(fn_name, :blue)}"\
|
204
|
-
"(#{Prof::Formatter.colorize(fn_args, :purple)})"
|
205
|
-
end
|
38
|
+
value
|
206
39
|
end
|
207
|
-
end
|
208
40
|
|
209
|
-
|
210
|
-
class Tree::Visitors::Perform
|
211
|
-
alias_method :__visit_function, :visit_function
|
41
|
+
alias_method :__visit_mixin, :visit_mixin
|
212
42
|
|
213
|
-
def
|
214
|
-
prof =
|
43
|
+
def visit_mixin(node)
|
44
|
+
prof = ::SassProf::Profiler.new(node.dup, :include, node.args.dup,
|
45
|
+
@environment)
|
215
46
|
prof.start
|
216
47
|
|
217
|
-
value =
|
48
|
+
value = __visit_mixin node
|
218
49
|
|
219
50
|
prof.stop
|
220
51
|
|
@@ -226,7 +57,7 @@ module Sass
|
|
226
57
|
alias_method :__perform_sass_fn, :perform_sass_fn
|
227
58
|
|
228
59
|
def perform_sass_fn(function, args, splat, environment)
|
229
|
-
prof =
|
60
|
+
prof = ::SassProf::Profiler.new(function.dup, :invoke, args.dup,
|
230
61
|
environment.dup)
|
231
62
|
prof.start
|
232
63
|
|
@@ -245,8 +76,8 @@ module Sass
|
|
245
76
|
def render
|
246
77
|
__render
|
247
78
|
ensure
|
248
|
-
|
249
|
-
|
79
|
+
::SassProf::Reporter.print_report
|
80
|
+
::SassProf::Reporter.reset_report
|
250
81
|
end
|
251
82
|
end
|
252
83
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SassProf
|
2
|
+
module Config
|
3
|
+
attr_accessor :t_max
|
4
|
+
attr_accessor :max_width
|
5
|
+
attr_accessor :output_file
|
6
|
+
attr_accessor :quiet
|
7
|
+
attr_accessor :color
|
8
|
+
attr_accessor :precision
|
9
|
+
|
10
|
+
alias_method :max_execution_time=, :t_max=
|
11
|
+
alias_method :max_execution_time, :t_max
|
12
|
+
|
13
|
+
@t_max = 100
|
14
|
+
@max_width = false
|
15
|
+
@output_file = false
|
16
|
+
@quiet = false
|
17
|
+
@color = true
|
18
|
+
@precision = 15
|
19
|
+
|
20
|
+
extend self
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module SassProf
|
2
|
+
module Formatter
|
3
|
+
|
4
|
+
COLORS = Hash.new("37").merge({
|
5
|
+
:black => "30",
|
6
|
+
:red => "31",
|
7
|
+
:green => "32",
|
8
|
+
:yellow => "33",
|
9
|
+
:blue => "34",
|
10
|
+
:purple => "35",
|
11
|
+
:cyan => "36",
|
12
|
+
:white => "37",
|
13
|
+
})
|
14
|
+
|
15
|
+
def colorize(string, color)
|
16
|
+
return string.to_s unless Config.color
|
17
|
+
|
18
|
+
"\e[0;#{COLORS.fetch(color)}m#{string}\e[0m"
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_table(rows)
|
22
|
+
pr = Config.precision / 3 - 5 # 5 is to account for whitespace
|
23
|
+
t_ms = rows.map { |c|
|
24
|
+
c[1].gsub(/\e\[(\d+)(;\d+)*m/, "").to_f }.reduce :+
|
25
|
+
|
26
|
+
return if t_ms.nil?
|
27
|
+
|
28
|
+
t_ss, t_ms = t_ms.divmod 1000
|
29
|
+
t_mm, t_ss = t_ss.divmod 60
|
30
|
+
|
31
|
+
# Add total execution time footer
|
32
|
+
rows << :separator
|
33
|
+
rows << [
|
34
|
+
"Total",
|
35
|
+
"%.#{pr}fm %.#{pr}fs %.#{pr}fms" % [t_mm, t_ss, t_ms],
|
36
|
+
"",
|
37
|
+
""
|
38
|
+
]
|
39
|
+
|
40
|
+
table = Terminal::Table.new({
|
41
|
+
:headings => ["File", "Execution Time", "Action", "Signature"],
|
42
|
+
:rows => rows
|
43
|
+
})
|
44
|
+
|
45
|
+
table
|
46
|
+
end
|
47
|
+
|
48
|
+
def truncate_row(row)
|
49
|
+
max_width = Config.max_width
|
50
|
+
tr_row = []
|
51
|
+
|
52
|
+
row.map do |col|
|
53
|
+
clean_width = col.gsub(/\e\[(\d+)(;\d+)*m/, "").length
|
54
|
+
diff = col.length - clean_width
|
55
|
+
|
56
|
+
if clean_width > max_width
|
57
|
+
tr_row << (col[0..max_width + diff] << "\e[0m...")
|
58
|
+
else
|
59
|
+
tr_row << col
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
tr_row
|
64
|
+
end
|
65
|
+
|
66
|
+
extend self
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module SassProf
|
2
|
+
class Profiler
|
3
|
+
attr_accessor :function
|
4
|
+
attr_accessor :action
|
5
|
+
attr_accessor :args
|
6
|
+
attr_accessor :env
|
7
|
+
|
8
|
+
def initialize(function, action, args = nil, env = nil)
|
9
|
+
@function = function
|
10
|
+
@action = action
|
11
|
+
@args = args
|
12
|
+
@env = env
|
13
|
+
@t_total = 0
|
14
|
+
@t_then = 0
|
15
|
+
@t_now = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
@t_then = Time.now
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop
|
23
|
+
@t_now = Time.now
|
24
|
+
t_delta = (@t_now.to_f - @t_then.to_f) * 1000.0
|
25
|
+
@t_then, @t_total = @t_now, t_delta
|
26
|
+
|
27
|
+
create_fn_report
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def create_fn_report
|
33
|
+
fn_report = [fn_source, fn_execution_time, fn_action,
|
34
|
+
fn_signature]
|
35
|
+
|
36
|
+
Reporter.add_row fn_report unless Config.quiet
|
37
|
+
|
38
|
+
if @t_total > Config.t_max && is_performable_action?
|
39
|
+
raise RuntimeError.new Formatter.colorize(
|
40
|
+
"Max execution time of #{Config.t_max}ms reached for function"\
|
41
|
+
" `#{fn_name}()` (took #{@t_total.round(3)}ms)", :red)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def fn_execution_time
|
46
|
+
color = @t_total > Config.t_max ? :red : :green
|
47
|
+
t_exec = "%.#{Config.precision}f" % @t_total
|
48
|
+
Formatter.colorize t_exec, color
|
49
|
+
end
|
50
|
+
|
51
|
+
def fn_name
|
52
|
+
case
|
53
|
+
when function.respond_to?(:name)
|
54
|
+
function.name
|
55
|
+
else
|
56
|
+
"Unknown function"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def fn_args
|
61
|
+
return nil if args.nil?
|
62
|
+
|
63
|
+
if args.is_a? Array
|
64
|
+
args.map { |a| a.inspect }.join(", ")
|
65
|
+
else
|
66
|
+
args.to_s[1...args.length-2]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fn_source
|
71
|
+
return Formatter.colorize("Unknown file", :red) unless env
|
72
|
+
|
73
|
+
orig_filename = env.options.fetch :original_filename, "Unknown file"
|
74
|
+
filename = env.options.fetch :filename, "Unknown file"
|
75
|
+
|
76
|
+
Formatter.colorize "#{File.basename(orig_filename)}:"\
|
77
|
+
"#{File.basename(filename)}", :yellow
|
78
|
+
end
|
79
|
+
|
80
|
+
def fn_action
|
81
|
+
Formatter.colorize action, :yellow
|
82
|
+
end
|
83
|
+
|
84
|
+
def fn_signature
|
85
|
+
"#{Formatter.colorize(fn_name, :blue)}"\
|
86
|
+
"(#{Formatter.colorize(fn_args, :purple)})"
|
87
|
+
end
|
88
|
+
|
89
|
+
def is_performable_action?
|
90
|
+
[:invoke, :include, :extend].include? action
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SassProf
|
2
|
+
module Reporter
|
3
|
+
attr_accessor :rows
|
4
|
+
|
5
|
+
@rows = []
|
6
|
+
|
7
|
+
def add_row(row)
|
8
|
+
row = Formatter.truncate_row row if Config.max_width
|
9
|
+
@rows << row
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset_report
|
13
|
+
@rows = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_report
|
17
|
+
log_report if Config.output_file
|
18
|
+
puts Formatter.to_table @rows
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_report
|
22
|
+
File.open(Config.output_file, "a+") do |f|
|
23
|
+
f.puts Formatter.to_table @rows.map { |r|
|
24
|
+
r.map { |col| col.gsub /\e\[(\d+)(;\d+)*m/, "" } }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
extend self
|
29
|
+
end
|
30
|
+
end
|
data/lib/sass-prof/version.rb
CHANGED
data/sass-prof.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ezekg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: compass
|
@@ -95,6 +95,10 @@ files:
|
|
95
95
|
- README.md
|
96
96
|
- Rakefile
|
97
97
|
- lib/sass-prof.rb
|
98
|
+
- lib/sass-prof/config.rb
|
99
|
+
- lib/sass-prof/formatter.rb
|
100
|
+
- lib/sass-prof/profiler.rb
|
101
|
+
- lib/sass-prof/reporter.rb
|
98
102
|
- lib/sass-prof/version.rb
|
99
103
|
- sass-prof.gemspec
|
100
104
|
- screenshot.jpg
|