├── .gitignore
├── README.md
├── css
└── flamegraph.css
├── inc
├── class-qm-collector.php
└── class-qm-output-html.php
├── js
└── d3-flame-graph
│ ├── LICENSE
│ ├── bower.json
│ ├── bower_components
│ ├── d3-tip
│ │ ├── .bower.json
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── index.js
│ │ └── package.json
│ ├── d3
│ │ ├── .bower.json
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── d3.js
│ │ └── d3.min.js
│ └── lodash
│ │ ├── .bower.json
│ │ ├── LICENSE
│ │ ├── bower.json
│ │ ├── lodash.js
│ │ └── lodash.min.js
│ └── src
│ ├── d3.flameGraph.css
│ └── d3.flameGraph.js
└── query-monitor-flamegraph.php
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/humanmade/query-monitor-flamegraph/bae55d3a12f9648ac9a15daf7ab45c92b9451085/.gitignore
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Query Monitor Flamegraph
5 | This Query Monitor extension will add profiling framegraphs to Query Monitor via the xhprof PHP extension.
6 | |
7 |
8 | |
9 |
10 |
11 |
12 | A Human Made project. Maintained by @joehoyle.
13 | |
14 |
15 |
16 | |
17 |
18 |
19 |
20 | 
21 |
22 | ## Install Instructions
23 |
24 | 1. Have the [Query Monitor](https://github.com/johnbillion/query-monitor) plugin installed and activated.
25 | 1. Have the [xhprof](https://pecl.php.net/package/xhprof) PHP extension installed.
26 | 1. Install this plugin :)
27 | 1. Add a call to `xhprof_sample_enable();` to your `wp-config.php`
28 |
29 | ## Versions of XHProf
30 |
31 | Unfortunately XHProf is not actively maintained and has some shortcomings. Flamegraph makes use of the `xhprof_sample_enable()` function which by is hardcoded to 100ms intervals with the official XHProf extension. There's several forks and updates to XHProf, refer to the table below:
32 |
33 | |Project|Compatible|Notes|
34 | |---|---|---|
35 | |[XHProf Official](https://pecl.php.net/package/xhprof)|yes|Note: Doesn't support PHP 7. Is restricted to 100ms interval sampling, making it useless for the most part.|
36 | |[XHProf with configurable sampling](https://github.com/phacility/xhprof/pull/80)|yes|Note: Doesn't support PHP 7. Best solution! However, you'll need to build from source.|
37 | |[Tideways](https://tideways.io/profiler/xhprof-for-php7-php5.6)|no|Tideways is an XHProf fork, however doesn't support `*_sample_enabled`. See https://github.com/tideways/php-profiler-extension/issues/26.|
38 | |[XHProf PHP7 fork](https://github.com/RustJason/xhprof/tree/php7)|no|Doesn't support `xhprof_sample_enabled`|
39 |
40 | If you know of any other XHProf forks or compatible output libraries, be sure to let me know!
41 |
--------------------------------------------------------------------------------
/css/flamegraph.css:
--------------------------------------------------------------------------------
1 | .timestack-flamegraph {
2 | min-height: 400px;
3 | position: relative;
4 | }
5 |
6 | .timestack-flamegraph > ul.timestack-split-timeline {
7 | position: absolute;
8 | bottom: 0;
9 | left: 0;
10 | right: 0;
11 | }
12 |
13 | ul.timestack-split-timeline {
14 | list-style: none;
15 | margin: 0;
16 | padding: 0 !important;
17 | position: relative;
18 | height: 20px;
19 | margin-top: -20px !important;
20 | }
21 |
22 | ul.timestack-split-timeline > li {
23 | float: left;
24 | display: block;
25 | height: 20px;
26 | box-sizing: border-box;
27 | position: relative;
28 | /*border-right: 1px solid rgba(0,0,0,.3);*/
29 | border-radius: 2px;
30 | position: relative;
31 | }
32 |
33 | ul.timestack-split-timeline > li:after {
34 | display: block;
35 | position: absolute;
36 | top: 0;
37 | left: 0;
38 | bottom: 0;
39 | right: 0;
40 | content: attr(data-name);
41 | overflow: hidden;
42 | padding: 1px 4px;
43 | opacity: .3;
44 | font-weight: bold;
45 | font-size: 10px;
46 | }
47 |
--------------------------------------------------------------------------------
/inc/class-qm-collector.php:
--------------------------------------------------------------------------------
1 | data = $this->folded_to_hierarchical( $stack );
43 | }
44 |
45 | protected function folded_to_hierarchical( $stack ) {
46 |
47 | $nodes = array( (object) array(
48 | 'name' => 'main()',
49 | 'value' => 1,
50 | 'children' => [],
51 | ) );
52 |
53 | foreach ( $stack as $time => $call_stack ) {
54 | $call_stack = explode( '==>', $call_stack );
55 |
56 |
57 | $nodes = $this->add_children_to_nodes( $nodes, $call_stack );
58 | }
59 |
60 | return $nodes;
61 | }
62 |
63 | /**
64 | * Accepts [ Node, Node ], [ main, wp-settings, sleep ]
65 | */
66 | protected function add_children_to_nodes( $nodes, $children ) {
67 | $last_node = $nodes ? $nodes[ count( $nodes ) - 1 ] : null;
68 | $this_child = $children[0];
69 | $time = (int) ini_get( 'xhprof.sampling_interval' );
70 |
71 | if ( ! $time ) {
72 | $time = 100000;
73 | }
74 | if ( $last_node && $last_node->name === $this_child ) {
75 | $node = $last_node;
76 | $node->value += ( $time / 1000 );
77 | } else {
78 | $nodes[] = $node = (object) array(
79 | 'name' => $this_child,
80 | 'value' => $time / 1000,
81 | 'children' => array(),
82 | );
83 | }
84 | if ( count( $children ) > 1 ) {
85 | $node->children = $this->add_children_to_nodes( $node->children, array_slice( $children, 1 ) );
86 | }
87 |
88 | return $nodes;
89 |
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/inc/class-qm-output-html.php:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 |
38 |
39 |
collector->get_data()[0] ); ?>
40 |
45 |
68 |
69 | "
7 | ],
8 | "description": "A d3.js library to produce flame graphs.",
9 | "main": "src/d3.flame.js",
10 | "keywords": [
11 | "flame",
12 | "graph",
13 | "flamegraph",
14 | "performance",
15 | "d3",
16 | "d3js"
17 | ],
18 | "license": "Apache-2.0",
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "tests"
25 | ],
26 | "dependencies": {
27 | "d3": "~3.5.5",
28 | "d3-tip": "~0.6.7",
29 | "lodash": "~3.10.1"
30 | },
31 | "resolutions": {
32 | "d3": "3.5.5"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3-tip",
3 | "version": "0.6.8",
4 | "main": "index.js",
5 | "ignore": [
6 | "**/.*",
7 | "node_modules",
8 | "components",
9 | "bower_components",
10 | "examples",
11 | "Makefile",
12 | "docs"
13 | ],
14 | "dependencies": {
15 | "d3": "^3.5.5"
16 | },
17 | "homepage": "https://github.com/Caged/d3-tip",
18 | "_release": "0.6.8",
19 | "_resolution": {
20 | "type": "version",
21 | "tag": "v0.6.8",
22 | "commit": "92bd167db0c3c24e895e7405376630be79b53a0b"
23 | },
24 | "_source": "https://github.com/Caged/d3-tip.git",
25 | "_target": "~0.6.7",
26 | "_originalSource": "d3-tip"
27 | }
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2013 Justin Palmer
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/README.md:
--------------------------------------------------------------------------------
1 | # d3.tip: Tooltips for d3.js visualizations
2 |
3 | [](http://bl.ocks.org/Caged/6476579)
4 |
5 | * [See a live demo](http://bl.ocks.org/Caged/6476579)
6 | * [Example code](/examples)
7 |
8 | ### API Docs
9 | See the [API Documentation](docs/index.md)
10 |
11 | ### Download Latest Version
12 | * [Development Version](https://raw.github.com/Caged/d3-tip/master/index.js) : **6kb** / **~2kb gzipped**
13 |
14 | ### Install with Bower
15 | ```
16 | bower install d3-tip
17 | ```
18 |
19 | ### Quick Usage
20 | ```javascript
21 | /* Initialize tooltip */
22 | tip = d3.tip().attr('class', 'd3-tip').html(function(d) { return d; });
23 |
24 | /* Invoke the tip in the context of your visualization */
25 | vis.call(tip)
26 |
27 | vis.selectAll('rect')
28 | .data(data)
29 | .enter().append('rect')
30 | .attr('width', function() { return x.rangeBand() })
31 | .attr('height', function(d) { return h - y(d) })
32 | .attr('y', function(d) { return y(d) })
33 | .attr('x', function(d, i) { return x(i) })
34 | .on('mouseover', tip.show)
35 | .on('mouseout', tip.hide)
36 | ```
37 |
38 | If you want basic styling, you can include `example-styles.css` using a service like
39 | rawgithub.com.
40 |
41 | ```html
42 |
43 | ```
44 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3-tip",
3 | "version": "0.6.8",
4 | "main": "index.js",
5 | "ignore": [
6 | "**/.*",
7 | "node_modules",
8 | "components",
9 | "bower_components",
10 | "examples",
11 | "Makefile",
12 | "docs"
13 | ],
14 | "dependencies": {
15 | "d3": "^3.5.5"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/index.js:
--------------------------------------------------------------------------------
1 | // d3.tip
2 | // Copyright (c) 2013 Justin Palmer
3 | //
4 | // Tooltips for d3.js SVG visualizations
5 |
6 | (function (root, factory) {
7 | if (typeof define === 'function' && define.amd) {
8 | // AMD. Register as an anonymous module with d3 as a dependency.
9 | define(['d3'], factory)
10 | } else if (typeof module === 'object' && module.exports) {
11 | // CommonJS
12 | module.exports = function(d3) {
13 | d3.tip = factory(d3)
14 | return d3.tip
15 | }
16 | } else {
17 | // Browser global.
18 | root.d3.tip = factory(root.d3)
19 | }
20 | }(this, function (d3) {
21 |
22 | // Public - contructs a new tooltip
23 | //
24 | // Returns a tip
25 | return function() {
26 | var direction = d3_tip_direction,
27 | offset = d3_tip_offset,
28 | html = d3_tip_html,
29 | node = initNode(),
30 | svg = null,
31 | point = null,
32 | target = null
33 |
34 | function tip(vis) {
35 | svg = getSVGNode(vis)
36 | point = svg.createSVGPoint()
37 | document.body.appendChild(node)
38 | }
39 |
40 | // Public - show the tooltip on the screen
41 | //
42 | // Returns a tip
43 | tip.show = function() {
44 | var args = Array.prototype.slice.call(arguments)
45 | if(args[args.length - 1] instanceof SVGElement) target = args.pop()
46 |
47 | var content = html.apply(this, args),
48 | poffset = offset.apply(this, args),
49 | dir = direction.apply(this, args),
50 | nodel = getNodeEl(),
51 | i = directions.length,
52 | coords,
53 | scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
54 | scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
55 |
56 | nodel.html(content)
57 | .style({ opacity: 1, 'pointer-events': 'all' })
58 |
59 | while(i--) nodel.classed(directions[i], false)
60 | coords = direction_callbacks.get(dir).apply(this)
61 | nodel.classed(dir, true).style({
62 | top: (coords.top + poffset[0]) + scrollTop + 'px',
63 | left: (coords.left + poffset[1]) + scrollLeft + 'px'
64 | })
65 |
66 | return tip
67 | }
68 |
69 | // Public - hide the tooltip
70 | //
71 | // Returns a tip
72 | tip.hide = function() {
73 | var nodel = getNodeEl()
74 | nodel.style({ opacity: 0, 'pointer-events': 'none' })
75 | return tip
76 | }
77 |
78 | // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
79 | //
80 | // n - name of the attribute
81 | // v - value of the attribute
82 | //
83 | // Returns tip or attribute value
84 | tip.attr = function(n, v) {
85 | if (arguments.length < 2 && typeof n === 'string') {
86 | return getNodeEl().attr(n)
87 | } else {
88 | var args = Array.prototype.slice.call(arguments)
89 | d3.selection.prototype.attr.apply(getNodeEl(), args)
90 | }
91 |
92 | return tip
93 | }
94 |
95 | // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
96 | //
97 | // n - name of the property
98 | // v - value of the property
99 | //
100 | // Returns tip or style property value
101 | tip.style = function(n, v) {
102 | if (arguments.length < 2 && typeof n === 'string') {
103 | return getNodeEl().style(n)
104 | } else {
105 | var args = Array.prototype.slice.call(arguments)
106 | d3.selection.prototype.style.apply(getNodeEl(), args)
107 | }
108 |
109 | return tip
110 | }
111 |
112 | // Public: Set or get the direction of the tooltip
113 | //
114 | // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
115 | // sw(southwest), ne(northeast) or se(southeast)
116 | //
117 | // Returns tip or direction
118 | tip.direction = function(v) {
119 | if (!arguments.length) return direction
120 | direction = v == null ? v : d3.functor(v)
121 |
122 | return tip
123 | }
124 |
125 | // Public: Sets or gets the offset of the tip
126 | //
127 | // v - Array of [x, y] offset
128 | //
129 | // Returns offset or
130 | tip.offset = function(v) {
131 | if (!arguments.length) return offset
132 | offset = v == null ? v : d3.functor(v)
133 |
134 | return tip
135 | }
136 |
137 | // Public: sets or gets the html value of the tooltip
138 | //
139 | // v - String value of the tip
140 | //
141 | // Returns html value or tip
142 | tip.html = function(v) {
143 | if (!arguments.length) return html
144 | html = v == null ? v : d3.functor(v)
145 |
146 | return tip
147 | }
148 |
149 | // Public: destroys the tooltip and removes it from the DOM
150 | //
151 | // Returns a tip
152 | tip.destroy = function() {
153 | if(node) {
154 | getNodeEl().remove();
155 | node = null;
156 | }
157 | return tip;
158 | }
159 |
160 | function d3_tip_direction() { return 'n' }
161 | function d3_tip_offset() { return [0, 0] }
162 | function d3_tip_html() { return ' ' }
163 |
164 | var direction_callbacks = d3.map({
165 | n: direction_n,
166 | s: direction_s,
167 | e: direction_e,
168 | w: direction_w,
169 | nw: direction_nw,
170 | ne: direction_ne,
171 | sw: direction_sw,
172 | se: direction_se
173 | }),
174 |
175 | directions = direction_callbacks.keys()
176 |
177 | function direction_n() {
178 | var bbox = getScreenBBox()
179 | return {
180 | top: bbox.n.y - node.offsetHeight,
181 | left: bbox.n.x - node.offsetWidth / 2
182 | }
183 | }
184 |
185 | function direction_s() {
186 | var bbox = getScreenBBox()
187 | return {
188 | top: bbox.s.y,
189 | left: bbox.s.x - node.offsetWidth / 2
190 | }
191 | }
192 |
193 | function direction_e() {
194 | var bbox = getScreenBBox()
195 | return {
196 | top: bbox.e.y - node.offsetHeight / 2,
197 | left: bbox.e.x
198 | }
199 | }
200 |
201 | function direction_w() {
202 | var bbox = getScreenBBox()
203 | return {
204 | top: bbox.w.y - node.offsetHeight / 2,
205 | left: bbox.w.x - node.offsetWidth
206 | }
207 | }
208 |
209 | function direction_nw() {
210 | var bbox = getScreenBBox()
211 | return {
212 | top: bbox.nw.y - node.offsetHeight,
213 | left: bbox.nw.x - node.offsetWidth
214 | }
215 | }
216 |
217 | function direction_ne() {
218 | var bbox = getScreenBBox()
219 | return {
220 | top: bbox.ne.y - node.offsetHeight,
221 | left: bbox.ne.x
222 | }
223 | }
224 |
225 | function direction_sw() {
226 | var bbox = getScreenBBox()
227 | return {
228 | top: bbox.sw.y,
229 | left: bbox.sw.x - node.offsetWidth
230 | }
231 | }
232 |
233 | function direction_se() {
234 | var bbox = getScreenBBox()
235 | return {
236 | top: bbox.se.y,
237 | left: bbox.e.x
238 | }
239 | }
240 |
241 | function initNode() {
242 | var node = d3.select(document.createElement('div'))
243 | node.style({
244 | position: 'absolute',
245 | top: 0,
246 | opacity: 0,
247 | 'pointer-events': 'none',
248 | 'box-sizing': 'border-box'
249 | })
250 |
251 | return node.node()
252 | }
253 |
254 | function getSVGNode(el) {
255 | el = el.node()
256 | if(el.tagName.toLowerCase() === 'svg')
257 | return el
258 |
259 | return el.ownerSVGElement
260 | }
261 |
262 | function getNodeEl() {
263 | if(node === null) {
264 | node = initNode();
265 | // re-add node to DOM
266 | document.body.appendChild(node);
267 | };
268 | return d3.select(node);
269 | }
270 |
271 | // Private - gets the screen coordinates of a shape
272 | //
273 | // Given a shape on the screen, will return an SVGPoint for the directions
274 | // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
275 | // sw(southwest).
276 | //
277 | // +-+-+
278 | // | |
279 | // + +
280 | // | |
281 | // +-+-+
282 | //
283 | // Returns an Object {n, s, e, w, nw, sw, ne, se}
284 | function getScreenBBox() {
285 | var targetel = target || d3.event.target;
286 |
287 | while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
288 | targetel = targetel.parentNode;
289 | }
290 |
291 | var bbox = {},
292 | matrix = targetel.getScreenCTM(),
293 | tbbox = targetel.getBBox(),
294 | width = tbbox.width,
295 | height = tbbox.height,
296 | x = tbbox.x,
297 | y = tbbox.y
298 |
299 | point.x = x
300 | point.y = y
301 | bbox.nw = point.matrixTransform(matrix)
302 | point.x += width
303 | bbox.ne = point.matrixTransform(matrix)
304 | point.y += height
305 | bbox.se = point.matrixTransform(matrix)
306 | point.x -= width
307 | bbox.sw = point.matrixTransform(matrix)
308 | point.y -= height / 2
309 | bbox.w = point.matrixTransform(matrix)
310 | point.x += width
311 | bbox.e = point.matrixTransform(matrix)
312 | point.x -= width / 2
313 | point.y -= height / 2
314 | bbox.n = point.matrixTransform(matrix)
315 | point.y += height
316 | bbox.s = point.matrixTransform(matrix)
317 |
318 | return bbox
319 | }
320 |
321 | return tip
322 | };
323 |
324 | }));
325 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3-tip/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3-tip",
3 | "version": "0.6.8",
4 | "description": "Tooltips for d3 svg visualizations",
5 | "author": "Justin Palmer (http://labratrevenge.com/d3-tip)",
6 | "main": "index.js",
7 | "directories": {
8 | "doc": "docs",
9 | "example": "examples"
10 | },
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/Caged/d3-tip"
17 | },
18 | "keywords": [
19 | "d3",
20 | "tooltip"
21 | ],
22 | "license": "MIT",
23 | "bugs": {
24 | "url": "https://github.com/Caged/d3-tip/issues"
25 | },
26 | "homepage": "https://github.com/Caged/d3-tip",
27 | "dependencies": {
28 | "d3": "^3.5.5"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3",
3 | "description": "A JavaScript visualization library for HTML and SVG.",
4 | "main": "d3.js",
5 | "license": "BSD-3-Clause",
6 | "ignore": [],
7 | "homepage": "https://github.com/mbostock-bower/d3-bower",
8 | "version": "3.5.17",
9 | "_release": "3.5.17",
10 | "_resolution": {
11 | "type": "version",
12 | "tag": "v3.5.17",
13 | "commit": "abe0262a205c9f3755c3a757de4dfd1d49f34b24"
14 | },
15 | "_source": "https://github.com/mbostock-bower/d3-bower.git",
16 | "_target": "~3.5.5",
17 | "_originalSource": "d3"
18 | }
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2016, Michael Bostock
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * The name Michael Bostock may not be used to endorse or promote products
15 | derived from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3/README.md:
--------------------------------------------------------------------------------
1 | # Data-Driven Documents
2 |
3 |
4 |
5 | **D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG, and CSS. **D3** emphasizes web standards and combines powerful visualization components with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers without tying yourself to a proprietary framework.
6 |
7 | Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki)
8 |
9 | For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock).
10 |
11 | ## Good News, Everyone!
12 |
13 | The next major release of D3, 4.0, is coming! See the [4.0 development branch](https://github.com/mbostock/d3/tree/4) and read the [new API reference](https://github.com/mbostock/d3/blob/4/README.md) to get ready.
14 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/d3/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3",
3 | "description": "A JavaScript visualization library for HTML and SVG.",
4 | "main": "d3.js",
5 | "license": "BSD-3-Clause",
6 | "ignore": []
7 | }
8 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/lodash/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lodash",
3 | "main": "lodash.js",
4 | "ignore": [
5 | ".*",
6 | "*.custom.*",
7 | "*.log",
8 | "*.map",
9 | "*.md",
10 | "lodash.src.js",
11 | "component.json",
12 | "package.json",
13 | "doc",
14 | "node_modules",
15 | "perf",
16 | "test",
17 | "vendor"
18 | ],
19 | "homepage": "https://github.com/lodash/lodash",
20 | "version": "3.10.1",
21 | "_release": "3.10.1",
22 | "_resolution": {
23 | "type": "version",
24 | "tag": "3.10.1",
25 | "commit": "ef20b4290cc4fe7551c82a552ea7ffa76548eec8"
26 | },
27 | "_source": "https://github.com/lodash/lodash.git",
28 | "_target": "~3.10.1",
29 | "_originalSource": "lodash"
30 | }
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/lodash/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2012-2015 The Dojo Foundation
2 | Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,
3 | DocumentCloud and Investigative Reporters & Editors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/lodash/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lodash",
3 | "main": "lodash.js",
4 | "ignore": [
5 | ".*",
6 | "*.custom.*",
7 | "*.log",
8 | "*.map",
9 | "*.md",
10 | "lodash.src.js",
11 | "component.json",
12 | "package.json",
13 | "doc",
14 | "node_modules",
15 | "perf",
16 | "test",
17 | "vendor"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/bower_components/lodash/lodash.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * lodash 3.10.1 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
4 | * Build: `lodash modern -o ./lodash.js`
5 | */
6 | ;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===w,u=n===n,o=null===t,i=t===w,f=t===t;if(n>t&&!o||!u||r&&!i&&f||e&&f)return 1;if(n=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n);
8 | }function v(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r=F&&gu&&lu?new Dn(t):null,c=t.length;a&&(i=Mn,f=false,t=a);n:for(;++oi(t,a,0)&&u.push(a);return u}function at(n,t){var r=true;return Su(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,o=u;return Su(n,function(n,i,f){i=+t(n,i,f),(r(i,u)||i===e&&i===o)&&(u=i,
14 | o=n)}),o}function lt(n,t){var r=[];return Su(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function st(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function pt(n,t,r,e){e||(e=[]);for(var u=-1,o=n.length;++ut&&(t=-t>u?0:u+t),r=r===w||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Be(u);++e=c)break n;o=e[o],u*="asc"===o||true===o?1:-1;break n}u=t.b-r.b}return u})}function $t(n,t){
21 | var r=0;return Su(n,function(n,e,u){r+=+t(n,e,u)||0}),r}function St(n,t){var e=-1,u=xr(),o=n.length,i=u===r,f=i&&o>=F,a=f&&gu&&lu?new Dn(void 0):null,c=[];a?(u=Mn,i=false):(f=false,a=t?[]:c);n:for(;++eu(a,s,0)&&((t||f)&&a.push(s),c.push(l))}return c}function Ft(n,t){for(var r=-1,e=t.length,u=Be(e);++r>>1,i=n[o];(r?i<=t:iu?w:o,u=1);++e=F)return t.plant(e).value();for(var u=0,n=r?o[u].apply(this,n):e;++uarguments.length;return typeof e=="function"&&o===w&&Oo(r)?n(r,e,u,i):Ot(r,wr(e,o,4),u,i,t)}}function sr(n,t,r,e,u,o,i,f,a,c){function l(){for(var m=arguments.length,b=m,j=Be(m);b--;)j[b]=arguments[b];if(e&&(j=Mt(j,e,u)),o&&(j=qt(j,o,i)),_||y){var b=l.placeholder,k=v(j,b),m=m-k.length;if(mt?0:t)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0,0>t?0:t)):[]}function Kr(n){return n?n[0]:w}function Vr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e=="number")e=0>e?bu(u+e,0):e;else if(e)return e=Lt(n,t),
42 | er?bu(u+r,0):r||0,typeof n=="string"||!Oo(n)&&be(n)?r<=u&&-1t?0:+t||0,e);++r=n&&(t=w),r}}function ae(n,t,r){function e(t,r){r&&iu(r),a=p=h=w,t&&(_=ho(),c=n.apply(s,f),p||a||(f=s=w))}function u(){var n=t-(ho()-l);0>=n||n>t?e(h,a):p=su(u,n)}function o(){e(g,p);
46 | }function i(){if(f=arguments,l=ho(),s=this,h=g&&(p||!y),false===v)var r=y&&!p;else{a||y||(_=l);var e=v-(l-_),i=0>=e||e>v;i?(a&&(a=iu(a)),_=l,c=n.apply(s,f)):a||(a=su(o,e))}return i&&p?p=iu(p):p||t===v||(p=su(u,t)),r&&(i=true,c=n.apply(s,f)),!i||p||a||(f=s=w),c}var f,a,c,l,s,p,h,_=0,v=false,g=true;if(typeof n!="function")throw new Ge(L);if(t=0>t?0:+t||0,true===r)var y=true,g=false;else ge(r)&&(y=!!r.leading,v="maxWait"in r&&bu(+r.maxWait||0,t),g="trailing"in r?!!r.trailing:g);return i.cancel=function(){p&&iu(p),a&&iu(a),
47 | _=0,a=p=h=w},i}function ce(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)}if(typeof n!="function"||t&&typeof t!="function")throw new Ge(L);return r.cache=new ce.Cache,r}function le(n,t){if(typeof n!="function")throw new Ge(L);return t=bu(t===w?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=bu(r.length-t,0),o=Be(u);++et}function pe(n){return h(n)&&Er(n)&&nu.call(n,"callee")&&!cu.call(n,"callee")}function he(n,t,r,e){return e=(r=typeof r=="function"?Bt(r,e,3):w)?r(n,t):w,e===w?dt(n,t,r):!!e}function _e(n){return h(n)&&typeof n.message=="string"&&ru.call(n)==P}function ve(n){return ge(n)&&ru.call(n)==K}function ge(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function ye(n){
49 | return null==n?false:ve(n)?uu.test(Qe.call(n)):h(n)&&Rn.test(n)}function de(n){return typeof n=="number"||h(n)&&ru.call(n)==V}function me(n){var t;if(!h(n)||ru.call(n)!=Z||pe(n)||!(nu.call(n,"constructor")||(t=n.constructor,typeof t!="function"||t instanceof t)))return false;var r;return ht(n,function(n,t){r=t}),r===w||nu.call(n,r)}function we(n){return ge(n)&&ru.call(n)==Y}function be(n){return typeof n=="string"||h(n)&&ru.call(n)==G}function xe(n){return h(n)&&Sr(n.length)&&!!Sn[ru.call(n)]}function Ae(n,t){
50 | return nt||!n||!mu(t))return r;do t%2&&(r+=n),t=yu(t/2),n+=n;while(t);return r}function We(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(g(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,r){return r&&Ur(n,t,r)&&(t=w),n=u(n),n.match(t||Wn)||[]}function Se(n,t,r){return r&&Ur(n,t,r)&&(t=w),h(n)?Ne(n):ut(n,t)}function Fe(n){
52 | return n}function Ne(n){return bt(ot(n,true))}function Te(n,t,r){if(null==r){var e=ge(t),u=e?zo(t):w;((u=u&&u.length?gt(t,u):w)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=gt(t,zo(t)));var o=true,e=-1,i=ve(n),f=u.length;false===r?o=false:ge(r)&&"chain"in r&&(o=r.chain);for(;++e=$)return r}else n=0;return Lu(r,e)}}(),Mu=le(function(n,t){
55 | return h(n)&&Er(n)?ft(n,pt(t,false,true)):[]}),qu=tr(),Pu=tr(true),Ku=le(function(n){for(var t=n.length,e=t,u=Be(l),o=xr(),i=o===r,f=[];e--;){var a=n[e]=Er(a=n[e])?a:[];u[e]=i&&120<=a.length&&gu&&lu?new Dn(e&&a):null}var i=n[0],c=-1,l=i?i.length:0,s=u[0];n:for(;++c(s?Mn(s,a):o(f,a,0))){for(e=t;--e;){var p=u[e];if(0>(p?Mn(p,a):o(n[e],a,0)))continue n}s&&s.push(a),f.push(a)}return f}),Vu=le(function(t,r){r=pt(r);var e=rt(t,r);return It(t,r.sort(n)),e}),Zu=vr(),Yu=vr(true),Gu=le(function(n){return St(pt(n,false,true));
56 | }),Ju=le(function(n,t){return Er(n)?ft(n,t):[]}),Xu=le(Jr),Hu=le(function(n){var t=n.length,r=2--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Ur(n,t,r)&&(t=w),t=n&&null==t?n.length:bu(+t||0,0),gr(n,E,w,w,w,w,t)},Nn.assign=Co,Nn.at=no,Nn.before=fe,Nn.bind=_o,Nn.bindAll=vo,Nn.bindKey=go,Nn.callback=Se,Nn.chain=Qr,Nn.chunk=function(n,t,r){t=(r?Ur(n,t,r):null==t)?1:bu(yu(t)||1,1),r=0;for(var e=n?n.length:0,u=-1,o=Be(vu(e/t));rr&&(r=-r>u?0:u+r),e=e===w||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;rt?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){
71 | return n&&n.length?Nt(n,wr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3)):[]},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new Ge(L);return false===r?e=false:ge(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ae(n,t,{leading:e,maxWait:+t,trailing:u})},Nn.thru=ne,Nn.times=function(n,t,r){if(n=yu(n),1>n||!mu(n))return[];var e=-1,u=Be(xu(n,4294967295));for(t=Bt(t,r,1);++ee?u[e]=t(e):t(e);
72 | return u},Nn.toArray=je,Nn.toPlainObject=ke,Nn.transform=function(n,t,r,e){var u=Oo(n)||xe(n);return t=wr(t,e,4),null==r&&(u||ge(n)?(e=n.constructor,r=u?Oo(n)?new e:[]:$u(ve(e)?e.prototype:w)):r={}),(u?Pn:_t)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=Gu,Nn.uniq=Gr,Nn.unzip=Jr,Nn.unzipWith=Xr,Nn.values=Ee,Nn.valuesIn=function(n){return Ft(n,Re(n))},Nn.where=function(n,t){return re(n,bt(t))},Nn.without=Ju,Nn.wrap=function(n,t){return t=null==t?Fe:t,gr(t,R,w,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++nr?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&hn.test(n)?n.replace(sn,c):n},Nn.escapeRegExp=function(n){return(n=u(n))&&bn.test(n)?n.replace(wn,l):n||"(?:)"},Nn.every=te,Nn.find=ro,Nn.findIndex=qu,Nn.findKey=$o,Nn.findLast=eo,
75 | Nn.findLastIndex=Pu,Nn.findLastKey=So,Nn.findWhere=function(n,t){return ro(n,bt(t))},Nn.first=Kr,Nn.floor=ni,Nn.get=function(n,t,r){return n=null==n?w:yt(n,Dr(t),t+""),n===w?r:n},Nn.gt=se,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=nu.call(n,t);if(!r&&!Wr(t)){if(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),null==n)return false;t=Zr(t),r=nu.call(n,t)}return r||Sr(n.length)&&Cr(t,n.length)&&(Oo(n)||pe(n))},Nn.identity=Fe,Nn.includes=ee,Nn.indexOf=Vr,Nn.inRange=function(n,t,r){
76 | return t=+t||0,r===w?(r=t,t=0):r=+r||0,n>=xu(t,r)&&nr?bu(e+r,0):xu(r||0,e-1))+1;else if(r)return u=Lt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1;
78 | if(t!==t)return p(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=Ae,Nn.lte=function(n,t){return n<=t},Nn.max=ti,Nn.min=ri,Nn.noConflict=function(){return Zn._=eu,this},Nn.noop=Le,Nn.now=ho,Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return er?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){if(r&&Ur(n,t,r)&&(t=w),t=wr(t,r,3),1==t.length){n=Oo(n)?n:zr(n),r=n.length;for(var e=0;r--;)e+=+t(n[r])||0;n=e}else n=$t(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Ur(n,t,r)&&(t=r=w),n=u(n),t=nt(tt({},r||t),e,Qn),r=nt(tt({},t.imports),e.imports,Qn);
81 | var o,i,f=zo(r),a=Ft(r,f),c=0;r=t.interpolate||Cn;var l="__p+='";r=Ze((t.escape||Cn).source+"|"+r.source+"|"+(r===gn?jn:Cn).source+"|"+(t.evaluate||Cn).source+"|$","g");var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,f,a){return e||(e=u),l+=n.slice(c,a).replace(Un,s),r&&(o=true,l+="'+__e("+r+")+'"),f&&(i=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),c=a+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(i?l.replace(fn,""):l).replace(an,"$1").replace(cn,"$1;"),
82 | l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(o?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Jo(function(){return qe(f,p+"return "+l).apply(w,a)}),t.source=l,_e(t))throw t;return t},Nn.trim=We,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Ur(e,t,r):null==t)?g(n):o(n,t+"")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n;
83 | },Nn.trunc=function(n,t,r){r&&Ur(n,t,r)&&(t=w);var e=U;if(r=W,null!=t)if(ge(t)){var o="separator"in t?t.separator:o,e="length"in t?+t.length||0:e;r="omission"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length,1>e)return r;if(t=n.slice(0,e),null==o)return t+r;if(we(o)){if(n.slice(e).search(o)){var i,f=n.slice(0,e);for(o.global||(o=Ze(o.source,(kn.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(f);)i=n.index;t=t.slice(0,null==i?e:i)}}else n.indexOf(o,e)!=e&&(o=t.lastIndexOf(o),
84 | -1u.__dir__?"Right":"")}),u},zn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Pn(["filter","map","takeWhile"],function(n,t){
86 | var r=t+1,e=r!=T;zn.prototype[n]=function(n,t){var u=this.clone();return u.__iteratees__.push({iteratee:wr(n,t,1),type:r}),u.__filtered__=u.__filtered__||e,u}}),Pn(["first","last"],function(n,t){var r="take"+(t?"Right":"");zn.prototype[n]=function(){return this[r](1).value()[0]}}),Pn(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");zn.prototype[n]=function(){return this.__filtered__?new zn(this):this[r](1)}}),Pn(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?bt:ze;zn.prototype[n]=function(n){
87 | return this[r](e(n))}}),zn.prototype.compact=function(){return this.filter(Fe)},zn.prototype.reject=function(n,t){return n=wr(n,t,1),this.filter(function(t){return!n(t)})},zn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return r.__filtered__&&(0t)?new zn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==w&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r)},zn.prototype.takeRightWhile=function(n,t){return this.reverse().takeWhile(n,t).reverse()},zn.prototype.toArray=function(){return this.take(Ru);
88 | },_t(zn.prototype,function(n,t){var r=/^(?:filter|map|reject)|While$/.test(t),e=/^(?:first|last)$/.test(t),u=Nn[e?"take"+("last"==t?"Right":""):t];u&&(Nn.prototype[t]=function(){function t(n){return e&&i?u(n,1)[0]:u.apply(w,Jn([n],o))}var o=e?[1]:arguments,i=this.__chain__,f=this.__wrapped__,a=!!this.__actions__.length,c=f instanceof zn,l=o[0],s=c||Oo(f);return s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false),l={func:ne,args:[t],thisArg:w},a=c&&!a,e&&!i?a?(f=f.clone(),f.__actions__.push(l),n.call(f)):u.call(w,this.value())[0]:!e&&s?(f=a?f:new zn(this),
89 | f=n.apply(f,o),f.__actions__.push(l),new Ln(f,i)):this.thru(t)})}),Pn("join pop push replace shift sort splice split unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?He:Je)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),_t(zn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name+"";(Wu[e]||(Wu[e]=[])).push({
90 | name:t,func:r})}}),Wu[sr(w,A).name]=[{name:"wrapper",func:w}],zn.prototype.clone=function(){var n=new zn(this.__wrapped__);return n.__actions__=qn(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=qn(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=qn(this.__views__),n},zn.prototype.reverse=function(){if(this.__filtered__){var n=new zn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},zn.prototype.value=function(){
91 | var n,t=this.__wrapped__.value(),r=this.__dir__,e=Oo(t),u=0>r,o=e?t.length:0;n=o;for(var i=this.__views__,f=0,a=-1,c=i.length;++a"'`]/g,pn=RegExp(ln.source),hn=RegExp(sn.source),_n=/<%-([\s\S]+?)%>/g,vn=/<%([\s\S]+?)%>/g,gn=/<%=([\s\S]+?)%>/g,yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,dn=/^\w*$/,mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,wn=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,bn=RegExp(wn.source),xn=/[\u0300-\u036f\ufe20-\ufe23]/g,An=/\\(\\)?/g,jn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,kn=/\w*$/,In=/^0[xX]/,Rn=/^\[object .+?Constructor\]$/,On=/^\d+$/,En=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Cn=/($^)/,Un=/['\n\r\u2028\u2029\\]/g,Wn=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?=[A-Z\\xc0-\\xd6\\xd8-\\xde][a-z\\xdf-\\xf6\\xf8-\\xff]+)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|[0-9]+","g"),$n="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap".split(" "),Sn={};
94 | Sn[X]=Sn[H]=Sn[Q]=Sn[nn]=Sn[tn]=Sn[rn]=Sn[en]=Sn[un]=Sn[on]=true,Sn[B]=Sn[D]=Sn[J]=Sn[M]=Sn[q]=Sn[P]=Sn[K]=Sn["[object Map]"]=Sn[V]=Sn[Z]=Sn[Y]=Sn["[object Set]"]=Sn[G]=Sn["[object WeakMap]"]=false;var Fn={};Fn[B]=Fn[D]=Fn[J]=Fn[M]=Fn[q]=Fn[X]=Fn[H]=Fn[Q]=Fn[nn]=Fn[tn]=Fn[V]=Fn[Z]=Fn[Y]=Fn[G]=Fn[rn]=Fn[en]=Fn[un]=Fn[on]=true,Fn[P]=Fn[K]=Fn["[object Map]"]=Fn["[object Set]"]=Fn["[object WeakMap]"]=false;var Nn={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a",
95 | "\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y",
96 | "\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"},Tn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Ln={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},zn={"function":true,object:true},Bn={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"},Dn={"\\":"\\",
97 | "'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mn=zn[typeof exports]&&exports&&!exports.nodeType&&exports,qn=zn[typeof module]&&module&&!module.nodeType&&module,Pn=zn[typeof self]&&self&&self.Object&&self,Kn=zn[typeof window]&&window&&window.Object&&window,Vn=qn&&qn.exports===Mn&&Mn,Zn=Mn&&qn&&typeof global=="object"&&global&&global.Object&&global||Kn!==(this&&this.window)&&Kn||Pn||this,Yn=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=Yn, define(function(){
98 | return Yn})):Mn&&qn?Vn?(qn.exports=Yn)._=Yn:Mn._=Yn:Zn._=Yn}).call(this);
--------------------------------------------------------------------------------
/js/d3-flame-graph/src/d3.flameGraph.css:
--------------------------------------------------------------------------------
1 | .d3-flame-graph rect {
2 | stroke: #EEEEEE;
3 | fill-opacity: .8;
4 | }
5 |
6 | .d3-flame-graph rect:hover {
7 | stroke: #474747;
8 | stroke-width: 0.5;
9 | cursor: pointer;
10 | }
11 |
12 | .d3-flame-graph .label {
13 | pointer-events: none;
14 | white-space: nowrap;
15 | text-overflow: ellipsis;
16 | overflow: hidden;
17 | font-size: 12px;
18 | font-family: Verdana;
19 | margin-left: 4px;
20 | margin-right: 4px;
21 | line-height: 1.5;
22 | padding: 0 0 0;
23 | font-weight: 400;
24 | color: black;
25 | text-align: left;
26 | }
27 |
28 | .d3-flame-graph .fade {
29 | opacity: 0.6 !important;
30 | }
31 |
32 | .d3-flame-graph .title {
33 | font-size: 20px;
34 | font-family: Verdana;
35 | }
36 |
37 | .d3-flame-graph-tip {
38 | line-height: 1;
39 | font-family: Verdana;
40 | font-size: 12px;
41 | padding: 12px;
42 | background: rgba(0, 0, 0, 0.8);
43 | color: #fff;
44 | z-index: 9999;
45 | border-radius: 2px;
46 | pointer-events: none;
47 | }
48 |
49 | /* Creates a small triangle extender for the tooltip */
50 | .d3-flame-graph-tip:after {
51 | box-sizing: border-box;
52 | display: inline;
53 | font-size: 10px;
54 | width: 100%;
55 | line-height: 1;
56 | color: rgba(0, 0, 0, 0.8);
57 | position: absolute;
58 | pointer-events: none;
59 | }
60 |
61 | /* Northward tooltips */
62 | .d3-flame-graph-tip.n:after {
63 | content: "\25BC";
64 | margin: -1px 0 0 0;
65 | top: 100%;
66 | left: 0;
67 | text-align: center;
68 | }
69 |
70 | /* Eastward tooltips */
71 | .d3-flame-graph-tip.e:after {
72 | content: "\25C0";
73 | margin: -4px 0 0 0;
74 | top: 50%;
75 | left: -8px;
76 | }
77 |
78 | /* Southward tooltips */
79 | .d3-flame-graph-tip.s:after {
80 | content: "\25B2";
81 | margin: 0 0 1px 0;
82 | top: -8px;
83 | left: 0;
84 | text-align: center;
85 | }
86 |
87 | /* Westward tooltips */
88 | .d3-flame-graph-tip.w:after {
89 | content: "\25B6";
90 | margin: -4px 0 0 -1px;
91 | top: 50%;
92 | left: 100%;
93 | }
94 |
--------------------------------------------------------------------------------
/js/d3-flame-graph/src/d3.flameGraph.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | function flameGraph() {
5 |
6 | var w = 960, // graph width
7 | h = 540, // graph height
8 | c = 18, // cell height
9 | selection = null, // selection
10 | tooltip = true, // enable tooltip
11 | title = "", // graph title
12 | transitionDuration = 750,
13 | transitionEase = "cubic-in-out", // tooltip offset
14 | sort = true,
15 | reversed = false, // reverse the graph direction
16 | clickHandler = null;
17 |
18 | var tip = d3.tip()
19 | .direction("s")
20 | .offset([8, 0])
21 | .attr('class', 'd3-flame-graph-tip')
22 | .html(function(d) { return label(d); });
23 |
24 | var labelFormat = function(d) {
25 | return d.name + " (" + d3.round(100 * d.dx, 3) + "%, " + d.value + " samples)";
26 | };
27 |
28 | function setDetails(t) {
29 | var details = document.getElementById("details");
30 | if (details)
31 | details.innerHTML = t;
32 | }
33 |
34 | function label(d) {
35 | if (!d.dummy) {
36 | return labelFormat(d);
37 | } else {
38 | return "";
39 | }
40 | }
41 |
42 | function name(d) {
43 | return d.name;
44 | }
45 |
46 | var colorMapper = function(d) {
47 | return d.highlight ? "#E600E6" : colorHash(d.name);
48 | };
49 |
50 | function generateHash(name) {
51 | // Return a vector (0.0->1.0) that is a hash of the input string.
52 | // The hash is computed to favor early characters over later ones, so
53 | // that strings with similar starts have similar vectors. Only the first
54 | // 6 characters are considered.
55 | var hash = 0, weight = 1, max_hash = 0, mod = 10, max_char = 6;
56 | if (name) {
57 | for (var i = 0; i < name.length; i++) {
58 | if (i > max_char) { break; }
59 | hash += weight * (name.charCodeAt(i) % mod);
60 | max_hash += weight * (mod - 1);
61 | weight *= 0.70;
62 | }
63 | if (max_hash > 0) { hash = hash / max_hash; }
64 | }
65 | return hash;
66 | }
67 |
68 | function colorHash(name) {
69 | // Return an rgb() color string that is a hash of the provided name,
70 | // and with a warm palette.
71 | var vector = 0;
72 | if (name) {
73 | name = name.replace(/.*`/, ""); // drop module name if present
74 | name = name.replace(/\(.*/, ""); // drop extra info
75 | vector = generateHash(name);
76 | }
77 | var r = 200 + Math.round(55 * vector);
78 | var g = 0 + Math.round(230 * (1 - vector));
79 | var b = 0 + Math.round(55 * (1 - vector));
80 | return "rgb(" + r + "," + g + "," + b + ")";
81 | }
82 |
83 | function augment(data) {
84 | // Augment partitioning layout with "dummy" nodes so that internal nodes'
85 | // values dictate their width. Annoying, but seems to be least painful
86 | // option. https://github.com/mbostock/d3/pull/574
87 | if (data.children && (data.children.length > 0)) {
88 | data.children.forEach(augment);
89 | var childValues = 0;
90 | data.children.forEach(function(child) {
91 | childValues += child.value;
92 | });
93 | if (childValues < data.value) {
94 | data.children.push(
95 | {
96 | "name": "",
97 | "value": data.value - childValues,
98 | "dummy": true
99 | }
100 | );
101 | }
102 | }
103 | }
104 |
105 | function hide(d) {
106 | if(!d.original) {
107 | d.original = d.value;
108 | }
109 | d.value = 0;
110 | if(d.children) {
111 | d.children.forEach(hide);
112 | }
113 | }
114 |
115 | function show(d) {
116 | d.fade = false;
117 | if(d.original) {
118 | d.value = d.original;
119 | }
120 | if(d.children) {
121 | d.children.forEach(show);
122 | }
123 | }
124 |
125 | function getSiblings(d) {
126 | var siblings = [];
127 | if (d.parent) {
128 | var me = d.parent.children.indexOf(d);
129 | siblings = d.parent.children.slice(0);
130 | siblings.splice(me, 1);
131 | }
132 | return siblings;
133 | }
134 |
135 | function hideSiblings(d) {
136 | var siblings = getSiblings(d);
137 | siblings.forEach(function(s) {
138 | hide(s);
139 | });
140 | if(d.parent) {
141 | hideSiblings(d.parent);
142 | }
143 | }
144 |
145 | function fadeAncestors(d) {
146 | if(d.parent) {
147 | d.parent.fade = true;
148 | fadeAncestors(d.parent);
149 | }
150 | }
151 |
152 | function getRoot(d) {
153 | if(d.parent) {
154 | return getRoot(d.parent);
155 | }
156 | return d;
157 | }
158 |
159 | function zoom(d) {
160 | tip.hide(d);
161 | hideSiblings(d);
162 | show(d);
163 | fadeAncestors(d);
164 | update();
165 | if (typeof clickHandler === 'function') {
166 | clickHandler(d);
167 | }
168 | }
169 |
170 | function searchTree(d, term) {
171 | var re = new RegExp(term),
172 | searchResults = [];
173 |
174 | function searchInner(d) {
175 | var label = d.name;
176 |
177 | if (d.children) {
178 | d.children.forEach(function (child) {
179 | searchInner(child);
180 | });
181 | }
182 |
183 | if (label.match(re)) {
184 | d.highlight = true;
185 | searchResults.push(d);
186 | } else {
187 | d.highlight = false;
188 | }
189 | }
190 |
191 | searchInner(d);
192 | return searchResults;
193 | }
194 |
195 | function clear(d) {
196 | d.highlight = false;
197 | if(d.children) {
198 | d.children.forEach(function(child) {
199 | clear(child);
200 | });
201 | }
202 | }
203 |
204 | function doSort(a, b) {
205 | if (typeof sort === 'function') {
206 | return sort(a, b);
207 | } else if (sort) {
208 | return d3.ascending(a.name, b.name);
209 | } else {
210 | return 0;
211 | }
212 | }
213 |
214 | var partition = d3.layout.partition()
215 | .sort(doSort)
216 | .value(function(d) {return d.v || d.value;})
217 | .children(function(d) {return d.c || d.children;});
218 |
219 | function update() {
220 |
221 | selection.each(function(data) {
222 |
223 | var x = d3.scale.linear().range([0, w]),
224 | y = d3.scale.linear().range([0, c]);
225 |
226 | var nodes = partition(data);
227 |
228 | var kx = w / data.dx;
229 |
230 | var g = d3.select(this).select("svg").selectAll("g").data(nodes);
231 |
232 | g.transition()
233 | .duration(transitionDuration)
234 | .ease(transitionEase)
235 | .attr("transform", function(d) { return "translate(" + x(d.x) + ","
236 | + (reversed ? y(d.depth) : (h - y(d.depth) - c)) + ")"; });
237 |
238 | g.select("rect").transition()
239 | .duration(transitionDuration)
240 | .ease(transitionEase)
241 | .attr("width", function(d) { return d.dx * kx; });
242 |
243 | var node = g.enter()
244 | .append("svg:g")
245 | .attr("transform", function(d) { return "translate(" + x(d.x) + ","
246 | + (reversed ? y(d.depth) : (h - y(d.depth) - c)) + ")"; });
247 |
248 | node.append("svg:rect")
249 | .attr("width", function(d) { return d.dx * kx; });
250 |
251 | if (!tooltip)
252 | node.append("svg:title");
253 |
254 | node.append("foreignObject")
255 | .append("xhtml:div");
256 |
257 | g.attr("width", function(d) { return d.dx * kx; })
258 | .attr("height", function(d) { return c; })
259 | .attr("name", function(d) { return d.name; })
260 | .attr("class", function(d) { return d.fade ? "frame fade" : "frame"; });
261 |
262 | g.select("rect")
263 | .attr("height", function(d) { return c; })
264 | .attr("fill", function(d) { return colorMapper(d); })
265 | .style("visibility", function(d) {return d.dummy ? "hidden" : "visible";});
266 |
267 | if (!tooltip)
268 | g.select("title")
269 | .text(label);
270 |
271 | g.select("foreignObject")
272 | .attr("width", function(d) { return d.dx * kx; })
273 | .attr("height", function(d) { return c; })
274 | .select("div")
275 | .attr("class", "label")
276 | .style("display", function(d) { return (d.dx * kx < 35) || d.dummy ? "none" : "block";})
277 | .text(name);
278 |
279 | g.on('click', zoom);
280 |
281 | g.exit().remove();
282 |
283 | g.on('mouseover', function(d) {
284 | if(!d.dummy) {
285 | if (tooltip) tip.show(d);
286 | setDetails(label(d));
287 | }
288 | }).on('mouseout', function(d) {
289 | if(!d.dummy) {
290 | if (tooltip) tip.hide(d);
291 | setDetails("");
292 | }
293 | });
294 | });
295 | }
296 |
297 | function merge(data, samples) {
298 | samples.forEach(function (sample) {
299 | var node = _.find(data, function (element) {
300 | return element.name === sample.name;
301 | });
302 |
303 | if (node) {
304 | node.value += sample.value;
305 | if (sample.children) {
306 | if (!node.children) {
307 | node.children = [];
308 | }
309 | merge(node.children, sample.children)
310 | }
311 | } else {
312 | data.push(sample);
313 | }
314 | });
315 | }
316 |
317 | function chart(s) {
318 |
319 | selection = s;
320 |
321 | if (!arguments.length) return chart;
322 |
323 | selection.each(function(data) {
324 |
325 | var svg = d3.select(this)
326 | .append("svg:svg")
327 | .attr("width", w)
328 | .attr("height", h)
329 | .attr("class", "partition d3-flame-graph")
330 | .call(tip);
331 |
332 | svg.append("svg:text")
333 | .attr("class", "title")
334 | .attr("text-anchor", "middle")
335 | .attr("y", "25")
336 | .attr("x", w/2)
337 | .attr("fill", "#808080")
338 | .text(title);
339 |
340 | augment(data);
341 |
342 | // "creative" fix for node ordering when partition is called for the first time
343 | partition(data);
344 |
345 | });
346 |
347 | // first draw
348 | update();
349 | }
350 |
351 | chart.height = function (_) {
352 | if (!arguments.length) { return h; }
353 | h = _;
354 | return chart;
355 | };
356 |
357 | chart.width = function (_) {
358 | if (!arguments.length) { return w; }
359 | w = _;
360 | return chart;
361 | };
362 |
363 | chart.cellHeight = function (_) {
364 | if (!arguments.length) { return c; }
365 | c = _;
366 | return chart;
367 | };
368 |
369 | chart.tooltip = function (_) {
370 | if (!arguments.length) { return tooltip; }
371 | if (typeof _ === "function") {
372 | tip = _;
373 | }
374 | tooltip = true;
375 | return chart;
376 | };
377 |
378 | chart.title = function (_) {
379 | if (!arguments.length) { return title; }
380 | title = _;
381 | return chart;
382 | };
383 |
384 | chart.transitionDuration = function (_) {
385 | if (!arguments.length) { return transitionDuration; }
386 | transitionDuration = _;
387 | return chart;
388 | };
389 |
390 | chart.transitionEase = function (_) {
391 | if (!arguments.length) { return transitionEase; }
392 | transitionEase = _;
393 | return chart;
394 | };
395 |
396 | chart.sort = function (_) {
397 | if (!arguments.length) { return sort; }
398 | sort = _;
399 | return chart;
400 | };
401 |
402 | chart.reversed = function (_) {
403 | if (!arguments.length) { return reversed; }
404 | reversed = _;
405 | return chart;
406 | };
407 |
408 | chart.label = function(_) {
409 | if (!arguments.length) { return labelFormat; }
410 | labelFormat = _;
411 | return chart;
412 | };
413 |
414 | chart.search = function(term) {
415 | var searchResults = [];
416 | selection.each(function(data) {
417 | searchResults = searchTree(data, term);
418 | update();
419 | });
420 | return searchResults;
421 | };
422 |
423 | chart.clear = function() {
424 | selection.each(function(data) {
425 | clear(data);
426 | update();
427 | });
428 | };
429 |
430 | chart.zoomTo = function(d) {
431 | zoom(d);
432 | };
433 |
434 | chart.resetZoom = function() {
435 | selection.each(function (data) {
436 | zoom(data); // zoom to root
437 | });
438 | };
439 |
440 | chart.onClick = function(_) {
441 | if (!arguments.length) {
442 | return clickHandler;
443 | }
444 | clickHandler = _;
445 | return chart;
446 | };
447 |
448 | chart.merge = function(samples) {
449 | selection.each(function (data) {
450 | merge([data], [samples]);
451 | augment(data);
452 | });
453 | update();
454 | }
455 |
456 | chart.color = function(_) {
457 | if (!arguments.length) { return colorMapper; }
458 | colorMapper = _;
459 | return chart;
460 | };
461 |
462 | return chart;
463 | }
464 |
465 | if (typeof module !== 'undefined' && module.exports){
466 | module.exports = flameGraph;
467 | }
468 | else {
469 | d3.flameGraph = flameGraph;
470 | }
471 | })();
472 |
--------------------------------------------------------------------------------
/query-monitor-flamegraph.php:
--------------------------------------------------------------------------------
1 |