flamegraph 0.0.5 → 0.0.6
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/CHANGELOG +6 -0
 - data/Gemfile +4 -0
 - data/Guardfile +1 -1
 - data/lib/flamegraph.rb +27 -4
 - data/lib/flamegraph/flamegraph.html +146 -7
 - data/lib/flamegraph/renderer.rb +4 -3
 - data/lib/flamegraph/stackprof_sampler.rb +42 -0
 - data/lib/flamegraph/version.rb +1 -1
 - data/test/test_stackprof_sampler.rb +36 -0
 - metadata +21 -18
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: f613760265ad137dae994ad575e5d90397506e1f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: b0b4968018697e4308746c72a7f0b9ac88fce97a
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 046ab66a7a510a2f9bd69da94e0b6c610d00e53a73ee3d98e38298075507fc73511fe92d4736c50253e957c8e453da5f9ea174d2577a21bb324a2466db030d03
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: b8346b54a13bf842a3a584a1f6149a0467b904b1a53d2c72720031c63c42b40268d1b38c4e2c9746c47276fcd5045c98e013c93eae3a27d977f60a7a19155bc4
         
     | 
    
        data/CHANGELOG
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/Guardfile
    CHANGED
    
    
    
        data/lib/flamegraph.rb
    CHANGED
    
    | 
         @@ -1,5 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "json"
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            if RUBY_VERSION >= "2.1.0".freeze
         
     | 
| 
      
 4 
     | 
    
         
            +
              begin
         
     | 
| 
      
 5 
     | 
    
         
            +
                require "stackprof"
         
     | 
| 
      
 6 
     | 
    
         
            +
                require "flamegraph/stackprof_sampler"
         
     | 
| 
      
 7 
     | 
    
         
            +
              rescue
         
     | 
| 
      
 8 
     | 
    
         
            +
                STDERR.puts "Please require the stackprof gem falling back to fast_stack"
         
     | 
| 
      
 9 
     | 
    
         
            +
                require "fast_stack"
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
            else
         
     | 
| 
      
 12 
     | 
    
         
            +
              begin
         
     | 
| 
      
 13 
     | 
    
         
            +
                require "fast_stack"
         
     | 
| 
      
 14 
     | 
    
         
            +
              rescue
         
     | 
| 
      
 15 
     | 
    
         
            +
                STDERR.puts "Please require the fast_stack gem, note flamegraph is only supported on Ruby 2.0 and above"
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       3 
19 
     | 
    
         
             
            require "flamegraph/version"
         
     | 
| 
       4 
20 
     | 
    
         
             
            require "flamegraph/renderer"
         
     | 
| 
       5 
21 
     | 
    
         | 
| 
         @@ -7,9 +23,16 @@ module Flamegraph 
     | 
|
| 
       7 
23 
     | 
    
         
             
              def self.generate(filename=nil, opts = {})
         
     | 
| 
       8 
24 
     | 
    
         
             
                fidelity = opts[:fidelity]  || 0.5
         
     | 
| 
       9 
25 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                backtraces = 
     | 
| 
       11 
     | 
    
         
            -
                   
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                backtraces =
         
     | 
| 
      
 27 
     | 
    
         
            +
                  if defined? StackProf
         
     | 
| 
      
 28 
     | 
    
         
            +
                    StackProfSampler.collect(fidelity) do
         
     | 
| 
      
 29 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  else
         
     | 
| 
      
 32 
     | 
    
         
            +
                    FastStack.profile(fidelity) do # , opts[:mode] || :ruby) do
         
     | 
| 
      
 33 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
       13 
36 
     | 
    
         | 
| 
       14 
37 
     | 
    
         
             
                embed_resources = (filename && !opts.key?(:embed_resources)) || opts[:embed_resources]
         
     | 
| 
       15 
38 
     | 
    
         | 
| 
         @@ -7,7 +7,7 @@ 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            <title>Flame Graph of Page</title>
         
     | 
| 
       9 
9 
     | 
    
         
             
            <style>
         
     | 
| 
       10 
     | 
    
         
            -
              .info {height:  
     | 
| 
      
 10 
     | 
    
         
            +
              .info {min-height: 50px; margin: 10px; }
         
     | 
| 
       11 
11 
     | 
    
         
             
              .legend div {
         
     | 
| 
       12 
12 
     | 
    
         
             
                display: block;
         
     | 
| 
       13 
13 
     | 
    
         
             
                float: left;
         
     | 
| 
         @@ -16,13 +16,62 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
                padding: 4px;
         
     | 
| 
       17 
17 
     | 
    
         
             
                height: 50px;
         
     | 
| 
       18 
18 
     | 
    
         
             
              }
         
     | 
| 
      
 19 
     | 
    
         
            +
              .code {
         
     | 
| 
      
 20 
     | 
    
         
            +
                font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace;
         
     | 
| 
      
 21 
     | 
    
         
            +
              }
         
     | 
| 
      
 22 
     | 
    
         
            +
              #frameinfo table .sample-info {
         
     | 
| 
      
 23 
     | 
    
         
            +
                width: 200px;
         
     | 
| 
      
 24 
     | 
    
         
            +
                color: #333;
         
     | 
| 
      
 25 
     | 
    
         
            +
                font-size: 12px;
         
     | 
| 
      
 26 
     | 
    
         
            +
              }
         
     | 
| 
      
 27 
     | 
    
         
            +
              #frameinfo table {
         
     | 
| 
      
 28 
     | 
    
         
            +
                border-collapse: collapse;
         
     | 
| 
      
 29 
     | 
    
         
            +
              }
         
     | 
| 
      
 30 
     | 
    
         
            +
              #frameinfo table tr {
         
     | 
| 
      
 31 
     | 
    
         
            +
                border-bottom: 1px solid #eee;
         
     | 
| 
      
 32 
     | 
    
         
            +
                margin-top: 5px;
         
     | 
| 
      
 33 
     | 
    
         
            +
              }
         
     | 
| 
      
 34 
     | 
    
         
            +
              #frameinfo td {
         
     | 
| 
      
 35 
     | 
    
         
            +
                padding: 5px;
         
     | 
| 
      
 36 
     | 
    
         
            +
              }
         
     | 
| 
      
 37 
     | 
    
         
            +
              #frameinfo-wrapper {
         
     | 
| 
      
 38 
     | 
    
         
            +
                position: fixed;
         
     | 
| 
      
 39 
     | 
    
         
            +
                z-index: 1;
         
     | 
| 
      
 40 
     | 
    
         
            +
                opacity: 0.7;
         
     | 
| 
      
 41 
     | 
    
         
            +
                background-color: black;
         
     | 
| 
      
 42 
     | 
    
         
            +
                width: 100%;
         
     | 
| 
      
 43 
     | 
    
         
            +
                height: 100%;
         
     | 
| 
      
 44 
     | 
    
         
            +
                top: 0;
         
     | 
| 
      
 45 
     | 
    
         
            +
                left: 0;
         
     | 
| 
      
 46 
     | 
    
         
            +
                display: none;
         
     | 
| 
      
 47 
     | 
    
         
            +
              }
         
     | 
| 
      
 48 
     | 
    
         
            +
              #frameinfo {
         
     | 
| 
      
 49 
     | 
    
         
            +
                position: fixed;
         
     | 
| 
      
 50 
     | 
    
         
            +
                padding: 10px;
         
     | 
| 
      
 51 
     | 
    
         
            +
                z-index: 2;
         
     | 
| 
      
 52 
     | 
    
         
            +
                opacity: 1.0;
         
     | 
| 
      
 53 
     | 
    
         
            +
                top: 0;
         
     | 
| 
      
 54 
     | 
    
         
            +
                margin-top: 50px;
         
     | 
| 
      
 55 
     | 
    
         
            +
                margin-left: 40px;
         
     | 
| 
      
 56 
     | 
    
         
            +
                width: 80%;
         
     | 
| 
      
 57 
     | 
    
         
            +
                height: 80%;
         
     | 
| 
      
 58 
     | 
    
         
            +
                background-color: white;
         
     | 
| 
      
 59 
     | 
    
         
            +
                border: 2px solid #666;
         
     | 
| 
      
 60 
     | 
    
         
            +
                display: none;
         
     | 
| 
      
 61 
     | 
    
         
            +
                overflow: auto;
         
     | 
| 
      
 62 
     | 
    
         
            +
              }
         
     | 
| 
       19 
63 
     | 
    
         
             
            </style>
         
     | 
| 
       20 
64 
     | 
    
         
             
            </head>
         
     | 
| 
       21 
65 
     | 
    
         
             
            <body>
         
     | 
| 
       22 
66 
     | 
    
         
             
              <div class="graph"></div>
         
     | 
| 
       23 
     | 
    
         
            -
              <div class="info"></div>
         
     | 
| 
      
 67 
     | 
    
         
            +
              <div class="info code"></div>
         
     | 
| 
       24 
68 
     | 
    
         
             
              <div class="legend"></div>
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 69 
     | 
    
         
            +
              <div id="frameinfo-wrapper"></div>
         
     | 
| 
      
 70 
     | 
    
         
            +
              <div id="frameinfo">
         
     | 
| 
      
 71 
     | 
    
         
            +
                <h3>Frame Info</h3>
         
     | 
| 
      
 72 
     | 
    
         
            +
                <table>
         
     | 
| 
      
 73 
     | 
    
         
            +
                </table>
         
     | 
| 
      
 74 
     | 
    
         
            +
              </div>
         
     | 
| 
       26 
75 
     | 
    
         
             
              <script>
         
     | 
| 
       27 
76 
     | 
    
         | 
| 
       28 
77 
     | 
    
         
             
            var data = /**DATA**/;
         
     | 
| 
         @@ -84,7 +133,12 @@ var guessGem = function(frame) 
     | 
|
| 
       84 
133 
     | 
    
         
             
            var guessMethod = function(frame) {
         
     | 
| 
       85 
134 
     | 
    
         
             
              var split = frame.split('`');
         
     | 
| 
       86 
135 
     | 
    
         
             
              if(split.length == 2) {
         
     | 
| 
       87 
     | 
    
         
            -
                 
     | 
| 
      
 136 
     | 
    
         
            +
                var fullMethod = split[1].split("'")[0];
         
     | 
| 
      
 137 
     | 
    
         
            +
                split = fullMethod.split("#");
         
     | 
| 
      
 138 
     | 
    
         
            +
                if(split.length == 2) {
         
     | 
| 
      
 139 
     | 
    
         
            +
                  return split[1];
         
     | 
| 
      
 140 
     | 
    
         
            +
                }
         
     | 
| 
      
 141 
     | 
    
         
            +
                return split[0];
         
     | 
| 
       88 
142 
     | 
    
         
             
              }
         
     | 
| 
       89 
143 
     | 
    
         
             
              return '?';
         
     | 
| 
       90 
144 
     | 
    
         
             
            }
         
     | 
| 
         @@ -101,7 +155,7 @@ var guessFile = function(frame) { 
     | 
|
| 
       101 
155 
     | 
    
         
             
            $.each(data, function(){
         
     | 
| 
       102 
156 
     | 
    
         
             
               maxX = Math.max(maxX, this.x + this.width);
         
     | 
| 
       103 
157 
     | 
    
         
             
               maxY = Math.max(maxY, this.y);
         
     | 
| 
       104 
     | 
    
         
            -
               this.shortName =  
     | 
| 
      
 158 
     | 
    
         
            +
               this.shortName = guessMethod(this.frame);
         
     | 
| 
       105 
159 
     | 
    
         
             
            });
         
     | 
| 
       106 
160 
     | 
    
         | 
| 
       107 
161 
     | 
    
         
             
            var width = $(window).width();
         
     | 
| 
         @@ -194,6 +248,87 @@ var mouseout = function(d) { 
     | 
|
| 
       194 
248 
     | 
    
         
             
                 .attr('opacity',1);
         
     | 
| 
       195 
249 
     | 
    
         
             
            };
         
     | 
| 
       196 
250 
     | 
    
         | 
| 
      
 251 
     | 
    
         
            +
            var backtrace = function(frame){
         
     | 
| 
      
 252 
     | 
    
         
            +
              for(var i=0; i<data.length; i++){
         
     | 
| 
      
 253 
     | 
    
         
            +
                if(frame === data[i]){ break; }
         
     | 
| 
      
 254 
     | 
    
         
            +
              }
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
              frames = [frame];
         
     | 
| 
      
 257 
     | 
    
         
            +
              var depth = frame.y;
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
              while(i > 0){
         
     | 
| 
      
 260 
     | 
    
         
            +
                if(depth == -1) break;
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                if(data[i].y === depth-1) {
         
     | 
| 
      
 263 
     | 
    
         
            +
                  frames.push(data[i]);
         
     | 
| 
      
 264 
     | 
    
         
            +
                  depth--;
         
     | 
| 
      
 265 
     | 
    
         
            +
                }
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                i--;
         
     | 
| 
      
 268 
     | 
    
         
            +
              }
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
              return frames;
         
     | 
| 
      
 271 
     | 
    
         
            +
            }
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
            $('#frameinfo-wrapper').click(function(d){
         
     | 
| 
      
 274 
     | 
    
         
            +
                $(this).hide();
         
     | 
| 
      
 275 
     | 
    
         
            +
                $('#frameinfo').hide();
         
     | 
| 
      
 276 
     | 
    
         
            +
            });
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
      
 278 
     | 
    
         
            +
            var click = function(d){
         
     | 
| 
      
 279 
     | 
    
         
            +
              var trace = backtrace(d);
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
              var link = function(path, dest){
         
     | 
| 
      
 282 
     | 
    
         
            +
                return path.replace(/[^\/]+:\d+/, function(x){ return "<a target='_blank' href='"+ dest +"'>" + x + "</a>"})
         
     | 
| 
      
 283 
     | 
    
         
            +
              };
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
              var linkify = function(path){
         
     | 
| 
      
 286 
     | 
    
         
            +
                var split = path.split("/")[0].split("-");
         
     | 
| 
      
 287 
     | 
    
         
            +
                if(["activerecord","actionpack","railties","activesupport", "rails"].indexOf(split[0]) > -1) {
         
     | 
| 
      
 288 
     | 
    
         
            +
                  var github = "https://github.com/rails/rails/blob/";
         
     | 
| 
      
 289 
     | 
    
         
            +
                  var file = path.split(":")[0].split("/");
         
     | 
| 
      
 290 
     | 
    
         
            +
                  if(split[0] === "rails") {
         
     | 
| 
      
 291 
     | 
    
         
            +
                    file.shift();
         
     | 
| 
      
 292 
     | 
    
         
            +
                  } else {
         
     | 
| 
      
 293 
     | 
    
         
            +
                    file[0] = split[0];
         
     | 
| 
      
 294 
     | 
    
         
            +
                  }
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
                  github += (split[1].length < 6 ? "v" : "") + split[1] + "/";
         
     | 
| 
      
 297 
     | 
    
         
            +
                  github += file.join("/");
         
     | 
| 
      
 298 
     | 
    
         
            +
                  github += "#L" + parseInt(path.split(":")[1]);
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                  return link(path, github);
         
     | 
| 
      
 301 
     | 
    
         
            +
                }
         
     | 
| 
      
 302 
     | 
    
         
            +
                return path;
         
     | 
| 
      
 303 
     | 
    
         
            +
              }
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
              var simplify = function(frame){
         
     | 
| 
      
 306 
     | 
    
         
            +
                var split = frame.split('/gems/');
         
     | 
| 
      
 307 
     | 
    
         
            +
                if(split.length > 1){
         
     | 
| 
      
 308 
     | 
    
         
            +
                  var path = linkify(split.pop());
         
     | 
| 
      
 309 
     | 
    
         
            +
                  return "<span class='full-location'>" + split.join('/gems/') + "/</span>" + path;
         
     | 
| 
      
 310 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 311 
     | 
    
         
            +
                  return frame;
         
     | 
| 
      
 312 
     | 
    
         
            +
                }
         
     | 
| 
      
 313 
     | 
    
         
            +
              }
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
              var table = trace.map(function(f){
         
     | 
| 
      
 316 
     | 
    
         
            +
                    var i = info[f.frame];
         
     | 
| 
      
 317 
     | 
    
         
            +
                    return "<tr><td class='code'>" + simplify(f.frame) + "</td><td class='sample-info'>" +
         
     | 
| 
      
 318 
     | 
    
         
            +
                            samplePercent(i.samples.length, f.topFrame ? f.topFrame.exclusiveCount : 0) + 
         
     | 
| 
      
 319 
     | 
    
         
            +
                            "</td></tr>";
         
     | 
| 
      
 320 
     | 
    
         
            +
                  }).join("\n");
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
              var table = $('#frameinfo table').html(table);
         
     | 
| 
      
 323 
     | 
    
         
            +
              table.find(".full-location").hide().after("<span class='expand'>… </span>");
         
     | 
| 
      
 324 
     | 
    
         
            +
              table.find(".expand").css({cursor: "pointer"}).click(function(){
         
     | 
| 
      
 325 
     | 
    
         
            +
                  $(this).hide().parent().find(".full-location").show();
         
     | 
| 
      
 326 
     | 
    
         
            +
              });
         
     | 
| 
      
 327 
     | 
    
         
            +
             
     | 
| 
      
 328 
     | 
    
         
            +
              $('#frameinfo-wrapper').show();
         
     | 
| 
      
 329 
     | 
    
         
            +
              $('#frameinfo').show();
         
     | 
| 
      
 330 
     | 
    
         
            +
            };
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
       197 
332 
     | 
    
         
             
            // http://stackoverflow.com/a/7419630
         
     | 
| 
       198 
333 
     | 
    
         
             
            var rainbow = function(numOfSteps, step) {
         
     | 
| 
       199 
334 
     | 
    
         
             
                // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distiguishable vibrant markers in Google Maps and other apps.
         
     | 
| 
         @@ -291,7 +426,7 @@ function fontSize(d,i) { 
     | 
|
| 
       291 
426 
     | 
    
         
             
              var height = yScale(1);
         
     | 
| 
       292 
427 
     | 
    
         
             
              var length = 0;
         
     | 
| 
       293 
428 
     | 
    
         
             
              d3.select(this).style("font-size", size + "px").text(word);
         
     | 
| 
       294 
     | 
    
         
            -
              while(((this.getBBox().width >= width) || (this.getBBox().height >= height)) 
     | 
| 
      
 429 
     | 
    
         
            +
              while((size > 12.1) && ((this.getBBox().width >= width) || (this.getBBox().height >= height)))
         
     | 
| 
       295 
430 
     | 
    
         
             
               {
         
     | 
| 
       296 
431 
     | 
    
         
             
                size -= 0.1;
         
     | 
| 
       297 
432 
     | 
    
         
             
                d3.select(this).style("font-size", size + "px");
         
     | 
| 
         @@ -323,7 +458,9 @@ svg.selectAll("g") 
     | 
|
| 
       323 
458 
     | 
    
         
             
                    return i.color;
         
     | 
| 
       324 
459 
     | 
    
         
             
                  })
         
     | 
| 
       325 
460 
     | 
    
         
             
                  .on("mouseover", mouseover)
         
     | 
| 
       326 
     | 
    
         
            -
                  .on("mouseout", mouseout) 
     | 
| 
      
 461 
     | 
    
         
            +
                  .on("mouseout", mouseout)
         
     | 
| 
      
 462 
     | 
    
         
            +
                  .on("click", click)
         
     | 
| 
      
 463 
     | 
    
         
            +
                  .attr("cursor", "pointer");
         
     | 
| 
       327 
464 
     | 
    
         | 
| 
       328 
465 
     | 
    
         
             
                  d3.select(this)
         
     | 
| 
       329 
466 
     | 
    
         
             
                    .append("text")
         
     | 
| 
         @@ -331,7 +468,9 @@ svg.selectAll("g") 
     | 
|
| 
       331 
468 
     | 
    
         
             
                    .attr("y",function(d) { return yScale(maxY - d.y);})
         
     | 
| 
       332 
469 
     | 
    
         
             
                    .on("mouseover", mouseover)
         
     | 
| 
       333 
470 
     | 
    
         
             
                    .on("mouseout", mouseout)
         
     | 
| 
      
 471 
     | 
    
         
            +
                    .on("click", click)
         
     | 
| 
       334 
472 
     | 
    
         
             
                    .each(fontSize)
         
     | 
| 
      
 473 
     | 
    
         
            +
                    .attr("cursor", "pointer")
         
     | 
| 
       335 
474 
     | 
    
         
             
                    .attr("display", "none");
         
     | 
| 
       336 
475 
     | 
    
         | 
| 
       337 
476 
     | 
    
         
             
                });
         
     | 
    
        data/lib/flamegraph/renderer.rb
    CHANGED
    
    | 
         @@ -22,13 +22,14 @@ class Flamegraph::Renderer 
     | 
|
| 
       22 
22 
     | 
    
         
             
              end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
              def graph_data
         
     | 
| 
       25 
     | 
    
         
            -
                height = 0
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
25 
     | 
    
         
             
                table = []
         
     | 
| 
       28 
26 
     | 
    
         
             
                prev = []
         
     | 
| 
       29 
27 
     | 
    
         | 
| 
       30 
28 
     | 
    
         
             
                # a 2d array makes collapsing easy
         
     | 
| 
       31 
29 
     | 
    
         
             
                @stacks.each_with_index do |stack, pos|
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  next unless stack
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       32 
33 
     | 
    
         
             
                  col = []
         
     | 
| 
       33 
34 
     | 
    
         | 
| 
       34 
35 
     | 
    
         
             
                  stack.reverse.map{|r| r.to_s}.each_with_index do |frame, i|
         
     | 
| 
         @@ -79,7 +80,7 @@ class Flamegraph::Renderer 
     | 
|
| 
       79 
80 
     | 
    
         
             
              end
         
     | 
| 
       80 
81 
     | 
    
         | 
| 
       81 
82 
     | 
    
         
             
              def read(file)
         
     | 
| 
       82 
     | 
    
         
            -
                 
     | 
| 
      
 83 
     | 
    
         
            +
                IO.read(::File.expand_path(file, ::File.dirname(__FILE__)))
         
     | 
| 
       83 
84 
     | 
    
         
             
              end
         
     | 
| 
       84 
85 
     | 
    
         | 
| 
       85 
86 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Flamegraph::StackProfSampler
         
     | 
| 
      
 2 
     | 
    
         
            +
              def self.collect(fidelity=0.5)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                result = StackProf.run(mode: :wall,
         
     | 
| 
      
 5 
     | 
    
         
            +
                                       raw: true,
         
     | 
| 
      
 6 
     | 
    
         
            +
                                       aggregate: false,
         
     | 
| 
      
 7 
     | 
    
         
            +
                                       interval: (fidelity * 1000).to_i) do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                stacks = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                stack = []
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                return [] unless result[:raw]
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                length = nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                result[:raw].each do |i|
         
     | 
| 
      
 19 
     | 
    
         
            +
                  if length.nil?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    length = i
         
     | 
| 
      
 21 
     | 
    
         
            +
                    next
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  if length > 0
         
     | 
| 
      
 25 
     | 
    
         
            +
                    frame = result[:frames][i]
         
     | 
| 
      
 26 
     | 
    
         
            +
                    frame = "#{frame[:file]}:#{frame[:line]}:in `#{frame[:name]}'"
         
     | 
| 
      
 27 
     | 
    
         
            +
                    stack << frame.to_s
         
     | 
| 
      
 28 
     | 
    
         
            +
                    length -= 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                    next
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  i.times do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    stacks << stack.reverse
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  stack = []
         
     | 
| 
      
 37 
     | 
    
         
            +
                  length = nil
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                stacks
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/flamegraph/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            if RUBY_VERSION >= "2.1.0"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              require 'stackprof'
         
     | 
| 
      
 4 
     | 
    
         
            +
              require 'test_helper'
         
     | 
| 
      
 5 
     | 
    
         
            +
              require 'flamegraph/stackprof_sampler'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              class TestStackprofSampler < Minitest::Test
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def idle(duration)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  r, w = IO.pipe
         
     | 
| 
      
 11 
     | 
    
         
            +
                  IO.select([r], nil, nil, duration)
         
     | 
| 
      
 12 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 13 
     | 
    
         
            +
                  r.close
         
     | 
| 
      
 14 
     | 
    
         
            +
                  w.close
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def test_sample_collection
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  samples = Flamegraph::StackProfSampler.collect do
         
     | 
| 
      
 20 
     | 
    
         
            +
                    idle 0.005
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  assert(samples.count > 3, "Should get more than 3 samples in 5 millisecs")
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def test_fidelity
         
     | 
| 
      
 27 
     | 
    
         
            +
                  samples = Flamegraph::StackProfSampler.collect(10) do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    idle 0.005
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  assert(samples.count <= 1, "Should get a max of 1 sample got #{samples.count}")
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,97 +1,97 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: flamegraph
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.6
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sam Saffron
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-11-12 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: fast_stack
         
     | 
| 
       15 
15 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       16 
16 
     | 
    
         
             
                requirements:
         
     | 
| 
       17 
     | 
    
         
            -
                - -  
     | 
| 
      
 17 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       18 
18 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       19 
19 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       20 
20 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       21 
21 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       22 
22 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       23 
23 
     | 
    
         
             
                requirements:
         
     | 
| 
       24 
     | 
    
         
            -
                - -  
     | 
| 
      
 24 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
26 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       27 
27 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
28 
     | 
    
         
             
              name: bundler
         
     | 
| 
       29 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       30 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       31 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       32 
32 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       33 
33 
     | 
    
         
             
                    version: '1.3'
         
     | 
| 
       34 
34 
     | 
    
         
             
              type: :development
         
     | 
| 
       35 
35 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       36 
36 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       37 
37 
     | 
    
         
             
                requirements:
         
     | 
| 
       38 
     | 
    
         
            -
                - - ~>
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
       39 
39 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       40 
40 
     | 
    
         
             
                    version: '1.3'
         
     | 
| 
       41 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       42 
42 
     | 
    
         
             
              name: rake
         
     | 
| 
       43 
43 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       44 
44 
     | 
    
         
             
                requirements:
         
     | 
| 
       45 
     | 
    
         
            -
                - -  
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       46 
46 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       47 
47 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       48 
48 
     | 
    
         
             
              type: :development
         
     | 
| 
       49 
49 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       50 
50 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       51 
51 
     | 
    
         
             
                requirements:
         
     | 
| 
       52 
     | 
    
         
            -
                - -  
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       53 
53 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       54 
54 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       55 
55 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       56 
56 
     | 
    
         
             
              name: minitest
         
     | 
| 
       57 
57 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       58 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
     | 
    
         
            -
                - -  
     | 
| 
      
 59 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       60 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
61 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       62 
62 
     | 
    
         
             
              type: :development
         
     | 
| 
       63 
63 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       64 
64 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
65 
     | 
    
         
             
                requirements:
         
     | 
| 
       66 
     | 
    
         
            -
                - -  
     | 
| 
      
 66 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
68 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       69 
69 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       70 
70 
     | 
    
         
             
              name: guard
         
     | 
| 
       71 
71 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       72 
72 
     | 
    
         
             
                requirements:
         
     | 
| 
       73 
     | 
    
         
            -
                - -  
     | 
| 
      
 73 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       74 
74 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       75 
75 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       76 
76 
     | 
    
         
             
              type: :development
         
     | 
| 
       77 
77 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       78 
78 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       79 
79 
     | 
    
         
             
                requirements:
         
     | 
| 
       80 
     | 
    
         
            -
                - -  
     | 
| 
      
 80 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       81 
81 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       82 
82 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       83 
83 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       84 
84 
     | 
    
         
             
              name: guard-minitest
         
     | 
| 
       85 
85 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       86 
86 
     | 
    
         
             
                requirements:
         
     | 
| 
       87 
     | 
    
         
            -
                - -  
     | 
| 
      
 87 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       88 
88 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       89 
89 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       90 
90 
     | 
    
         
             
              type: :development
         
     | 
| 
       91 
91 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       92 
92 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       93 
93 
     | 
    
         
             
                requirements:
         
     | 
| 
       94 
     | 
    
         
            -
                - -  
     | 
| 
      
 94 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       95 
95 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       96 
96 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       97 
97 
     | 
    
         
             
            description: Flamegraph support for arbitrary ruby apps
         
     | 
| 
         @@ -101,7 +101,7 @@ executables: [] 
     | 
|
| 
       101 
101 
     | 
    
         
             
            extensions: []
         
     | 
| 
       102 
102 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       103 
103 
     | 
    
         
             
            files:
         
     | 
| 
       104 
     | 
    
         
            -
            - .gitignore
         
     | 
| 
      
 104 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
       105 
105 
     | 
    
         
             
            - CHANGELOG
         
     | 
| 
       106 
106 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       107 
107 
     | 
    
         
             
            - Guardfile
         
     | 
| 
         @@ -119,11 +119,13 @@ files: 
     | 
|
| 
       119 
119 
     | 
    
         
             
            - lib/flamegraph/lodash.min.js
         
     | 
| 
       120 
120 
     | 
    
         
             
            - lib/flamegraph/renderer.rb
         
     | 
| 
       121 
121 
     | 
    
         
             
            - lib/flamegraph/sampler.rb
         
     | 
| 
      
 122 
     | 
    
         
            +
            - lib/flamegraph/stackprof_sampler.rb
         
     | 
| 
       122 
123 
     | 
    
         
             
            - lib/flamegraph/version.rb
         
     | 
| 
       123 
124 
     | 
    
         
             
            - test/test_fast_stack_sampler.rb
         
     | 
| 
       124 
125 
     | 
    
         
             
            - test/test_helper.rb
         
     | 
| 
       125 
126 
     | 
    
         
             
            - test/test_renderer.rb
         
     | 
| 
       126 
127 
     | 
    
         
             
            - test/test_sampler.rb
         
     | 
| 
      
 128 
     | 
    
         
            +
            - test/test_stackprof_sampler.rb
         
     | 
| 
       127 
129 
     | 
    
         
             
            homepage: ''
         
     | 
| 
       128 
130 
     | 
    
         
             
            licenses:
         
     | 
| 
       129 
131 
     | 
    
         
             
            - MIT
         
     | 
| 
         @@ -134,17 +136,17 @@ require_paths: 
     | 
|
| 
       134 
136 
     | 
    
         
             
            - lib
         
     | 
| 
       135 
137 
     | 
    
         
             
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
       136 
138 
     | 
    
         
             
              requirements:
         
     | 
| 
       137 
     | 
    
         
            -
              - -  
     | 
| 
      
 139 
     | 
    
         
            +
              - - ">="
         
     | 
| 
       138 
140 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       139 
141 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       140 
142 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       141 
143 
     | 
    
         
             
              requirements:
         
     | 
| 
       142 
     | 
    
         
            -
              - -  
     | 
| 
      
 144 
     | 
    
         
            +
              - - ">="
         
     | 
| 
       143 
145 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       144 
146 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       145 
147 
     | 
    
         
             
            requirements: []
         
     | 
| 
       146 
148 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       147 
     | 
    
         
            -
            rubygems_version: 2. 
     | 
| 
      
 149 
     | 
    
         
            +
            rubygems_version: 2.2.2
         
     | 
| 
       148 
150 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       149 
151 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       150 
152 
     | 
    
         
             
            summary: Flamegraph support for arbitrary ruby apps
         
     | 
| 
         @@ -153,3 +155,4 @@ test_files: 
     | 
|
| 
       153 
155 
     | 
    
         
             
            - test/test_helper.rb
         
     | 
| 
       154 
156 
     | 
    
         
             
            - test/test_renderer.rb
         
     | 
| 
       155 
157 
     | 
    
         
             
            - test/test_sampler.rb
         
     | 
| 
      
 158 
     | 
    
         
            +
            - test/test_stackprof_sampler.rb
         
     |