autobench 0.0.1alpha1

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +16 -0
  3. data/README.md +123 -0
  4. data/bin/autobench +180 -0
  5. data/bin/autobench-config +162 -0
  6. data/lib/autobench.rb +28 -0
  7. data/lib/autobench/client.rb +78 -0
  8. data/lib/autobench/common.rb +49 -0
  9. data/lib/autobench/config.rb +62 -0
  10. data/lib/autobench/render.rb +102 -0
  11. data/lib/autobench/version.rb +3 -0
  12. data/lib/autobench/yslow.rb +75 -0
  13. data/lib/phantomas/README.md +296 -0
  14. data/lib/phantomas/core/formatter.js +65 -0
  15. data/lib/phantomas/core/helper.js +64 -0
  16. data/lib/phantomas/core/modules/requestsMonitor/requestsMonitor.js +214 -0
  17. data/lib/phantomas/core/pads.js +16 -0
  18. data/lib/phantomas/core/phantomas.js +418 -0
  19. data/lib/phantomas/lib/args.js +27 -0
  20. data/lib/phantomas/lib/modules/_coffee-script.js +2 -0
  21. data/lib/phantomas/lib/modules/assert.js +326 -0
  22. data/lib/phantomas/lib/modules/events.js +216 -0
  23. data/lib/phantomas/lib/modules/http.js +55 -0
  24. data/lib/phantomas/lib/modules/path.js +441 -0
  25. data/lib/phantomas/lib/modules/punycode.js +510 -0
  26. data/lib/phantomas/lib/modules/querystring.js +214 -0
  27. data/lib/phantomas/lib/modules/tty.js +7 -0
  28. data/lib/phantomas/lib/modules/url.js +625 -0
  29. data/lib/phantomas/lib/modules/util.js +520 -0
  30. data/lib/phantomas/modules/ajaxRequests/ajaxRequests.js +15 -0
  31. data/lib/phantomas/modules/assetsTypes/assetsTypes.js +21 -0
  32. data/lib/phantomas/modules/cacheHits/cacheHits.js +28 -0
  33. data/lib/phantomas/modules/caching/caching.js +66 -0
  34. data/lib/phantomas/modules/cookies/cookies.js +54 -0
  35. data/lib/phantomas/modules/domComplexity/domComplexity.js +130 -0
  36. data/lib/phantomas/modules/domQueries/domQueries.js +148 -0
  37. data/lib/phantomas/modules/domains/domains.js +49 -0
  38. data/lib/phantomas/modules/globalVariables/globalVariables.js +44 -0
  39. data/lib/phantomas/modules/headers/headers.js +48 -0
  40. data/lib/phantomas/modules/localStorage/localStorage.js +14 -0
  41. data/lib/phantomas/modules/requestsStats/requestsStats.js +71 -0
  42. data/lib/phantomas/modules/staticAssets/staticAssets.js +40 -0
  43. data/lib/phantomas/modules/waterfall/waterfall.js +62 -0
  44. data/lib/phantomas/modules/windowPerformance/windowPerformance.js +36 -0
  45. data/lib/phantomas/package.json +27 -0
  46. data/lib/phantomas/phantomas.js +35 -0
  47. data/lib/phantomas/run-multiple.js +177 -0
  48. data/lib/yslow.js +5 -0
  49. metadata +135 -0
data/lib/autobench.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'autobench/common'
2
+ require 'autobench/config'
3
+ require 'autobench/render'
4
+ require 'autobench/yslow'
5
+ require 'autobench/client'
6
+
7
+ class Autobench
8
+ attr_accessor :config
9
+
10
+ LIB_DIR ||= File.dirname(__FILE__)
11
+ def initialize config, overides={}
12
+ @config = Autobench::Config.new(config, overides)
13
+ end
14
+
15
+ def render
16
+ @render ||= Autobench::Render.new(@config)
17
+ end
18
+
19
+ def yslow
20
+ @yslow ||= Autobench::YSlow.new(@config)
21
+ end
22
+
23
+ def client
24
+ @client ||= Autobench::Client.new(@config)
25
+ end
26
+ end
27
+
28
+ # vim: ft=ruby:
@@ -0,0 +1,78 @@
1
+ class Autobench
2
+ class Client
3
+ include Common
4
+ def initialize config
5
+ @config = config
6
+ @thresholds = @config["thresholds"]["client"] rescue []
7
+ @full_results = []
8
+ @failures = []
9
+ @successes = []
10
+ end
11
+
12
+ def benchmark
13
+ begin
14
+ @full_results = JSON.parse(%x{#{command}}.strip)
15
+ @thresholds.each do |key,threshold|
16
+ if fetch(key) > threshold
17
+ @failures.push("#{key} is #{fetch(key)}, threshold is #{threshold}")
18
+ else
19
+ @successes.push("#{key} is #{fetch(key)}, threshold is #{threshold}")
20
+ end
21
+ end
22
+ @full_results
23
+ rescue
24
+ puts "COMMAND FAILED: #{command}"
25
+ raise
26
+ end
27
+ end
28
+
29
+ def [](key)
30
+ return fetch(key)
31
+ end
32
+
33
+ def fetch(key)
34
+ return median(raw_results.map {|i| i[key] })
35
+ end
36
+
37
+ # backdoor hook to @full_results
38
+ def raw_results
39
+ raise "missing benchmarks" unless @full_results
40
+ @full_results
41
+ end
42
+
43
+ # generate result set that is only medians by default
44
+ def full_results
45
+ r = {}
46
+ raw_results.first.keys.each do |key|
47
+ r[key] = fetch(key)
48
+ end
49
+ return r
50
+ end
51
+
52
+ private
53
+ def command
54
+ "cd #{@config.phantomas} && #{@config.node} ./run-multiple.js #{modules} --url=#{url} --runs=#{@config["runs"]} --format=json"
55
+ end
56
+
57
+ def url
58
+ "http://#{@config['server']}#{(@config['port'] == 80 ? "" : ":#{@config['port']}")}#{@config['uri']}"
59
+ end
60
+
61
+ def modules
62
+ mod_str = ""
63
+ if @config.has_key?("phantomas") && @config["phantomas"].has_key?("modules")
64
+ mod_str << "--modules="+@config["phantomas"]["modules"].join(",")
65
+ end
66
+ return mod_str
67
+ end
68
+
69
+ def median(array)
70
+ sorted = array.sort
71
+ len = sorted.length
72
+ return (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
73
+ end
74
+ end
75
+ end
76
+
77
+ # vim: ft=ruby:
78
+
@@ -0,0 +1,49 @@
1
+ class Autobench
2
+ module Common
3
+ def [](key)
4
+ full_results[key.to_sym]
5
+ end
6
+
7
+ def clean_keys results, ignored
8
+ raise "missing benchmarks" unless @full_results
9
+ results.each_key do |key|
10
+ results.delete(key) if ignored.include?(key)
11
+ end
12
+ return results
13
+ end
14
+
15
+ def failures
16
+ return "none" if passed?
17
+ out = ""
18
+ @failures.each_with_index do |f,i|
19
+ out << "[#{i+1}] #{f}\n"
20
+ end
21
+ return out
22
+ end
23
+
24
+ def successes
25
+ raise "missing benchmarks" unless @full_results
26
+ return "none" if @successes.empty?
27
+ out = ""
28
+ @successes.each_with_index do |f,i|
29
+ out << "[#{i+1}] #{f}\n"
30
+ end
31
+ return out
32
+ end
33
+
34
+ def passed?
35
+ raise "missing benchmarks" unless @full_results
36
+ return @failures.empty?
37
+ end
38
+
39
+ def failed?
40
+ !passed?
41
+ end
42
+
43
+ def thresholds?
44
+ return !@thresholds.empty?
45
+ end
46
+
47
+ end
48
+ end
49
+
@@ -0,0 +1,62 @@
1
+ require "yaml"
2
+ require "json"
3
+
4
+ class Autobench
5
+ LIB_DIR ||= File.expand_path('..', File.dirname(__FILE__))
6
+ class Config
7
+ attr_accessor :basedir
8
+ def initialize config, overides={}
9
+ @config = if config.is_a?(String)
10
+ YAML.load_file(config).merge(overides)
11
+ elsif config.is_a?(Hash)
12
+ config.merge(overides)
13
+ else
14
+ raise "invalid config"
15
+ end
16
+ end
17
+
18
+ def phantomas
19
+ default = File.join(::Autobench::LIB_DIR, "phantomas")
20
+ begin
21
+ return default if @config["paths"]["phantomas"].nil?
22
+ return @config["paths"]["phantomas"]
23
+ rescue NoMethodError
24
+ return default
25
+ end
26
+ end
27
+
28
+ def yslow
29
+ default = ::Autobench::LIB_DIR
30
+ begin
31
+ return default if @config["paths"]["yslow"].nil?
32
+ return @config["paths"]["yslow"]
33
+ rescue NoMethodError
34
+ return default
35
+ end
36
+ end
37
+
38
+ %w{ httperf node phantomjs }.each do |bin|
39
+ define_method(bin) do
40
+ return @config["paths"][bin] rescue bin
41
+ end
42
+ end
43
+ #def httperf
44
+ #return @config["paths"]["httperf"] rescue "httperf"
45
+ #end
46
+
47
+ #def node
48
+ #return @config["paths"]["node"] rescue "node"
49
+ #end
50
+
51
+ #def phantomjs
52
+ #return @config["paths"]["phantomjs"] rescue "phantomjs"
53
+ #end
54
+
55
+
56
+ def method_missing(meth, *args, &block)
57
+ @config.send(meth.to_sym, *args, &block) rescue super
58
+ end
59
+ end
60
+ end
61
+
62
+ # vim: ft=ruby:
@@ -0,0 +1,102 @@
1
+ require 'httperf'
2
+ class Autobench
3
+ LIB_DIR ||= File.expand_path('..', File.dirname(__FILE__))
4
+ class Render
5
+ include Common
6
+ def initialize config
7
+ @config = config
8
+ @thresholds = config["thresholds"]["render"] rescue []
9
+ @failures = []
10
+ @successes = []
11
+ setup_httperf_configuration(config)
12
+ end
13
+
14
+ def benchmark
15
+ httperf = HTTPerf.new(@httperf_config, @config.httperf)
16
+ httperf.parse = true
17
+
18
+ @full_results = httperf.run.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}
19
+ # keys: sym -> str
20
+
21
+ @thresholds.each do |key,threshold|
22
+ if higher_is_better.include?(key)
23
+ if (full_results[key].to_f < threshold.to_f)
24
+ @failures.push("#{key} is #{full_results[key].to_f}, threshold is #{threshold.to_f}")
25
+ else
26
+ @successes.push("#{key} is #{full_results[key].to_f}, threshold is #{threshold.to_f}")
27
+ end
28
+ else
29
+ if (full_results[key].to_f > threshold.to_f)
30
+ @failures.push("#{key} is #{full_results[key].to_f}, threshold is #{threshold.to_f}")
31
+ else
32
+ @successes.push("#{key} is #{full_results[key].to_f}, threshold is #{threshold.to_f}")
33
+ end
34
+ end
35
+ end
36
+
37
+ ignored_keys.each do |key|
38
+ @full_results.delete(key)
39
+ end
40
+
41
+ @full_results
42
+ end
43
+
44
+ def full_results
45
+ return clean_keys(@full_results, %w[ command connection_times ])
46
+ end
47
+
48
+ private
49
+ def setup_httperf_configuration config
50
+ @httperf_config = {} # defaults
51
+
52
+ if config.has_key?("httperf")
53
+ puts config["httperf"]
54
+ @httperf_config.merge!(config["httperf"])
55
+ end
56
+
57
+ # all required
58
+ %w{ server port uri }.each do |key|
59
+ raise "Autobench::Render missing `#{key}`." unless config.has_key?(key)
60
+ @httperf_config[key] = config[key]
61
+ end
62
+
63
+ if config.has_key?("runs")
64
+ @httperf_config["num-conns"] = config["runs"]
65
+ end
66
+
67
+ @httperf_config.merge!(httperf_forced_options)
68
+ end
69
+
70
+ def httperf_forced_options
71
+ { "verbose" => true }
72
+ end
73
+
74
+ def higher_is_better
75
+ %w[
76
+ connection_rate_per_sec
77
+ request_rate_per_sec
78
+ reply_status_2xx
79
+ total_connections
80
+ total_requests
81
+ total_replies
82
+ ]
83
+ end
84
+ def ignored_keys
85
+ %w[
86
+ max_connect_burst_length
87
+ cpu_time_system_pct
88
+ cpu_time_total_pct
89
+ cpu_time_user_sec
90
+ cpu_time_system_sec
91
+ cpu_time_user_pct
92
+ reply_rate_min
93
+ reply_rate_avg
94
+ reply_rate_max
95
+ reply_rate_stddev
96
+ reply_rate_samples
97
+ connection_length
98
+ ]
99
+ end
100
+ end
101
+ end
102
+ # vim: ft=ruby:
@@ -0,0 +1,3 @@
1
+ class Autobench
2
+ VERSION = '0.0.1alpha1'
3
+ end
@@ -0,0 +1,75 @@
1
+ require 'json'
2
+ class Autobench
3
+ LIB_DIR ||= File.expand_path('..', File.dirname(__FILE__))
4
+ class YSlow
5
+ include Common
6
+ def initialize config
7
+ @config = config
8
+ @thresholds = config["thresholds"]["yslow"] rescue []
9
+ @failures = []
10
+ @successes = []
11
+ end
12
+
13
+ def benchmark
14
+ begin
15
+ @full_results = JSON.parse(%x{#{command}}.strip)
16
+ rescue
17
+ raise "Error running: #{command}"
18
+ end
19
+ @thresholds.each do |key,threshold|
20
+ # U-G-L-Y
21
+ if key == "overall"
22
+ if full_results[mappings[key]].to_i < threshold.to_i
23
+ @failures.push("#{key} is #{full_results[mappings[key]]}, threshold is #{threshold}");
24
+ else
25
+ @successes.push("#{key} is #{full_results[mappings[key]]}, threshold is #{threshold}");
26
+ end
27
+ else
28
+ if full_results[mappings[key]].to_i > threshold.to_i
29
+ @failures.push("#{key} is #{full_results[mappings[key]]}, threshold is #{threshold}");
30
+ else
31
+ @successes.push("#{key} is #{full_results[mappings[key]]}, threshold is #{threshold}");
32
+ end
33
+ end
34
+ end
35
+ @full_results
36
+ end
37
+
38
+ def [](key)
39
+ return full_results[mappings[key]] if mappings.keys.include?(key)
40
+ return full_results[key] if mappings.values.include?(key)
41
+ return nil
42
+ end
43
+
44
+ def full_results
45
+ return clean_keys(@full_results, ['u','i'])
46
+ end
47
+
48
+ def mappings
49
+ {
50
+ "overall" => "o",
51
+ "loadtime" => "lt",
52
+ "requests" => "r",
53
+ "size" => "w"
54
+ }
55
+ end
56
+
57
+ private
58
+ def command
59
+ "cd #{@config.yslow} && #{@config.phantomjs} ./yslow.js --info basic #{options} http://#{@config['server']}#{(@config.has_key?("port") ? ":#{@config['port']}" : "")}#{@config['uri']}"
60
+ end
61
+
62
+ def options
63
+ return "" unless @config.has_key?("yslow")
64
+
65
+ ret = []
66
+ %w{ ruleset ua headers viewport }.each do |key|
67
+ ret.push "--#{key} #{@config["yslow"][key]}" if @config["yslow"].has_key?(key)
68
+ end
69
+
70
+ return ret.join(" ")
71
+ end
72
+ end
73
+ end
74
+
75
+ # vim: ft=ruby:
@@ -0,0 +1,296 @@
1
+ phantomas
2
+ =========
3
+
4
+ ![GitHub Logo](http://upload.wikimedia.org/wikipedia/en/a/a5/Fantomas.jpg)
5
+
6
+ PhantomJS-based modular web performance metrics collector.
7
+
8
+ And why phantomas? Well, [because](http://en.wikipedia.org/wiki/Fantômas) :)
9
+
10
+ ## Requirements
11
+
12
+ * [PhantomJS 1.7+](http://phantomjs.org/)
13
+ * [NodeJS](http://nodejs.org) (for `run-multiple.js` script)
14
+
15
+ ## Installation
16
+
17
+ ```
18
+ npm install phantomas
19
+ ```
20
+
21
+ ## Dependencies
22
+
23
+ phantomas uses the following 3rd party libraries (located in `/lib` directory):
24
+
25
+ * CommonJS modules from [phantomjs-nodify](https://github.com/jgonera/phantomjs-nodify) and nodejs source
26
+
27
+ ## Let's make Web a bit faster!
28
+
29
+ * [Best Practices for Speeding Up Your Web Site](http://developer.yahoo.com/performance/rules.html) (by Yahoo!)
30
+ * [Web Performance Best Practices](https://developers.google.com/speed/docs/best-practices/rules_intro) (by Google)
31
+
32
+ ## Contributors
33
+
34
+ * [macbre](https://github.com/macbre)
35
+ * [jmosney](https://github.com/jmosney)
36
+ * All the [contributors](https://github.com/macbre/phantomas/graphs/contributors)
37
+
38
+ ## Usage
39
+
40
+ ### Single run
41
+
42
+ ``` bash
43
+ ./phantomas.js --url=https://github.com/macbre/phantomas --verbose
44
+ ```
45
+
46
+ #### Parameters
47
+
48
+ * `--url` URL of the page to generate metrics for (required)
49
+ * `--format=[json|csv|plain]` output format (``plain`` is the default one)
50
+ * `--timeout=[seconds]` timeout for phantomas run (defaults to 15 seconds)
51
+ * `--viewport=[width]x[height]` phantomJS viewport dimensions (1280x1024 is the default)
52
+ * `--verbose` writes debug messages to the console
53
+ * `--silent` don't write anything to the console
54
+ * `--modules=[moduleOne],[moduleTwo]` run only selected modules
55
+ * `--user-agent='Custom user agent'` provide a custom user agent (will default to something similar to ``phantomas/0.4 (PhantomJS/1.7.0; 64bit)``)
56
+
57
+ ### Multiple runs
58
+
59
+ This helper script requires NodeJS.
60
+
61
+ ``` bash
62
+ ./run-multiple.js --url=https://github.com/macbre/phantomas --runs=5
63
+ ```
64
+
65
+ #### Parameters
66
+
67
+ * `--url` URL of the page to generate metrics for (required)
68
+ * `--runs` number of runs to perform (defaults to 3)
69
+ * `--modules=[moduleOne],[moduleTwo]` run only selected modules
70
+
71
+ ## Features
72
+
73
+ * Modular approach - each metric is generated by a separate "module"
74
+ * phantomas "core" acts as an [events emitter](https://github.com/macbre/phantomas/wiki/Events) that each module can hook into
75
+ * JSON and CSV as available output formats for easy integration with automated reporting / monitoring tools
76
+
77
+ ## Metrics
78
+
79
+ _Current number of metrics: 64_
80
+
81
+ Units:
82
+
83
+ * ms for time
84
+ * bytes for size
85
+
86
+ ```
87
+ ./phantomas.js --url=https://github.com/macbre/phantomas
88
+
89
+ phantomas metrics for <https://github.com/macbre/phantomas>:
90
+
91
+ * requests: 22
92
+ * gzipRequests: 9
93
+ * postRequests: 0
94
+ * redirects: 0
95
+ * notFound: 0
96
+ * timeToFirstByte: 503
97
+ * timeToLastByte: 520
98
+ * bodySize: 675125
99
+ * contentLength: 708206
100
+ * ajaxRequests: 0
101
+ * htmlCount: 1
102
+ * htmlSize: 50728
103
+ * cssCount: 2
104
+ * cssSize: 174949
105
+ * jsCount: 4
106
+ * jsSize: 322932
107
+ * imageCount: 12
108
+ * imageSize: 49287
109
+ * base64Count: 0
110
+ * base64Size: 0
111
+ * otherCount: 3
112
+ * otherSize: 77229
113
+ * cacheHits: 0
114
+ * cacheMisses: 0
115
+ * cachingNotSpecified: 3
116
+ * cachingTooShort: 2
117
+ * cachingDisabled: 0
118
+ * headersCount: 265
119
+ * headersSentCount: 65
120
+ * headersRecvCount: 200
121
+ * headersSize: 10205
122
+ * headersSentSize: 3850
123
+ * headersRecvSize: 6355
124
+ * assetsNotGzipped: 0
125
+ * assetsWithQueryString: 9
126
+ * smallImages: 2
127
+ * httpTrafficCompleted: 2460
128
+ * domains: 5
129
+ * DOMqueries: 39
130
+ * DOMinserts: 19
131
+ * jQuerySelectors: 0
132
+ * jQueryOnDOMReadyFunctions: 0
133
+ * cookiesSent: 0
134
+ * cookiesRecv: 268
135
+ * domainsWithCookies: 1
136
+ * documentCookiesLength: 387
137
+ * documentCookiesCount: 12
138
+ * bodyHTMLSize: 47769
139
+ * commentsSize: 452
140
+ * hiddenContentSize: 15635
141
+ * whiteSpacesSize: 2378
142
+ * DOMelementsCount: 554
143
+ * DOMelementMaxDepth: 13
144
+ * iframesCount: 0
145
+ * nodesWithInlineCSS: 5
146
+ * imagesWithoutDimensions: 3
147
+ * globalVariables: 18
148
+ * localStorageEntries: 0
149
+ * smallestResponse: 35
150
+ * biggestResponse: 239453
151
+ * fastestResponse: 43
152
+ * slowestResponse: 984
153
+ * medianResponse: 130.5
154
+ * onDOMReadyTime: 482
155
+ * windowOnLoadTime: 1716
156
+ ```
157
+
158
+ ### Requests monitor (core module)
159
+
160
+ * requests: total number of HTTP requests made
161
+ * gzipRequests: number of gzipped HTTP responses
162
+ * postRequests: number of POST requests
163
+ * redirects: number of HTTP redirects (either 301 or 302)
164
+ * notFound: number of HTTP 404 responses
165
+ * timeToFirstByte: time it took to receive the first byte of the first response
166
+ * timeToLastByte: time it took to receive the last byte of the first response
167
+ * bodySize: size of the content of all responses
168
+ * contentLength: size of the content of all responses (based on ``Content-Length`` header)
169
+ * httpTrafficCompleted: time it took to receive the last byte of the last HTTP response
170
+
171
+ ### AJAX requests
172
+
173
+ * ajaxRequests: number of AJAX requests
174
+
175
+ ### Assets types
176
+
177
+ * htmlCount: number of html responses
178
+ * htmlSize: size of html responses
179
+ * cssCount: number of css responses
180
+ * cssSize: size of css responses
181
+ * jsCount: number of js responses
182
+ * jsSize: size of js responses
183
+ * imageCount: number of image responses
184
+ * imageSize: size of image responses
185
+ * base64Count: number of base64 encoded "responses" (no HTTP request was made)
186
+ * base64Size: size of base64 encoded "responses"
187
+ * otherCount: number of other responses
188
+ * otherSize: size of other responses
189
+
190
+ ### Cache Hits
191
+
192
+ _Metrics are calculated based on ``X-Cache`` header added by Varnish / Squid servers._
193
+
194
+ * cacheHits: number of cache hits
195
+ * cacheMisses: number of cache misses
196
+
197
+ ### Headers
198
+
199
+ * headersCount: number of requests and responses headers
200
+ * headersSentCount: number of headers sent in requests
201
+ * headersRecvCount: number of headers received in responses
202
+ * headersSize: size of all headers
203
+ * headersSentSize: size of sent headers
204
+ * headersRecvSize: size of received headers
205
+
206
+ ### Domains
207
+
208
+ * domains: number of domains used to fetch the page
209
+
210
+ ### Cookies
211
+
212
+ * cookiesSent: length of cookies sent in HTTP requests
213
+ * cookiesRecv: length of cookies received in HTTP responses
214
+ * domainsWithCookies: number of domains with cookies set
215
+ * documentCookiesLength: length of `document.cookie`
216
+ * documentCookiesCount: number of cookies in `document.cookie`
217
+
218
+ ### DOM complexity
219
+
220
+ * globalVariables: number of JS globals variables
221
+ * bodyHTMLSize: the size of body tag content
222
+ * commentsSize: the size of HTML comments on the page
223
+ * hiddenContentSize: the size of content of hidden elements on the page (with CSS ``display: none``)
224
+ * whiteSpacesSize: the size of text nodes with whitespaces only
225
+ * DOMelementsCount: total number of HTML element nodes
226
+ * DOMelementMaxDepth: maximum level on nesting of HTML element node
227
+ * iframesCount: number of iframe nodes
228
+ * nodesWithInlineCSS: number of nodes with inline CSS styling (with `style` attribute)
229
+ * imagesWithoutDimensions: number of ``<img>`` nodes without both ``width`` and ``height`` attribute
230
+
231
+ ### DOM queries
232
+
233
+ * DOMqueries: number of `document.getElementById` and `document.getElementsByClassName` calls
234
+ * DOMinserts: number of DOM nodes inserts
235
+ * jQuerySelectors: number of jQuery selectors calls (e.g. `$('#foo > .bar')`)
236
+ * jQueryOnDOMReadyFunctions: number of functions bound to onDOMready event
237
+
238
+ ### Window performance
239
+
240
+ * onDOMReadyTime: time it took to fire onDOMready event
241
+ * windowOnLoadTime: time it took to fire window.load event
242
+
243
+ ### Requests statistics
244
+
245
+ * smallestResponse: the size of the smallest response
246
+ * biggestResponse: the size of the biggest response
247
+ * fastestResponse: the time to the last byte of the fastest response
248
+ * slowestResponse: the time to the last byte of the slowest response
249
+ * medianResponse: median value of time to the last byte for all responses
250
+
251
+ ### localStorage
252
+
253
+ * localStorageEntries: number of entries in local storage
254
+
255
+ ### Static assets
256
+
257
+ * assetsNotGzipped: static assets that were not gzipped
258
+ * assetsWithQueryString: static assets requested with query string (e.g. ?foo) in URL
259
+ * smallImages: images smaller than 2 kB that can be base64 encoded
260
+
261
+ ### Caching
262
+
263
+ * cachingNotSpecified: responses with no caching header sent (either `Cache-Control` or `Expires`)
264
+ * cachingTooShort: responses with too short (less than a week) caching time
265
+ * cachingDisabled: responses with caching disabled (`max-age=0`)
266
+
267
+ ## Notices
268
+
269
+ phantomas apart from "raw" metrics data, when in `--verbose` mode, emits notices with more in-depth data:
270
+
271
+ ```
272
+ > Caching period is less than a week for <https://ssl.google-analytics.com/ga.js> (set to 43200 s)
273
+ > No caching specified for <https://secure.gaug.es/track.js>
274
+ > Caching period is less than a week for <https://secure.gravatar.com/avatar/57548e3255bfa0e74afff98289dae839?s=140&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png> (set to 300 s)
275
+ > https://secure.gravatar.com/avatar/57548e3255bfa0e74afff98289dae839?s=140&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png (IMAGE) served with query string
276
+ > Requests per domain:
277
+ > github.com: 1 request(s)
278
+ > a248.e.akamai.net: 16 request(s)
279
+ > ssl.google-analytics.com: 2 request(s)
280
+ > secure.gaug.es: 2 request(s)
281
+ > secure.gravatar.com: 1 request(s)
282
+ >
283
+ > JavaScript globals (18): html5, Modernizr, moment, $, jQuery, $stats, jQuery18302483161953277886, GitHub, DateInput, clippyCopiedCallback, debug, _gaq, _gauges, CommandBar, stringDistance, fuzzyScore, _gat, gaGlobal
284
+ >
285
+ > The smallest response (0.03 kB): https://ssl.google-analytics.com/__utm.gif?utmwv=5.3.8&utms=1&utmn=396347331&utmhn=github.com&utmcs=UTF-8&utmsr=1024x768&utmvp=1024x1280&utmsc=32-bit&utmul=pl-pl&utmje=0&utmfl=-&utmdt=macbre%2Fphantomas%20%C2%B7%20GitHub&utmhid=1963809109&utmr=-&utmp=%2Fmacbre%2Fphantomas&utmac=UA-3769691-2&utmcc=__utma%3D1.1523233271.1353260190.1353260190.1353260190.1%3B%2B__utmz%3D1.1353260190.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&utmu=qB~
286
+ > The biggest response (233.84 kB): https://a248.e.akamai.net/assets.github.com/assets/github-81433815e4751f68e04d42ec948cba14ab028c2d.js
287
+ >
288
+ > The fastest response (43 ms): https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x.png?1340659561
289
+ > The slowest response (984 ms): https://secure.gravatar.com/avatar/57548e3255bfa0e74afff98289dae839?s=140&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png
290
+ ```
291
+
292
+ ## For developers
293
+
294
+ * [Project's wiki](https://github.com/macbre/phantomas/wiki)
295
+ * Description of [events fired by phantomas core](https://github.com/macbre/phantomas/wiki/Events)
296
+ * [TODO list](https://github.com/macbre/phantomas/wiki/TODO)