-
Notifications
You must be signed in to change notification settings - Fork 607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flame Graph support on Web UI #188
Changes from 37 commits
06f02b6
db1575c
7f9e781
8c11fce
b6e1efc
a55d5f9
acfe4b9
faa772e
96445d3
df97f08
5bd8ef3
5d827ef
edb9617
0afa5df
a397cfc
b110c5a
0c90f58
0ef2abf
5c523bf
a61ecb7
ea28314
7d50b81
dc7fb88
33b7a40
94b476f
ffeb2ac
335eff1
0e6f0f8
3b92869
d8164c3
39351b8
2e3e9bc
cf2aab6
4a03397
2289cb4
46ed7a2
370fc15
0e1724b
b9de433
7307bc6
49a0976
c548705
f465f8a
1bd096a
7b1f77e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,5 @@ | |
Raul Silvera <[email protected]> | ||
Tipp Moseley <[email protected]> | ||
Hyoun Kyu Cho <[email protected]> | ||
Martin Spier <[email protected]> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright 2017 Google Inc. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package driver | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"html/template" | ||
"math" | ||
"net/http" | ||
"strings" | ||
|
||
"github.com/google/pprof/internal/graph" | ||
"github.com/google/pprof/internal/report" | ||
) | ||
|
||
type treeNode struct { | ||
Name string `json:"n"` | ||
Cum int64 `json:"v"` | ||
CumFormat string `json:"l"` | ||
Percent string `json:"p"` | ||
Children []*treeNode `json:"c"` | ||
} | ||
|
||
// percentage computes the percentage of total of a value, and encodes | ||
// it as a string. At least two digits of precision are printed. | ||
func percentage(value, total int64) string { | ||
var ratio float64 | ||
if total != 0 { | ||
ratio = math.Abs(float64(value)/float64(total)) * 100 | ||
} | ||
return fmt.Sprintf("%5.2f%%", ratio) | ||
} | ||
|
||
// flamegraph generates a web page containing a flamegraph. | ||
func (ui *webInterface) flamegraph(w http.ResponseWriter, req *http.Request) { | ||
// Force the call tree so that the graph is a tree. | ||
rpt, errList := ui.makeReport(w, req, []string{"svg"}, "call_tree", "true") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update this to
The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you. I prefer to have the flame graph contain everything, but that's not the default behavior for the directed graph, so I wasn't really sure what would the users prefer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The graph does it by default because displaying the full graph for large programs becomes messy. Flame graph appears to be compact and readable enough on some larger profiles I tried so I think trimming the tree would be more confusing that useful here. |
||
if rpt == nil { | ||
return // error already reported | ||
} | ||
|
||
// Generate dot graph. | ||
g, config := report.GetDOT(rpt) | ||
var nodes []*treeNode | ||
nroots := 0 | ||
nodeMap := map[*graph.Node]*treeNode{} | ||
// Make all nodes and the map, collect the roots. | ||
for _, n := range g.Nodes { | ||
v := n.CumValue() | ||
node := &treeNode{ | ||
Name: n.Info.PrintableName(), | ||
Cum: v, | ||
CumFormat: config.FormatValue(v), | ||
Percent: strings.TrimSpace(percentage(v, config.Total)), | ||
} | ||
nodes = append(nodes, node) | ||
if len(n.In) == 0 { | ||
nodes[nroots], nodes[len(nodes)-1] = nodes[len(nodes)-1], nodes[nroots] | ||
nroots++ | ||
} | ||
nodeMap[n] = node | ||
} | ||
// Populate the child links. | ||
for _, n := range g.Nodes { | ||
node := nodeMap[n] | ||
for child := range n.Out { | ||
node.Children = append(node.Children, nodeMap[child]) | ||
} | ||
} | ||
|
||
// Calculate root value | ||
rootValue := int64(0) | ||
for _, n := range nodes[0:nroots] { | ||
rootValue = rootValue + n.Cum | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this can be done near |
||
} | ||
|
||
rootNode := &treeNode{ | ||
Name: "root", | ||
Cum: rootValue, | ||
CumFormat: config.FormatValue(rootValue), | ||
Percent: strings.TrimSpace(percentage(rootValue, config.Total)), | ||
Children: nodes[0:nroots], | ||
} | ||
|
||
// JSON marshalling flame graph | ||
b, err := json.Marshal(rootNode) | ||
if err != nil { | ||
http.Error(w, "error serializing flame graph", http.StatusInternalServerError) | ||
ui.options.UI.PrintErr(err) | ||
return | ||
} | ||
|
||
ui.render(w, "/flamegraph", "flamegraph", rpt, errList, config.Labels, webArgs{ | ||
FlameGraph: template.JS(b), | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright 2010-2017 Mike Bostock | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, | ||
are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
* Neither the name of the author nor the names of contributors may be used to | ||
endorse or promote products derived from this software without specific prior | ||
written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I I think we should do #265 and use
measurement.Percentage
in the code below so that this function can be dropped and so that the percentage formatting is enforced to be consistent.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I wait until it gets merged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I merged that, you can rebase.