-
-
Save zikaeroh/96741da55aad5964576e0aba864cbeb3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2020/10/08 19:24:28 debug server listening on port 39161 | |
[Trace - 19:24:28.645 PM] Sending request 'initialize - (0)'. | |
Params: {"processId":48783,"clientInfo":{"name":"vscode","version":"1.49.3"},"rootPath":"/home/jake/zikaeroh/pprof","rootUri":"file:///home/jake/zikaeroh/pprof","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional"},"didChangeConfiguration":{"dynamicRegistration":true},"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]}},"executeCommand":{"dynamicRegistration":true},"configuration":true,"workspaceFolders":true},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"complexDiagnosticCodeSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveAdditionalTextEditsSupport":true},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]}},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","member","macro","keyword","modifier","comment","string","number","regexp","operator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}}}},"window":{"workDoneProgress":true}},"initializationOptions":{"allExperiments":true,"usePlaceholders":false,"tempModfile":false},"trace":"off","workspaceFolders":[{"uri":"file:///home/jake/zikaeroh/pprof","name":"pprof"}]} | |
[Trace - 19:24:28.648 PM] Received response 'initialize - (0)' in 2ms. | |
Result: {"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","refactor.extract","refactor.rewrite","source.fixAll","source.organizeImports"]},"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"renameProvider":{"prepareProvider":true},"foldingRangeProvider":true,"executeCommandProvider":{"commands":["generate","fill_struct","regenerate_cgo","test","tidy","undeclared_name","upgrade_dependency","vendor","extract_variable","extract_function","gc_details","generate_gopls_mod"]},"callHierarchyProvider":true,"semanticTokensProvider":{"legend":{"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","member","macro","keyword","modifier","comment","string","number","regexp","operator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"]},"range":true,"full":true},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":"gopls","version":"Build info\n----------\ngolang.org/x/tools/gopls master\n golang.org/x/tools/gopls@v0.0.0-20201009010951-9ab7e515274e h1:Fxf8D75bsdvDgLpM6enYCHxPn+lFAiEBFAvdk/0UJ7s=\n github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\n github.com/google/go-cmp@v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=\n github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\n golang.org/x/mod@v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=\n golang.org/x/sync@v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=\n golang.org/x/tools@v0.0.0-20201009010951-9ab7e515274e h1:x1hHgXABYbwIYbEYxs6ypae/tryqQ7YQ1/DwGyKp4Ok=\n golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=\n honnef.co/go/tools@v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=\n mvdan.cc/gofumpt@v0.0.0-20200802201014-ab5a8192947d h1:t8TAw9WgTLghti7RYkpPmqk4JtQ3+wcP5GgZqgWeWLQ=\n mvdan.cc/xurls/v2@v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=\n"}} | |
[Trace - 19:24:28.650 PM] Sending notification 'initialized'. | |
Params: {} | |
[Trace - 19:24:28.650 PM] Received request 'window/workDoneProgress/create - (1)'. | |
Params: {"token":"5577006791947779410"} | |
[Trace - 19:24:28.651 PM] Sending notification 'textDocument/didOpen'. | |
Params: {"textDocument":{"uri":"file:///home/jake/zikaeroh/pprof/internal/graph/graph.go","languageId":"go","version":1,"text":"// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package graph collects a set of samples into a directed graph.\npackage graph\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/google/pprof/profile\"\n)\n\nvar (\n\t// Removes package name and method arugments for Java method names.\n\t// See tests for examples.\n\tjavaRegExp = regexp.MustCompile(`^(?:[a-z]\\w*\\.)*([A-Z][\\w\\$]*\\.(?:<init>|[a-z][\\w\\$]*(?:\\$\\d+)?))(?:(?:\\()|$)`)\n\t// Removes package name and method arugments for Go function names.\n\t// See tests for examples.\n\tgoRegExp = regexp.MustCompile(`^(?:[\\w\\-\\.]+\\/)+(.+)`)\n\t// Checks for a package name that could be a module version.\n\tgoVerRegExp = regexp.MustCompile(`^v[2-9]+\\.`)\n\t// Strips C++ namespace prefix from a C++ function / method name.\n\t// NOTE: Make sure to keep the template parameters in the name. Normally,\n\t// template parameters are stripped from the C++ names but when\n\t// -symbolize=demangle=templates flag is used, they will not be.\n\t// See tests for examples.\n\tcppRegExp = regexp.MustCompile(`^(?:[_a-zA-Z]\\w*::)+(_*[A-Z]\\w*::~?[_a-zA-Z]\\w*(?:<.*>)?)`)\n\tcppAnonymousPrefixRegExp = regexp.MustCompile(`^\\(anonymous namespace\\)::`)\n)\n\n// Graph summarizes a performance profile into a format that is\n// suitable for visualization.\ntype Graph struct {\n\tNodes Nodes\n}\n\n// Options encodes the options for constructing a graph\ntype Options struct {\n\tSampleValue func(s []int64) int64 // Function to compute the value of a sample\n\tSampleMeanDivisor func(s []int64) int64 // Function to compute the divisor for mean graphs, or nil\n\tFormatTag func(int64, string) string // Function to format a sample tag value into a string\n\tObjNames bool // Always preserve obj filename\n\tOrigFnNames bool // Preserve original (eg mangled) function names\n\n\tCallTree bool // Build a tree instead of a graph\n\tDropNegative bool // Drop nodes with overall negative values\n\n\tKeptNodes NodeSet // If non-nil, only use nodes in this set\n}\n\n// Nodes is an ordered collection of graph nodes.\ntype Nodes []*Node\n\n// Node is an entry on a profiling report. It represents a unique\n// program location.\ntype Node struct {\n\t// Info describes the source location associated to this node.\n\tInfo NodeInfo\n\n\t// Function represents the function that this node belongs to. On\n\t// graphs with sub-function resolution (eg line number or\n\t// addresses), two nodes in a NodeMap that are part of the same\n\t// function have the same value of Node.Function. If the Node\n\t// represents the whole function, it points back to itself.\n\tFunction *Node\n\n\t// Values associated to this node. Flat is exclusive to this node,\n\t// Cum includes all descendents.\n\tFlat, FlatDiv, Cum, CumDiv int64\n\n\t// In and out Contains the nodes immediately reaching or reached by\n\t// this node.\n\tIn, Out EdgeMap\n\n\t// LabelTags provide additional information about subsets of a sample.\n\tLabelTags TagMap\n\n\t// NumericTags provide additional values for subsets of a sample.\n\t// Numeric tags are optionally associated to a label tag. The key\n\t// for NumericTags is the name of the LabelTag they are associated\n\t// to, or \"\" for numeric tags not associated to a label tag.\n\tNumericTags map[string]TagMap\n}\n\n// FlatValue returns the exclusive value for this node, computing the\n// mean if a divisor is available.\nfunc (n *Node) FlatValue() int64 {\n\tif n.FlatDiv == 0 {\n\t\treturn n.Flat\n\t}\n\treturn n.Flat / n.FlatDiv\n}\n\n// CumValue returns the inclusive value for this node, computing the\n// mean if a divisor is available.\nfunc (n *Node) CumValue() int64 {\n\tif n.CumDiv == 0 {\n\t\treturn n.Cum\n\t}\n\treturn n.Cum / n.CumDiv\n}\n\n// AddToEdge increases the weight of an edge between two nodes. If\n// there isn't such an edge one is created.\nfunc (n *Node) AddToEdge(to *Node, v int64, residual, inline bool) {\n\tn.AddToEdgeDiv(to, 0, v, residual, inline)\n}\n\n// AddToEdgeDiv increases the weight of an edge between two nodes. If\n// there isn't such an edge one is created.\nfunc (n *Node) AddToEdgeDiv(to *Node, dv, v int64, residual, inline bool) {\n\tif n.Out[to] != to.In[n] {\n\t\tpanic(fmt.Errorf(\"asymmetric edges %v %v\", *n, *to))\n\t}\n\n\tif e := n.Out[to]; e != nil {\n\t\te.WeightDiv += dv\n\t\te.Weight += v\n\t\tif residual {\n\t\t\te.Residual = true\n\t\t}\n\t\tif !inline {\n\t\t\te.Inline = false\n\t\t}\n\t\treturn\n\t}\n\n\tinfo := &Edge{Src: n, Dest: to, WeightDiv: dv, Weight: v, Residual: residual, Inline: inline}\n\tn.Out[to] = info\n\tto.In[n] = info\n}\n\n// NodeInfo contains the attributes for a node.\ntype NodeInfo struct {\n\tName string\n\tOrigName string\n\tAddress uint64\n\tFile string\n\tStartLine, Lineno int\n\tObjfile string\n}\n\n// PrintableName calls the Node's Formatter function with a single space separator.\nfunc (i *NodeInfo) PrintableName() string {\n\treturn strings.Join(i.NameComponents(), \" \")\n}\n\n// NameComponents returns the components of the printable name to be used for a node.\nfunc (i *NodeInfo) NameComponents() []string {\n\tvar name []string\n\tif i.Address != 0 {\n\t\tname = append(name, fmt.Sprintf(\"%016x\", i.Address))\n\t}\n\tif fun := i.Name; fun != \"\" {\n\t\tname = append(name, fun)\n\t}\n\n\tswitch {\n\tcase i.Lineno != 0:\n\t\t// User requested line numbers, provide what we have.\n\t\tname = append(name, fmt.Sprintf(\"%s:%d\", i.File, i.Lineno))\n\tcase i.File != \"\":\n\t\t// User requested file name, provide it.\n\t\tname = append(name, i.File)\n\tcase i.Name != \"\":\n\t\t// User requested function name. It was already included.\n\tcase i.Objfile != \"\":\n\t\t// Only binary name is available\n\t\tname = append(name, \"[\"+filepath.Base(i.Objfile)+\"]\")\n\tdefault:\n\t\t// Do not leave it empty if there is no information at all.\n\t\tname = append(name, \"<unknown>\")\n\t}\n\treturn name\n}\n\n// NodeMap maps from a node info struct to a node. It is used to merge\n// report entries with the same info.\ntype NodeMap map[NodeInfo]*Node\n\n// NodeSet is a collection of node info structs.\ntype NodeSet map[NodeInfo]bool\n\n// NodePtrSet is a collection of nodes. Trimming a graph or tree requires a set\n// of objects which uniquely identify the nodes to keep. In a graph, NodeInfo\n// works as a unique identifier; however, in a tree multiple nodes may share\n// identical NodeInfos. A *Node does uniquely identify a node so we can use that\n// instead. Though a *Node also uniquely identifies a node in a graph,\n// currently, during trimming, graphs are rebuilt from scratch using only the\n// NodeSet, so there would not be the required context of the initial graph to\n// allow for the use of *Node.\ntype NodePtrSet map[*Node]bool\n\n// FindOrInsertNode takes the info for a node and either returns a matching node\n// from the node map if one exists, or adds one to the map if one does not.\n// If kept is non-nil, nodes are only added if they can be located on it.\nfunc (nm NodeMap) FindOrInsertNode(info NodeInfo, kept NodeSet) *Node {\n\tif kept != nil {\n\t\tif _, ok := kept[info]; !ok {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tif n, ok := nm[info]; ok {\n\t\treturn n\n\t}\n\n\tn := &Node{\n\t\tInfo: info,\n\t\tIn: make(EdgeMap),\n\t\tOut: make(EdgeMap),\n\t\tLabelTags: make(TagMap),\n\t\tNumericTags: make(map[string]TagMap),\n\t}\n\tnm[info] = n\n\tif info.Address == 0 && info.Lineno == 0 {\n\t\t// This node represents the whole function, so point Function\n\t\t// back to itself.\n\t\tn.Function = n\n\t\treturn n\n\t}\n\t// Find a node that represents the whole function.\n\tinfo.Address = 0\n\tinfo.Lineno = 0\n\tn.Function = nm.FindOrInsertNode(info, nil)\n\treturn n\n}\n\n// EdgeMap is used to represent the incoming/outgoing edges from a node.\ntype EdgeMap map[*Node]*Edge\n\n// Edge contains any attributes to be represented about edges in a graph.\ntype Edge struct {\n\tSrc, Dest *Node\n\t// The summary weight of the edge\n\tWeight, WeightDiv int64\n\n\t// residual edges connect nodes that were connected through a\n\t// separate node, which has been removed from the report.\n\tResidual bool\n\t// An inline edge represents a call that was inlined into the caller.\n\tInline bool\n}\n\n// WeightValue returns the weight value for this edge, normalizing if a\n// divisor is available.\nfunc (e *Edge) WeightValue() int64 {\n\tif e.WeightDiv == 0 {\n\t\treturn e.Weight\n\t}\n\treturn e.Weight / e.WeightDiv\n}\n\n// Tag represent sample annotations\ntype Tag struct {\n\tName string\n\tUnit string // Describe the value, \"\" for non-numeric tags\n\tValue int64\n\tFlat, FlatDiv int64\n\tCum, CumDiv int64\n}\n\n// FlatValue returns the exclusive value for this tag, computing the\n// mean if a divisor is available.\nfunc (t *Tag) FlatValue() int64 {\n\tif t.FlatDiv == 0 {\n\t\treturn t.Flat\n\t}\n\treturn t.Flat / t.FlatDiv\n}\n\n// CumValue returns the inclusive value for this tag, computing the\n// mean if a divisor is available.\nfunc (t *Tag) CumValue() int64 {\n\tif t.CumDiv == 0 {\n\t\treturn t.Cum\n\t}\n\treturn t.Cum / t.CumDiv\n}\n\n// TagMap is a collection of tags, classified by their name.\ntype TagMap map[string]*Tag\n\n// SortTags sorts a slice of tags based on their weight.\nfunc SortTags(t []*Tag, flat bool) []*Tag {\n\tts := tags{t, flat}\n\tsort.Sort(ts)\n\treturn ts.t\n}\n\n// New summarizes performance data from a profile into a graph.\nfunc New(prof *profile.Profile, o *Options) *Graph {\n\tif o.CallTree {\n\t\treturn newTree(prof, o)\n\t}\n\tg, _ := newGraph(prof, o)\n\treturn g\n}\n\n// newGraph computes a graph from a profile. It returns the graph, and\n// a map from the profile location indices to the corresponding graph\n// nodes.\nfunc newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) {\n\tnodes, locationMap := CreateNodes(prof, o)\n\tfor _, sample := range prof.Sample {\n\t\tvar w, dw int64\n\t\tw = o.SampleValue(sample.Value)\n\t\tif o.SampleMeanDivisor != nil {\n\t\t\tdw = o.SampleMeanDivisor(sample.Value)\n\t\t}\n\t\tif dw == 0 && w == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tseenNode := make(map[*Node]bool, len(sample.Location))\n\t\tseenEdge := make(map[nodePair]bool, len(sample.Location))\n\t\tvar parent *Node\n\t\t// A residual edge goes over one or more nodes that were not kept.\n\t\tresidual := false\n\n\t\tlabels := joinLabels(sample)\n\t\t// Group the sample frames, based on a global map.\n\t\tfor i := len(sample.Location) - 1; i >= 0; i-- {\n\t\t\tl := sample.Location[i]\n\t\t\tlocNodes := locationMap[l.ID]\n\t\t\tfor ni := len(locNodes) - 1; ni >= 0; ni-- {\n\t\t\t\tn := locNodes[ni]\n\t\t\t\tif n == nil {\n\t\t\t\t\tresidual = true\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Add cum weight to all nodes in stack, avoiding double counting.\n\t\t\t\tif _, ok := seenNode[n]; !ok {\n\t\t\t\t\tseenNode[n] = true\n\t\t\t\t\tn.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, false)\n\t\t\t\t}\n\t\t\t\t// Update edge weights for all edges in stack, avoiding double counting.\n\t\t\t\tif _, ok := seenEdge[nodePair{n, parent}]; !ok && parent != nil && n != parent {\n\t\t\t\t\tseenEdge[nodePair{n, parent}] = true\n\t\t\t\t\tparent.AddToEdgeDiv(n, dw, w, residual, ni != len(locNodes)-1)\n\t\t\t\t}\n\t\t\t\tparent = n\n\t\t\t\tresidual = false\n\t\t\t}\n\t\t}\n\t\tif parent != nil && !residual {\n\t\t\t// Add flat weight to leaf node.\n\t\t\tparent.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, true)\n\t\t}\n\t}\n\n\treturn selectNodesForGraph(nodes, o.DropNegative), locationMap\n}\n\nfunc selectNodesForGraph(nodes Nodes, dropNegative bool) *Graph {\n\t// Collect nodes into a graph.\n\tgNodes := make(Nodes, 0, len(nodes))\n\tfor _, n := range nodes {\n\t\tif n == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif n.Cum == 0 && n.Flat == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif dropNegative && isNegative(n) {\n\t\t\tcontinue\n\t\t}\n\t\tgNodes = append(gNodes, n)\n\t}\n\treturn &Graph{gNodes}\n}\n\ntype nodePair struct {\n\tsrc, dest *Node\n}\n\nfunc newTree(prof *profile.Profile, o *Options) (g *Graph) {\n\tparentNodeMap := make(map[*Node]NodeMap, len(prof.Sample))\n\tfor _, sample := range prof.Sample {\n\t\tvar w, dw int64\n\t\tw = o.SampleValue(sample.Value)\n\t\tif o.SampleMeanDivisor != nil {\n\t\t\tdw = o.SampleMeanDivisor(sample.Value)\n\t\t}\n\t\tif dw == 0 && w == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tvar parent *Node\n\t\tlabels := joinLabels(sample)\n\t\t// Group the sample frames, based on a per-node map.\n\t\tfor i := len(sample.Location) - 1; i >= 0; i-- {\n\t\t\tl := sample.Location[i]\n\t\t\tlines := l.Line\n\t\t\tif len(lines) == 0 {\n\t\t\t\tlines = []profile.Line{{}} // Create empty line to include location info.\n\t\t\t}\n\t\t\tfor lidx := len(lines) - 1; lidx >= 0; lidx-- {\n\t\t\t\tnodeMap := parentNodeMap[parent]\n\t\t\t\tif nodeMap == nil {\n\t\t\t\t\tnodeMap = make(NodeMap)\n\t\t\t\t\tparentNodeMap[parent] = nodeMap\n\t\t\t\t}\n\t\t\t\tn := nodeMap.findOrInsertLine(l, lines[lidx], o)\n\t\t\t\tif n == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tn.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, false)\n\t\t\t\tif parent != nil {\n\t\t\t\t\tparent.AddToEdgeDiv(n, dw, w, false, lidx != len(lines)-1)\n\t\t\t\t}\n\t\t\t\tparent = n\n\t\t\t}\n\t\t}\n\t\tif parent != nil {\n\t\t\tparent.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, true)\n\t\t}\n\t}\n\n\tnodes := make(Nodes, len(prof.Location))\n\tfor _, nm := range parentNodeMap {\n\t\tnodes = append(nodes, nm.nodes()...)\n\t}\n\treturn selectNodesForGraph(nodes, o.DropNegative)\n}\n\n// ShortenFunctionName returns a shortened version of a function's name.\nfunc ShortenFunctionName(f string) string {\n\tf = cppAnonymousPrefixRegExp.ReplaceAllString(f, \"\")\n\tfor _, re := range []*regexp.Regexp{goRegExp, javaRegExp, cppRegExp} {\n\t\tif matches := re.FindStringSubmatch(f); len(matches) >= 2 {\n\t\t\tname := strings.Join(matches[1:], \"\")\n\t\t\tif re == goRegExp {\n\t\t\t\treturn shortenGoFunc(f, name)\n\t\t\t}\n\t\t\treturn name\n\t\t}\n\t}\n\treturn f\n}\n\nfunc shortenGoFunc(f string, name string) string {\n\tif !goVerRegExp.MatchString(name) {\n\t\treturn name\n\t}\n\n\t// The shortened name could start with a module version (like \"v2\"). Go back one slash.\n\tend := len(f) - len(name) - 1\n\tif end >= 0 {\n\t\tprefix := f[:end]\n\t\tif idx := strings.LastIndex(prefix, \"/\"); idx >= 0 {\n\t\t\tend = idx\n\t\t}\n\t}\n\n\treturn f[end+1:]\n}\n\n// TrimTree trims a Graph in forest form, keeping only the nodes in kept. This\n// will not work correctly if even a single node has multiple parents.\nfunc (g *Graph) TrimTree(kept NodePtrSet) {\n\t// Creates a new list of nodes\n\toldNodes := g.Nodes\n\tg.Nodes = make(Nodes, 0, len(kept))\n\n\tfor _, cur := range oldNodes {\n\t\t// A node may not have multiple parents\n\t\tif len(cur.In) > 1 {\n\t\t\tpanic(\"TrimTree only works on trees\")\n\t\t}\n\n\t\t// If a node should be kept, add it to the new list of nodes\n\t\tif _, ok := kept[cur]; ok {\n\t\t\tg.Nodes = append(g.Nodes, cur)\n\t\t\tcontinue\n\t\t}\n\n\t\t// If a node has no parents, then delete all of the in edges of its\n\t\t// children to make them each roots of their own trees.\n\t\tif len(cur.In) == 0 {\n\t\t\tfor _, outEdge := range cur.Out {\n\t\t\t\tdelete(outEdge.Dest.In, cur)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Get the parent. This works since at this point cur.In must contain only\n\t\t// one element.\n\t\tif len(cur.In) != 1 {\n\t\t\tpanic(\"Get parent assertion failed. cur.In expected to be of length 1.\")\n\t\t}\n\t\tvar parent *Node\n\t\tfor _, edge := range cur.In {\n\t\t\tparent = edge.Src\n\t\t}\n\n\t\tparentEdgeInline := parent.Out[cur].Inline\n\n\t\t// Remove the edge from the parent to this node\n\t\tdelete(parent.Out, cur)\n\n\t\t// Reconfigure every edge from the current node to now begin at the parent.\n\t\tfor _, outEdge := range cur.Out {\n\t\t\tchild := outEdge.Dest\n\n\t\t\tdelete(child.In, cur)\n\t\t\tchild.In[parent] = outEdge\n\t\t\tparent.Out[child] = outEdge\n\n\t\t\toutEdge.Src = parent\n\t\t\toutEdge.Residual = true\n\t\t\t// If the edge from the parent to the current node and the edge from the\n\t\t\t// current node to the child are both inline, then this resulting residual\n\t\t\t// edge should also be inline\n\t\t\toutEdge.Inline = parentEdgeInline && outEdge.Inline\n\t\t}\n\t}\n\tg.RemoveRedundantEdges()\n}\n\nfunc joinLabels(s *profile.Sample) string {\n\tif len(s.Label) == 0 {\n\t\treturn \"\"\n\t}\n\n\tvar labels []string\n\tfor key, vals := range s.Label {\n\t\tfor _, v := range vals {\n\t\t\tlabels = append(labels, key+\":\"+v)\n\t\t}\n\t}\n\tsort.Strings(labels)\n\treturn strings.Join(labels, `\\n`)\n}\n\n// isNegative returns true if the node is considered as \"negative\" for the\n// purposes of drop_negative.\nfunc isNegative(n *Node) bool {\n\tswitch {\n\tcase n.Flat < 0:\n\t\treturn true\n\tcase n.Flat == 0 && n.Cum < 0:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// CreateNodes creates graph nodes for all locations in a profile. It\n// returns set of all nodes, plus a mapping of each location to the\n// set of corresponding nodes (one per location.Line).\nfunc CreateNodes(prof *profile.Profile, o *Options) (Nodes, map[uint64]Nodes) {\n\tlocations := make(map[uint64]Nodes, len(prof.Location))\n\tnm := make(NodeMap, len(prof.Location))\n\tfor _, l := range prof.Location {\n\t\tlines := l.Line\n\t\tif len(lines) == 0 {\n\t\t\tlines = []profile.Line{{}} // Create empty line to include location info.\n\t\t}\n\t\tnodes := make(Nodes, len(lines))\n\t\tfor ln := range lines {\n\t\t\tnodes[ln] = nm.findOrInsertLine(l, lines[ln], o)\n\t\t}\n\t\tlocations[l.ID] = nodes\n\t}\n\treturn nm.nodes(), locations\n}\n\nfunc (nm NodeMap) nodes() Nodes {\n\tnodes := make(Nodes, 0, len(nm))\n\tfor _, n := range nm {\n\t\tnodes = append(nodes, n)\n\t}\n\treturn nodes\n}\n\nfunc (nm NodeMap) findOrInsertLine(l *profile.Location, li profile.Line, o *Options) *Node {\n\tvar objfile string\n\tif m := l.Mapping; m != nil && m.File != \"\" {\n\t\tobjfile = m.File\n\t}\n\n\tif ni := nodeInfo(l, li, objfile, o); ni != nil {\n\t\treturn nm.FindOrInsertNode(*ni, o.KeptNodes)\n\t}\n\treturn nil\n}\n\nfunc nodeInfo(l *profile.Location, line profile.Line, objfile string, o *Options) *NodeInfo {\n\tif line.Function == nil {\n\t\treturn &NodeInfo{Address: l.Address, Objfile: objfile}\n\t}\n\tni := &NodeInfo{\n\t\tAddress: l.Address,\n\t\tLineno: int(line.Line),\n\t\tName: line.Function.Name,\n\t}\n\tif fname := line.Function.Filename; fname != \"\" {\n\t\tni.File = filepath.Clean(fname)\n\t}\n\tif o.OrigFnNames {\n\t\tni.OrigName = line.Function.SystemName\n\t}\n\tif o.ObjNames || (ni.Name == \"\" && ni.OrigName == \"\") {\n\t\tni.Objfile = objfile\n\t\tni.StartLine = int(line.Function.StartLine)\n\t}\n\treturn ni\n}\n\ntype tags struct {\n\tt []*Tag\n\tflat bool\n}\n\nfunc (t tags) Len() int { return len(t.t) }\nfunc (t tags) Swap(i, j int) { t.t[i], t.t[j] = t.t[j], t.t[i] }\nfunc (t tags) Less(i, j int) bool {\n\tif !t.flat {\n\t\tif t.t[i].Cum != t.t[j].Cum {\n\t\t\treturn abs64(t.t[i].Cum) > abs64(t.t[j].Cum)\n\t\t}\n\t}\n\tif t.t[i].Flat != t.t[j].Flat {\n\t\treturn abs64(t.t[i].Flat) > abs64(t.t[j].Flat)\n\t}\n\treturn t.t[i].Name < t.t[j].Name\n}\n\n// Sum adds the flat and cum values of a set of nodes.\nfunc (ns Nodes) Sum() (flat int64, cum int64) {\n\tfor _, n := range ns {\n\t\tflat += n.Flat\n\t\tcum += n.Cum\n\t}\n\treturn\n}\n\nfunc (n *Node) addSample(dw, w int64, labels string, numLabel map[string][]int64, numUnit map[string][]string, format func(int64, string) string, flat bool) {\n\t// Update sample value\n\tif flat {\n\t\tn.FlatDiv += dw\n\t\tn.Flat += w\n\t} else {\n\t\tn.CumDiv += dw\n\t\tn.Cum += w\n\t}\n\n\t// Add string tags\n\tif labels != \"\" {\n\t\tt := n.LabelTags.findOrAddTag(labels, \"\", 0)\n\t\tif flat {\n\t\t\tt.FlatDiv += dw\n\t\t\tt.Flat += w\n\t\t} else {\n\t\t\tt.CumDiv += dw\n\t\t\tt.Cum += w\n\t\t}\n\t}\n\n\tnumericTags := n.NumericTags[labels]\n\tif numericTags == nil {\n\t\tnumericTags = TagMap{}\n\t\tn.NumericTags[labels] = numericTags\n\t}\n\t// Add numeric tags\n\tif format == nil {\n\t\tformat = defaultLabelFormat\n\t}\n\tfor k, nvals := range numLabel {\n\t\tunits := numUnit[k]\n\t\tfor i, v := range nvals {\n\t\t\tvar t *Tag\n\t\t\tif len(units) > 0 {\n\t\t\t\tt = numericTags.findOrAddTag(format(v, units[i]), units[i], v)\n\t\t\t} else {\n\t\t\t\tt = numericTags.findOrAddTag(format(v, k), k, v)\n\t\t\t}\n\t\t\tif flat {\n\t\t\t\tt.FlatDiv += dw\n\t\t\t\tt.Flat += w\n\t\t\t} else {\n\t\t\t\tt.CumDiv += dw\n\t\t\t\tt.Cum += w\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc defaultLabelFormat(v int64, key string) string {\n\treturn strconv.FormatInt(v, 10)\n}\n\nfunc (m TagMap) findOrAddTag(label, unit string, value int64) *Tag {\n\tl := m[label]\n\tif l == nil {\n\t\tl = &Tag{\n\t\t\tName: label,\n\t\t\tUnit: unit,\n\t\t\tValue: value,\n\t\t}\n\t\tm[label] = l\n\t}\n\treturn l\n}\n\n// String returns a text representation of a graph, for debugging purposes.\nfunc (g *Graph) String() string {\n\tvar s []string\n\n\tnodeIndex := make(map[*Node]int, len(g.Nodes))\n\n\tfor i, n := range g.Nodes {\n\t\tnodeIndex[n] = i + 1\n\t}\n\n\tfor i, n := range g.Nodes {\n\t\tname := n.Info.PrintableName()\n\t\tvar in, out []int\n\n\t\tfor _, from := range n.In {\n\t\t\tin = append(in, nodeIndex[from.Src])\n\t\t}\n\t\tfor _, to := range n.Out {\n\t\t\tout = append(out, nodeIndex[to.Dest])\n\t\t}\n\t\ts = append(s, fmt.Sprintf(\"%d: %s[flat=%d cum=%d] %x -> %v \", i+1, name, n.Flat, n.Cum, in, out))\n\t}\n\treturn strings.Join(s, \"\\n\")\n}\n\n// DiscardLowFrequencyNodes returns a set of the nodes at or over a\n// specific cum value cutoff.\nfunc (g *Graph) DiscardLowFrequencyNodes(nodeCutoff int64) NodeSet {\n\treturn makeNodeSet(g.Nodes, nodeCutoff)\n}\n\n// DiscardLowFrequencyNodePtrs returns a NodePtrSet of nodes at or over a\n// specific cum value cutoff.\nfunc (g *Graph) DiscardLowFrequencyNodePtrs(nodeCutoff int64) NodePtrSet {\n\tcutNodes := getNodesAboveCumCutoff(g.Nodes, nodeCutoff)\n\tkept := make(NodePtrSet, len(cutNodes))\n\tfor _, n := range cutNodes {\n\t\tkept[n] = true\n\t}\n\treturn kept\n}\n\nfunc makeNodeSet(nodes Nodes, nodeCutoff int64) NodeSet {\n\tcutNodes := getNodesAboveCumCutoff(nodes, nodeCutoff)\n\tkept := make(NodeSet, len(cutNodes))\n\tfor _, n := range cutNodes {\n\t\tkept[n.Info] = true\n\t}\n\treturn kept\n}\n\n// getNodesAboveCumCutoff returns all the nodes which have a Cum value greater\n// than or equal to cutoff.\nfunc getNodesAboveCumCutoff(nodes Nodes, nodeCutoff int64) Nodes {\n\tcutoffNodes := make(Nodes, 0, len(nodes))\n\tfor _, n := range nodes {\n\t\tif abs64(n.Cum) < nodeCutoff {\n\t\t\tcontinue\n\t\t}\n\t\tcutoffNodes = append(cutoffNodes, n)\n\t}\n\treturn cutoffNodes\n}\n\n// TrimLowFrequencyTags removes tags that have less than\n// the specified weight.\nfunc (g *Graph) TrimLowFrequencyTags(tagCutoff int64) {\n\t// Remove nodes with value <= total*nodeFraction\n\tfor _, n := range g.Nodes {\n\t\tn.LabelTags = trimLowFreqTags(n.LabelTags, tagCutoff)\n\t\tfor s, nt := range n.NumericTags {\n\t\t\tn.NumericTags[s] = trimLowFreqTags(nt, tagCutoff)\n\t\t}\n\t}\n}\n\nfunc trimLowFreqTags(tags TagMap, minValue int64) TagMap {\n\tkept := TagMap{}\n\tfor s, t := range tags {\n\t\tif abs64(t.Flat) >= minValue || abs64(t.Cum) >= minValue {\n\t\t\tkept[s] = t\n\t\t}\n\t}\n\treturn kept\n}\n\n// TrimLowFrequencyEdges removes edges that have less than\n// the specified weight. Returns the number of edges removed\nfunc (g *Graph) TrimLowFrequencyEdges(edgeCutoff int64) int {\n\tvar droppedEdges int\n\tfor _, n := range g.Nodes {\n\t\tfor src, e := range n.In {\n\t\t\tif abs64(e.Weight) < edgeCutoff {\n\t\t\t\tdelete(n.In, src)\n\t\t\t\tdelete(src.Out, n)\n\t\t\t\tdroppedEdges++\n\t\t\t}\n\t\t}\n\t}\n\treturn droppedEdges\n}\n\n// SortNodes sorts the nodes in a graph based on a specific heuristic.\nfunc (g *Graph) SortNodes(cum bool, visualMode bool) {\n\t// Sort nodes based on requested mode\n\tswitch {\n\tcase visualMode:\n\t\t// Specialized sort to produce a more visually-interesting graph\n\t\tg.Nodes.Sort(EntropyOrder)\n\tcase cum:\n\t\tg.Nodes.Sort(CumNameOrder)\n\tdefault:\n\t\tg.Nodes.Sort(FlatNameOrder)\n\t}\n}\n\n// SelectTopNodePtrs returns a set of the top maxNodes *Node in a graph.\nfunc (g *Graph) SelectTopNodePtrs(maxNodes int, visualMode bool) NodePtrSet {\n\tset := make(NodePtrSet)\n\tfor _, node := range g.selectTopNodes(maxNodes, visualMode) {\n\t\tset[node] = true\n\t}\n\treturn set\n}\n\n// SelectTopNodes returns a set of the top maxNodes nodes in a graph.\nfunc (g *Graph) SelectTopNodes(maxNodes int, visualMode bool) NodeSet {\n\treturn makeNodeSet(g.selectTopNodes(maxNodes, visualMode), 0)\n}\n\n// selectTopNodes returns a slice of the top maxNodes nodes in a graph.\nfunc (g *Graph) selectTopNodes(maxNodes int, visualMode bool) Nodes {\n\tif maxNodes > 0 {\n\t\tif visualMode {\n\t\t\tvar count int\n\t\t\t// If generating a visual graph, count tags as nodes. Update\n\t\t\t// maxNodes to account for them.\n\t\t\tfor i, n := range g.Nodes {\n\t\t\t\ttags := countTags(n)\n\t\t\t\tif tags > maxNodelets {\n\t\t\t\t\ttags = maxNodelets\n\t\t\t\t}\n\t\t\t\tif count += tags + 1; count >= maxNodes {\n\t\t\t\t\tmaxNodes = i + 1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif maxNodes > len(g.Nodes) {\n\t\tmaxNodes = len(g.Nodes)\n\t}\n\treturn g.Nodes[:maxNodes]\n}\n\n// countTags counts the tags with flat count. This underestimates the\n// number of tags being displayed, but in practice is close enough.\nfunc countTags(n *Node) int {\n\tcount := 0\n\tfor _, e := range n.LabelTags {\n\t\tif e.Flat != 0 {\n\t\t\tcount++\n\t\t}\n\t}\n\tfor _, t := range n.NumericTags {\n\t\tfor _, e := range t {\n\t\t\tif e.Flat != 0 {\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t}\n\treturn count\n}\n\n// RemoveRedundantEdges removes residual edges if the destination can\n// be reached through another path. This is done to simplify the graph\n// while preserving connectivity.\nfunc (g *Graph) RemoveRedundantEdges() {\n\t// Walk the nodes and outgoing edges in reverse order to prefer\n\t// removing edges with the lowest weight.\n\tfor i := len(g.Nodes); i > 0; i-- {\n\t\tn := g.Nodes[i-1]\n\t\tin := n.In.Sort()\n\t\tfor j := len(in); j > 0; j-- {\n\t\t\te := in[j-1]\n\t\t\tif !e.Residual {\n\t\t\t\t// Do not remove edges heavier than a non-residual edge, to\n\t\t\t\t// avoid potential confusion.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif isRedundantEdge(e) {\n\t\t\t\tdelete(e.Src.Out, e.Dest)\n\t\t\t\tdelete(e.Dest.In, e.Src)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// isRedundantEdge determines if there is a path that allows e.Src\n// to reach e.Dest after removing e.\nfunc isRedundantEdge(e *Edge) bool {\n\tsrc, n := e.Src, e.Dest\n\tseen := map[*Node]bool{n: true}\n\tqueue := Nodes{n}\n\tfor len(queue) > 0 {\n\t\tn := queue[0]\n\t\tqueue = queue[1:]\n\t\tfor _, ie := range n.In {\n\t\t\tif e == ie || seen[ie.Src] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif ie.Src == src {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tseen[ie.Src] = true\n\t\t\tqueue = append(queue, ie.Src)\n\t\t}\n\t}\n\treturn false\n}\n\n// nodeSorter is a mechanism used to allow a report to be sorted\n// in different ways.\ntype nodeSorter struct {\n\trs Nodes\n\tless func(l, r *Node) bool\n}\n\nfunc (s nodeSorter) Len() int { return len(s.rs) }\nfunc (s nodeSorter) Swap(i, j int) { s.rs[i], s.rs[j] = s.rs[j], s.rs[i] }\nfunc (s nodeSorter) Less(i, j int) bool { return s.less(s.rs[i], s.rs[j]) }\n\n// Sort reorders a slice of nodes based on the specified ordering\n// criteria. The result is sorted in decreasing order for (absolute)\n// numeric quantities, alphabetically for text, and increasing for\n// addresses.\nfunc (ns Nodes) Sort(o NodeOrder) error {\n\tvar s nodeSorter\n\n\tswitch o {\n\tcase FlatNameOrder:\n\t\ts = nodeSorter{\n\t\t\tns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase FlatCumNameOrder:\n\t\ts = nodeSorter{\n\t\t\tns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase NameOrder:\n\t\ts = nodeSorter{\n\t\t\tns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.Name, r.Info.Name; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase FileOrder:\n\t\ts = nodeSorter{\n\t\t\tns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.File, r.Info.File; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.StartLine, r.Info.StartLine; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase AddressOrder:\n\t\ts = nodeSorter{\n\t\t\tns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.Address, r.Info.Address; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase CumNameOrder, EntropyOrder:\n\t\t// Hold scoring for score-based ordering\n\t\tvar score map[*Node]int64\n\t\tscoreOrder := func(l, r *Node) bool {\n\t\t\tif iv, jv := abs64(score[l]), abs64(score[r]); iv != jv {\n\t\t\t\treturn iv > jv\n\t\t\t}\n\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\treturn iv < jv\n\t\t\t}\n\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\treturn iv > jv\n\t\t\t}\n\t\t\treturn compareNodes(l, r)\n\t\t}\n\n\t\tswitch o {\n\t\tcase CumNameOrder:\n\t\t\tscore = make(map[*Node]int64, len(ns))\n\t\t\tfor _, n := range ns {\n\t\t\t\tscore[n] = n.Cum\n\t\t\t}\n\t\t\ts = nodeSorter{ns, scoreOrder}\n\t\tcase EntropyOrder:\n\t\t\tscore = make(map[*Node]int64, len(ns))\n\t\t\tfor _, n := range ns {\n\t\t\t\tscore[n] = entropyScore(n)\n\t\t\t}\n\t\t\ts = nodeSorter{ns, scoreOrder}\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"report: unrecognized sort ordering: %d\", o)\n\t}\n\tsort.Sort(s)\n\treturn nil\n}\n\n// compareNodes compares two nodes to provide a deterministic ordering\n// between them. Two nodes cannot have the same Node.Info value.\nfunc compareNodes(l, r *Node) bool {\n\treturn fmt.Sprint(l.Info) < fmt.Sprint(r.Info)\n}\n\n// entropyScore computes a score for a node representing how important\n// it is to include this node on a graph visualization. It is used to\n// sort the nodes and select which ones to display if we have more\n// nodes than desired in the graph. This number is computed by looking\n// at the flat and cum weights of the node and the incoming/outgoing\n// edges. The fundamental idea is to penalize nodes that have a simple\n// fallthrough from their incoming to the outgoing edge.\nfunc entropyScore(n *Node) int64 {\n\tscore := float64(0)\n\n\tif len(n.In) == 0 {\n\t\tscore++ // Favor entry nodes\n\t} else {\n\t\tscore += edgeEntropyScore(n, n.In, 0)\n\t}\n\n\tif len(n.Out) == 0 {\n\t\tscore++ // Favor leaf nodes\n\t} else {\n\t\tscore += edgeEntropyScore(n, n.Out, n.Flat)\n\t}\n\n\treturn int64(score*float64(n.Cum)) + n.Flat\n}\n\n// edgeEntropyScore computes the entropy value for a set of edges\n// coming in or out of a node. Entropy (as defined in information\n// theory) refers to the amount of information encoded by the set of\n// edges. A set of edges that have a more interesting distribution of\n// samples gets a higher score.\nfunc edgeEntropyScore(n *Node, edges EdgeMap, self int64) float64 {\n\tscore := float64(0)\n\ttotal := self\n\tfor _, e := range edges {\n\t\tif e.Weight > 0 {\n\t\t\ttotal += abs64(e.Weight)\n\t\t}\n\t}\n\tif total != 0 {\n\t\tfor _, e := range edges {\n\t\t\tfrac := float64(abs64(e.Weight)) / float64(total)\n\t\t\tscore += -frac * math.Log2(frac)\n\t\t}\n\t\tif self > 0 {\n\t\t\tfrac := float64(abs64(self)) / float64(total)\n\t\t\tscore += -frac * math.Log2(frac)\n\t\t}\n\t}\n\treturn score\n}\n\n// NodeOrder sets the ordering for a Sort operation\ntype NodeOrder int\n\n// Sorting options for node sort.\nconst (\n\tFlatNameOrder NodeOrder = iota\n\tFlatCumNameOrder\n\tCumNameOrder\n\tNameOrder\n\tFileOrder\n\tAddressOrder\n\tEntropyOrder\n)\n\n// Sort returns a slice of the edges in the map, in a consistent\n// order. The sort order is first based on the edge weight\n// (higher-to-lower) and then by the node names to avoid flakiness.\nfunc (e EdgeMap) Sort() []*Edge {\n\tel := make(edgeList, 0, len(e))\n\tfor _, w := range e {\n\t\tel = append(el, w)\n\t}\n\n\tsort.Sort(el)\n\treturn el\n}\n\n// Sum returns the total weight for a set of nodes.\nfunc (e EdgeMap) Sum() int64 {\n\tvar ret int64\n\tfor _, edge := range e {\n\t\tret += edge.Weight\n\t}\n\treturn ret\n}\n\ntype edgeList []*Edge\n\nfunc (el edgeList) Len() int {\n\treturn len(el)\n}\n\nfunc (el edgeList) Less(i, j int) bool {\n\tif el[i].Weight != el[j].Weight {\n\t\treturn abs64(el[i].Weight) > abs64(el[j].Weight)\n\t}\n\n\tfrom1 := el[i].Src.Info.PrintableName()\n\tfrom2 := el[j].Src.Info.PrintableName()\n\tif from1 != from2 {\n\t\treturn from1 < from2\n\t}\n\n\tto1 := el[i].Dest.Info.PrintableName()\n\tto2 := el[j].Dest.Info.PrintableName()\n\n\treturn to1 < to2\n}\n\nfunc (el edgeList) Swap(i, j int) {\n\tel[i], el[j] = el[j], el[i]\n}\n\nfunc abs64(i int64) int64 {\n\tif i < 0 {\n\t\treturn -i\n\t}\n\treturn i\n}\n"}} | |
[Trace - 19:24:28.651 PM] Sending notification 'textDocument/didOpen'. | |
Params: {"textDocument":{"uri":"git:/home/jake/zikaeroh/pprof/internal/graph/graph.go?%7B%22path%22%3A%22%2Fhome%2Fjake%2Fzikaeroh%2Fpprof%2Finternal%2Fgraph%2Fgraph.go%22%2C%22ref%22%3A%22~%22%7D","languageId":"go","version":1,"text":"// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package graph collects a set of samples into a directed graph.\npackage graph\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/google/pprof/profile\"\n)\n\nvar (\n\t// Removes package name and method arugments for Java method names.\n\t// See tests for examples.\n\tjavaRegExp = regexp.MustCompile(`^(?:[a-z]\\w*\\.)*([A-Z][\\w\\$]*\\.(?:<init>|[a-z][\\w\\$]*(?:\\$\\d+)?))(?:(?:\\()|$)`)\n\t// Removes package name and method arugments for Go function names.\n\t// See tests for examples.\n\tgoRegExp = regexp.MustCompile(`^(?:[\\w\\-\\.]+\\/)+(.+)`)\n\t// Checks for a package name that could be a module version.\n\tgoVerRegExp = regexp.MustCompile(`^v[2-9]+\\.`)\n\t// Strips C++ namespace prefix from a C++ function / method name.\n\t// NOTE: Make sure to keep the template parameters in the name. Normally,\n\t// template parameters are stripped from the C++ names but when\n\t// -symbolize=demangle=templates flag is used, they will not be.\n\t// See tests for examples.\n\tcppRegExp = regexp.MustCompile(`^(?:[_a-zA-Z]\\w*::)+(_*[A-Z]\\w*::~?[_a-zA-Z]\\w*(?:<.*>)?)`)\n\tcppAnonymousPrefixRegExp = regexp.MustCompile(`^\\(anonymous namespace\\)::`)\n)\n\n// Graph summarizes a performance profile into a format that is\n// suitable for visualization.\ntype Graph struct {\n\tNodes Nodes\n}\n\n// Options encodes the options for constructing a graph\ntype Options struct {\n\tSampleValue func(s []int64) int64 // Function to compute the value of a sample\n\tSampleMeanDivisor func(s []int64) int64 // Function to compute the divisor for mean graphs, or nil\n\tFormatTag func(int64, string) string // Function to format a sample tag value into a string\n\tObjNames bool // Always preserve obj filename\n\tOrigFnNames bool // Preserve original (eg mangled) function names\n\n\tCallTree bool // Build a tree instead of a graph\n\tDropNegative bool // Drop nodes with overall negative values\n\n\tKeptNodes NodeSet // If non-nil, only use nodes in this set\n}\n\n// Nodes is an ordered collection of graph nodes.\ntype Nodes []*Node\n\n// Node is an entry on a profiling report. It represents a unique\n// program location.\ntype Node struct {\n\t// Info describes the source location associated to this node.\n\tInfo NodeInfo\n\n\t// Function represents the function that this node belongs to. On\n\t// graphs with sub-function resolution (eg line number or\n\t// addresses), two nodes in a NodeMap that are part of the same\n\t// function have the same value of Node.Function. If the Node\n\t// represents the whole function, it points back to itself.\n\tFunction *Node\n\n\t// Values associated to this node. Flat is exclusive to this node,\n\t// Cum includes all descendents.\n\tFlat, FlatDiv, Cum, CumDiv int64\n\n\t// In and out Contains the nodes immediately reaching or reached by\n\t// this node.\n\tIn, Out EdgeMap\n\n\t// LabelTags provide additional information about subsets of a sample.\n\tLabelTags TagMap\n\n\t// NumericTags provide additional values for subsets of a sample.\n\t// Numeric tags are optionally associated to a label tag. The key\n\t// for NumericTags is the name of the LabelTag they are associated\n\t// to, or \"\" for numeric tags not associated to a label tag.\n\tNumericTags map[string]TagMap\n}\n\n// FlatValue returns the exclusive value for this node, computing the\n// mean if a divisor is available.\nfunc (n *Node) FlatValue() int64 {\n\tif n.FlatDiv == 0 {\n\t\treturn n.Flat\n\t}\n\treturn n.Flat / n.FlatDiv\n}\n\n// CumValue returns the inclusive value for this node, computing the\n// mean if a divisor is available.\nfunc (n *Node) CumValue() int64 {\n\tif n.CumDiv == 0 {\n\t\treturn n.Cum\n\t}\n\treturn n.Cum / n.CumDiv\n}\n\n// AddToEdge increases the weight of an edge between two nodes. If\n// there isn't such an edge one is created.\nfunc (n *Node) AddToEdge(to *Node, v int64, residual, inline bool) {\n\tn.AddToEdgeDiv(to, 0, v, residual, inline)\n}\n\n// AddToEdgeDiv increases the weight of an edge between two nodes. If\n// there isn't such an edge one is created.\nfunc (n *Node) AddToEdgeDiv(to *Node, dv, v int64, residual, inline bool) {\n\tif n.Out[to] != to.In[n] {\n\t\tpanic(fmt.Errorf(\"asymmetric edges %v %v\", *n, *to))\n\t}\n\n\tif e := n.Out[to]; e != nil {\n\t\te.WeightDiv += dv\n\t\te.Weight += v\n\t\tif residual {\n\t\t\te.Residual = true\n\t\t}\n\t\tif !inline {\n\t\t\te.Inline = false\n\t\t}\n\t\treturn\n\t}\n\n\tinfo := &Edge{Src: n, Dest: to, WeightDiv: dv, Weight: v, Residual: residual, Inline: inline}\n\tn.Out[to] = info\n\tto.In[n] = info\n}\n\n// NodeInfo contains the attributes for a node.\ntype NodeInfo struct {\n\tName string\n\tOrigName string\n\tAddress uint64\n\tFile string\n\tStartLine, Lineno int\n\tObjfile string\n}\n\n// PrintableName calls the Node's Formatter function with a single space separator.\nfunc (i *NodeInfo) PrintableName() string {\n\treturn strings.Join(i.NameComponents(), \" \")\n}\n\n// NameComponents returns the components of the printable name to be used for a node.\nfunc (i *NodeInfo) NameComponents() []string {\n\tvar name []string\n\tif i.Address != 0 {\n\t\tname = append(name, fmt.Sprintf(\"%016x\", i.Address))\n\t}\n\tif fun := i.Name; fun != \"\" {\n\t\tname = append(name, fun)\n\t}\n\n\tswitch {\n\tcase i.Lineno != 0:\n\t\t// User requested line numbers, provide what we have.\n\t\tname = append(name, fmt.Sprintf(\"%s:%d\", i.File, i.Lineno))\n\tcase i.File != \"\":\n\t\t// User requested file name, provide it.\n\t\tname = append(name, i.File)\n\tcase i.Name != \"\":\n\t\t// User requested function name. It was already included.\n\tcase i.Objfile != \"\":\n\t\t// Only binary name is available\n\t\tname = append(name, \"[\"+filepath.Base(i.Objfile)+\"]\")\n\tdefault:\n\t\t// Do not leave it empty if there is no information at all.\n\t\tname = append(name, \"<unknown>\")\n\t}\n\treturn name\n}\n\n// NodeMap maps from a node info struct to a node. It is used to merge\n// report entries with the same info.\ntype NodeMap map[NodeInfo]*Node\n\n// NodeSet is a collection of node info structs.\ntype NodeSet map[NodeInfo]bool\n\n// NodePtrSet is a collection of nodes. Trimming a graph or tree requires a set\n// of objects which uniquely identify the nodes to keep. In a graph, NodeInfo\n// works as a unique identifier; however, in a tree multiple nodes may share\n// identical NodeInfos. A *Node does uniquely identify a node so we can use that\n// instead. Though a *Node also uniquely identifies a node in a graph,\n// currently, during trimming, graphs are rebuilt from scratch using only the\n// NodeSet, so there would not be the required context of the initial graph to\n// allow for the use of *Node.\ntype NodePtrSet map[*Node]bool\n\n// FindOrInsertNode takes the info for a node and either returns a matching node\n// from the node map if one exists, or adds one to the map if one does not.\n// If kept is non-nil, nodes are only added if they can be located on it.\nfunc (nm NodeMap) FindOrInsertNode(info NodeInfo, kept NodeSet) *Node {\n\tif kept != nil {\n\t\tif _, ok := kept[info]; !ok {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tif n, ok := nm[info]; ok {\n\t\treturn n\n\t}\n\n\tn := &Node{\n\t\tInfo: info,\n\t\tIn: make(EdgeMap),\n\t\tOut: make(EdgeMap),\n\t\tLabelTags: make(TagMap),\n\t\tNumericTags: make(map[string]TagMap),\n\t}\n\tnm[info] = n\n\tif info.Address == 0 && info.Lineno == 0 {\n\t\t// This node represents the whole function, so point Function\n\t\t// back to itself.\n\t\tn.Function = n\n\t\treturn n\n\t}\n\t// Find a node that represents the whole function.\n\tinfo.Address = 0\n\tinfo.Lineno = 0\n\tn.Function = nm.FindOrInsertNode(info, nil)\n\treturn n\n}\n\n// EdgeMap is used to represent the incoming/outgoing edges from a node.\ntype EdgeMap map[*Node]*Edge\n\n// Edge contains any attributes to be represented about edges in a graph.\ntype Edge struct {\n\tSrc, Dest *Node\n\t// The summary weight of the edge\n\tWeight, WeightDiv int64\n\n\t// residual edges connect nodes that were connected through a\n\t// separate node, which has been removed from the report.\n\tResidual bool\n\t// An inline edge represents a call that was inlined into the caller.\n\tInline bool\n}\n\n// WeightValue returns the weight value for this edge, normalizing if a\n// divisor is available.\nfunc (e *Edge) WeightValue() int64 {\n\tif e.WeightDiv == 0 {\n\t\treturn e.Weight\n\t}\n\treturn e.Weight / e.WeightDiv\n}\n\n// Tag represent sample annotations\ntype Tag struct {\n\tName string\n\tUnit string // Describe the value, \"\" for non-numeric tags\n\tValue int64\n\tFlat, FlatDiv int64\n\tCum, CumDiv int64\n}\n\n// FlatValue returns the exclusive value for this tag, computing the\n// mean if a divisor is available.\nfunc (t *Tag) FlatValue() int64 {\n\tif t.FlatDiv == 0 {\n\t\treturn t.Flat\n\t}\n\treturn t.Flat / t.FlatDiv\n}\n\n// CumValue returns the inclusive value for this tag, computing the\n// mean if a divisor is available.\nfunc (t *Tag) CumValue() int64 {\n\tif t.CumDiv == 0 {\n\t\treturn t.Cum\n\t}\n\treturn t.Cum / t.CumDiv\n}\n\n// TagMap is a collection of tags, classified by their name.\ntype TagMap map[string]*Tag\n\n// SortTags sorts a slice of tags based on their weight.\nfunc SortTags(t []*Tag, flat bool) []*Tag {\n\tts := tags{t, flat}\n\tsort.Sort(ts)\n\treturn ts.t\n}\n\n// New summarizes performance data from a profile into a graph.\nfunc New(prof *profile.Profile, o *Options) *Graph {\n\tif o.CallTree {\n\t\treturn newTree(prof, o)\n\t}\n\tg, _ := newGraph(prof, o)\n\treturn g\n}\n\n// newGraph computes a graph from a profile. It returns the graph, and\n// a map from the profile location indices to the corresponding graph\n// nodes.\nfunc newGraph(prof *profile.Profile, o *Options) (*Graph, map[uint64]Nodes) {\n\tnodes, locationMap := CreateNodes(prof, o)\n\tfor _, sample := range prof.Sample {\n\t\tvar w, dw int64\n\t\tw = o.SampleValue(sample.Value)\n\t\tif o.SampleMeanDivisor != nil {\n\t\t\tdw = o.SampleMeanDivisor(sample.Value)\n\t\t}\n\t\tif dw == 0 && w == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tseenNode := make(map[*Node]bool, len(sample.Location))\n\t\tseenEdge := make(map[nodePair]bool, len(sample.Location))\n\t\tvar parent *Node\n\t\t// A residual edge goes over one or more nodes that were not kept.\n\t\tresidual := false\n\n\t\tlabels := joinLabels(sample)\n\t\t// Group the sample frames, based on a global map.\n\t\tfor i := len(sample.Location) - 1; i >= 0; i-- {\n\t\t\tl := sample.Location[i]\n\t\t\tlocNodes := locationMap[l.ID]\n\t\t\tfor ni := len(locNodes) - 1; ni >= 0; ni-- {\n\t\t\t\tn := locNodes[ni]\n\t\t\t\tif n == nil {\n\t\t\t\t\tresidual = true\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Add cum weight to all nodes in stack, avoiding double counting.\n\t\t\t\tif _, ok := seenNode[n]; !ok {\n\t\t\t\t\tseenNode[n] = true\n\t\t\t\t\tn.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, false)\n\t\t\t\t}\n\t\t\t\t// Update edge weights for all edges in stack, avoiding double counting.\n\t\t\t\tif _, ok := seenEdge[nodePair{n, parent}]; !ok && parent != nil && n != parent {\n\t\t\t\t\tseenEdge[nodePair{n, parent}] = true\n\t\t\t\t\tparent.AddToEdgeDiv(n, dw, w, residual, ni != len(locNodes)-1)\n\t\t\t\t}\n\t\t\t\tparent = n\n\t\t\t\tresidual = false\n\t\t\t}\n\t\t}\n\t\tif parent != nil && !residual {\n\t\t\t// Add flat weight to leaf node.\n\t\t\tparent.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, true)\n\t\t}\n\t}\n\n\treturn selectNodesForGraph(nodes, o.DropNegative), locationMap\n}\n\nfunc selectNodesForGraph(nodes Nodes, dropNegative bool) *Graph {\n\t// Collect nodes into a graph.\n\tgNodes := make(Nodes, 0, len(nodes))\n\tfor _, n := range nodes {\n\t\tif n == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif n.Cum == 0 && n.Flat == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif dropNegative && isNegative(n) {\n\t\t\tcontinue\n\t\t}\n\t\tgNodes = append(gNodes, n)\n\t}\n\treturn &Graph{gNodes}\n}\n\ntype nodePair struct {\n\tsrc, dest *Node\n}\n\nfunc newTree(prof *profile.Profile, o *Options) (g *Graph) {\n\tparentNodeMap := make(map[*Node]NodeMap, len(prof.Sample))\n\tfor _, sample := range prof.Sample {\n\t\tvar w, dw int64\n\t\tw = o.SampleValue(sample.Value)\n\t\tif o.SampleMeanDivisor != nil {\n\t\t\tdw = o.SampleMeanDivisor(sample.Value)\n\t\t}\n\t\tif dw == 0 && w == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tvar parent *Node\n\t\tlabels := joinLabels(sample)\n\t\t// Group the sample frames, based on a per-node map.\n\t\tfor i := len(sample.Location) - 1; i >= 0; i-- {\n\t\t\tl := sample.Location[i]\n\t\t\tlines := l.Line\n\t\t\tif len(lines) == 0 {\n\t\t\t\tlines = []profile.Line{{}} // Create empty line to include location info.\n\t\t\t}\n\t\t\tfor lidx := len(lines) - 1; lidx >= 0; lidx-- {\n\t\t\t\tnodeMap := parentNodeMap[parent]\n\t\t\t\tif nodeMap == nil {\n\t\t\t\t\tnodeMap = make(NodeMap)\n\t\t\t\t\tparentNodeMap[parent] = nodeMap\n\t\t\t\t}\n\t\t\t\tn := nodeMap.findOrInsertLine(l, lines[lidx], o)\n\t\t\t\tif n == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tn.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, false)\n\t\t\t\tif parent != nil {\n\t\t\t\t\tparent.AddToEdgeDiv(n, dw, w, false, lidx != len(lines)-1)\n\t\t\t\t}\n\t\t\t\tparent = n\n\t\t\t}\n\t\t}\n\t\tif parent != nil {\n\t\t\tparent.addSample(dw, w, labels, sample.NumLabel, sample.NumUnit, o.FormatTag, true)\n\t\t}\n\t}\n\n\tnodes := make(Nodes, len(prof.Location))\n\tfor _, nm := range parentNodeMap {\n\t\tnodes = append(nodes, nm.nodes()...)\n\t}\n\treturn selectNodesForGraph(nodes, o.DropNegative)\n}\n\n// ShortenFunctionName returns a shortened version of a function's name.\nfunc ShortenFunctionName(f string) string {\n\tf = cppAnonymousPrefixRegExp.ReplaceAllString(f, \"\")\n\tfor _, re := range []*regexp.Regexp{goRegExp, javaRegExp, cppRegExp} {\n\t\tif matches := re.FindStringSubmatch(f); len(matches) >= 2 {\n\t\t\tname := strings.Join(matches[1:], \"\")\n\t\t\tif re == goRegExp {\n\t\t\t\treturn shortenGoFunc(f, name)\n\t\t\t}\n\t\t\treturn name\n\t\t}\n\t}\n\treturn f\n}\n\nfunc shortenGoFunc(f string, name string) string {\n\tif !goVerRegExp.MatchString(name) {\n\t\treturn name\n\t}\n\n\t// The shortened name could start with a module version (like \"v2\"). Go back one slash.\n\tend := len(f) - len(name) - 1\n\tif end >= 0 {\n\t\tprefix := f[:end]\n\t\tif idx := strings.LastIndex(prefix, \"/\"); idx >= 0 {\n\t\t\tend = idx\n\t\t}\n\t}\n\n\treturn f[end+1:]\n}\n\n// TrimTree trims a Graph in forest form, keeping only the nodes in kept. This\n// will not work correctly if even a single node has multiple parents.\nfunc (g *Graph) TrimTree(kept NodePtrSet) {\n\t// Creates a new list of nodes\n\toldNodes := g.Nodes\n\tg.Nodes = make(Nodes, 0, len(kept))\n\n\tfor _, cur := range oldNodes {\n\t\t// A node may not have multiple parents\n\t\tif len(cur.In) > 1 {\n\t\t\tpanic(\"TrimTree only works on trees\")\n\t\t}\n\n\t\t// If a node should be kept, add it to the new list of nodes\n\t\tif _, ok := kept[cur]; ok {\n\t\t\tg.Nodes = append(g.Nodes, cur)\n\t\t\tcontinue\n\t\t}\n\n\t\t// If a node has no parents, then delete all of the in edges of its\n\t\t// children to make them each roots of their own trees.\n\t\tif len(cur.In) == 0 {\n\t\t\tfor _, outEdge := range cur.Out {\n\t\t\t\tdelete(outEdge.Dest.In, cur)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Get the parent. This works since at this point cur.In must contain only\n\t\t// one element.\n\t\tif len(cur.In) != 1 {\n\t\t\tpanic(\"Get parent assertion failed. cur.In expected to be of length 1.\")\n\t\t}\n\t\tvar parent *Node\n\t\tfor _, edge := range cur.In {\n\t\t\tparent = edge.Src\n\t\t}\n\n\t\tparentEdgeInline := parent.Out[cur].Inline\n\n\t\t// Remove the edge from the parent to this node\n\t\tdelete(parent.Out, cur)\n\n\t\t// Reconfigure every edge from the current node to now begin at the parent.\n\t\tfor _, outEdge := range cur.Out {\n\t\t\tchild := outEdge.Dest\n\n\t\t\tdelete(child.In, cur)\n\t\t\tchild.In[parent] = outEdge\n\t\t\tparent.Out[child] = outEdge\n\n\t\t\toutEdge.Src = parent\n\t\t\toutEdge.Residual = true\n\t\t\t// If the edge from the parent to the current node and the edge from the\n\t\t\t// current node to the child are both inline, then this resulting residual\n\t\t\t// edge should also be inline\n\t\t\toutEdge.Inline = parentEdgeInline && outEdge.Inline\n\t\t}\n\t}\n\tg.RemoveRedundantEdges()\n}\n\nfunc joinLabels(s *profile.Sample) string {\n\tif len(s.Label) == 0 {\n\t\treturn \"\"\n\t}\n\n\tvar labels []string\n\tfor key, vals := range s.Label {\n\t\tfor _, v := range vals {\n\t\t\tlabels = append(labels, key+\":\"+v)\n\t\t}\n\t}\n\tsort.Strings(labels)\n\treturn strings.Join(labels, `\\n`)\n}\n\n// isNegative returns true if the node is considered as \"negative\" for the\n// purposes of drop_negative.\nfunc isNegative(n *Node) bool {\n\tswitch {\n\tcase n.Flat < 0:\n\t\treturn true\n\tcase n.Flat == 0 && n.Cum < 0:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// CreateNodes creates graph nodes for all locations in a profile. It\n// returns set of all nodes, plus a mapping of each location to the\n// set of corresponding nodes (one per location.Line).\nfunc CreateNodes(prof *profile.Profile, o *Options) (Nodes, map[uint64]Nodes) {\n\tlocations := make(map[uint64]Nodes, len(prof.Location))\n\tnm := make(NodeMap, len(prof.Location))\n\tfor _, l := range prof.Location {\n\t\tlines := l.Line\n\t\tif len(lines) == 0 {\n\t\t\tlines = []profile.Line{{}} // Create empty line to include location info.\n\t\t}\n\t\tnodes := make(Nodes, len(lines))\n\t\tfor ln := range lines {\n\t\t\tnodes[ln] = nm.findOrInsertLine(l, lines[ln], o)\n\t\t}\n\t\tlocations[l.ID] = nodes\n\t}\n\treturn nm.nodes(), locations\n}\n\nfunc (nm NodeMap) nodes() Nodes {\n\tnodes := make(Nodes, 0, len(nm))\n\tfor _, n := range nm {\n\t\tnodes = append(nodes, n)\n\t}\n\treturn nodes\n}\n\nfunc (nm NodeMap) findOrInsertLine(l *profile.Location, li profile.Line, o *Options) *Node {\n\tvar objfile string\n\tif m := l.Mapping; m != nil && m.File != \"\" {\n\t\tobjfile = m.File\n\t}\n\n\tif ni := nodeInfo(l, li, objfile, o); ni != nil {\n\t\treturn nm.FindOrInsertNode(*ni, o.KeptNodes)\n\t}\n\treturn nil\n}\n\nfunc nodeInfo(l *profile.Location, line profile.Line, objfile string, o *Options) *NodeInfo {\n\tif line.Function == nil {\n\t\treturn &NodeInfo{Address: l.Address, Objfile: objfile}\n\t}\n\tni := &NodeInfo{\n\t\tAddress: l.Address,\n\t\tLineno: int(line.Line),\n\t\tName: line.Function.Name,\n\t}\n\tif fname := line.Function.Filename; fname != \"\" {\n\t\tni.File = filepath.Clean(fname)\n\t}\n\tif o.OrigFnNames {\n\t\tni.OrigName = line.Function.SystemName\n\t}\n\tif o.ObjNames || (ni.Name == \"\" && ni.OrigName == \"\") {\n\t\tni.Objfile = objfile\n\t\tni.StartLine = int(line.Function.StartLine)\n\t}\n\treturn ni\n}\n\ntype tags struct {\n\tt []*Tag\n\tflat bool\n}\n\nfunc (t tags) Len() int { return len(t.t) }\nfunc (t tags) Swap(i, j int) { t.t[i], t.t[j] = t.t[j], t.t[i] }\nfunc (t tags) Less(i, j int) bool {\n\tif !t.flat {\n\t\tif t.t[i].Cum != t.t[j].Cum {\n\t\t\treturn abs64(t.t[i].Cum) > abs64(t.t[j].Cum)\n\t\t}\n\t}\n\tif t.t[i].Flat != t.t[j].Flat {\n\t\treturn abs64(t.t[i].Flat) > abs64(t.t[j].Flat)\n\t}\n\treturn t.t[i].Name < t.t[j].Name\n}\n\n// Sum adds the flat and cum values of a set of nodes.\nfunc (ns Nodes) Sum() (flat int64, cum int64) {\n\tfor _, n := range ns {\n\t\tflat += n.Flat\n\t\tcum += n.Cum\n\t}\n\treturn\n}\n\nfunc (n *Node) addSample(dw, w int64, labels string, numLabel map[string][]int64, numUnit map[string][]string, format func(int64, string) string, flat bool) {\n\t// Update sample value\n\tif flat {\n\t\tn.FlatDiv += dw\n\t\tn.Flat += w\n\t} else {\n\t\tn.CumDiv += dw\n\t\tn.Cum += w\n\t}\n\n\t// Add string tags\n\tif labels != \"\" {\n\t\tt := n.LabelTags.findOrAddTag(labels, \"\", 0)\n\t\tif flat {\n\t\t\tt.FlatDiv += dw\n\t\t\tt.Flat += w\n\t\t} else {\n\t\t\tt.CumDiv += dw\n\t\t\tt.Cum += w\n\t\t}\n\t}\n\n\tnumericTags := n.NumericTags[labels]\n\tif numericTags == nil {\n\t\tnumericTags = TagMap{}\n\t\tn.NumericTags[labels] = numericTags\n\t}\n\t// Add numeric tags\n\tif format == nil {\n\t\tformat = defaultLabelFormat\n\t}\n\tfor k, nvals := range numLabel {\n\t\tunits := numUnit[k]\n\t\tfor i, v := range nvals {\n\t\t\tvar t *Tag\n\t\t\tif len(units) > 0 {\n\t\t\t\tt = numericTags.findOrAddTag(format(v, units[i]), units[i], v)\n\t\t\t} else {\n\t\t\t\tt = numericTags.findOrAddTag(format(v, k), k, v)\n\t\t\t}\n\t\t\tif flat {\n\t\t\t\tt.FlatDiv += dw\n\t\t\t\tt.Flat += w\n\t\t\t} else {\n\t\t\t\tt.CumDiv += dw\n\t\t\t\tt.Cum += w\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc defaultLabelFormat(v int64, key string) string {\n\treturn strconv.FormatInt(v, 10)\n}\n\nfunc (m TagMap) findOrAddTag(label, unit string, value int64) *Tag {\n\tl := m[label]\n\tif l == nil {\n\t\tl = &Tag{\n\t\t\tName: label,\n\t\t\tUnit: unit,\n\t\t\tValue: value,\n\t\t}\n\t\tm[label] = l\n\t}\n\treturn l\n}\n\n// String returns a text representation of a graph, for debugging purposes.\nfunc (g *Graph) String() string {\n\tvar s []string\n\n\tnodeIndex := make(map[*Node]int, len(g.Nodes))\n\n\tfor i, n := range g.Nodes {\n\t\tnodeIndex[n] = i + 1\n\t}\n\n\tfor i, n := range g.Nodes {\n\t\tname := n.Info.PrintableName()\n\t\tvar in, out []int\n\n\t\tfor _, from := range n.In {\n\t\t\tin = append(in, nodeIndex[from.Src])\n\t\t}\n\t\tfor _, to := range n.Out {\n\t\t\tout = append(out, nodeIndex[to.Dest])\n\t\t}\n\t\ts = append(s, fmt.Sprintf(\"%d: %s[flat=%d cum=%d] %x -> %v \", i+1, name, n.Flat, n.Cum, in, out))\n\t}\n\treturn strings.Join(s, \"\\n\")\n}\n\n// DiscardLowFrequencyNodes returns a set of the nodes at or over a\n// specific cum value cutoff.\nfunc (g *Graph) DiscardLowFrequencyNodes(nodeCutoff int64) NodeSet {\n\treturn makeNodeSet(g.Nodes, nodeCutoff)\n}\n\n// DiscardLowFrequencyNodePtrs returns a NodePtrSet of nodes at or over a\n// specific cum value cutoff.\nfunc (g *Graph) DiscardLowFrequencyNodePtrs(nodeCutoff int64) NodePtrSet {\n\tcutNodes := getNodesAboveCumCutoff(g.Nodes, nodeCutoff)\n\tkept := make(NodePtrSet, len(cutNodes))\n\tfor _, n := range cutNodes {\n\t\tkept[n] = true\n\t}\n\treturn kept\n}\n\nfunc makeNodeSet(nodes Nodes, nodeCutoff int64) NodeSet {\n\tcutNodes := getNodesAboveCumCutoff(nodes, nodeCutoff)\n\tkept := make(NodeSet, len(cutNodes))\n\tfor _, n := range cutNodes {\n\t\tkept[n.Info] = true\n\t}\n\treturn kept\n}\n\n// getNodesAboveCumCutoff returns all the nodes which have a Cum value greater\n// than or equal to cutoff.\nfunc getNodesAboveCumCutoff(nodes Nodes, nodeCutoff int64) Nodes {\n\tcutoffNodes := make(Nodes, 0, len(nodes))\n\tfor _, n := range nodes {\n\t\tif abs64(n.Cum) < nodeCutoff {\n\t\t\tcontinue\n\t\t}\n\t\tcutoffNodes = append(cutoffNodes, n)\n\t}\n\treturn cutoffNodes\n}\n\n// TrimLowFrequencyTags removes tags that have less than\n// the specified weight.\nfunc (g *Graph) TrimLowFrequencyTags(tagCutoff int64) {\n\t// Remove nodes with value <= total*nodeFraction\n\tfor _, n := range g.Nodes {\n\t\tn.LabelTags = trimLowFreqTags(n.LabelTags, tagCutoff)\n\t\tfor s, nt := range n.NumericTags {\n\t\t\tn.NumericTags[s] = trimLowFreqTags(nt, tagCutoff)\n\t\t}\n\t}\n}\n\nfunc trimLowFreqTags(tags TagMap, minValue int64) TagMap {\n\tkept := TagMap{}\n\tfor s, t := range tags {\n\t\tif abs64(t.Flat) >= minValue || abs64(t.Cum) >= minValue {\n\t\t\tkept[s] = t\n\t\t}\n\t}\n\treturn kept\n}\n\n// TrimLowFrequencyEdges removes edges that have less than\n// the specified weight. Returns the number of edges removed\nfunc (g *Graph) TrimLowFrequencyEdges(edgeCutoff int64) int {\n\tvar droppedEdges int\n\tfor _, n := range g.Nodes {\n\t\tfor src, e := range n.In {\n\t\t\tif abs64(e.Weight) < edgeCutoff {\n\t\t\t\tdelete(n.In, src)\n\t\t\t\tdelete(src.Out, n)\n\t\t\t\tdroppedEdges++\n\t\t\t}\n\t\t}\n\t}\n\treturn droppedEdges\n}\n\n// SortNodes sorts the nodes in a graph based on a specific heuristic.\nfunc (g *Graph) SortNodes(cum bool, visualMode bool) {\n\t// Sort nodes based on requested mode\n\tswitch {\n\tcase visualMode:\n\t\t// Specialized sort to produce a more visually-interesting graph\n\t\tg.Nodes.Sort(EntropyOrder)\n\tcase cum:\n\t\tg.Nodes.Sort(CumNameOrder)\n\tdefault:\n\t\tg.Nodes.Sort(FlatNameOrder)\n\t}\n}\n\n// SelectTopNodePtrs returns a set of the top maxNodes *Node in a graph.\nfunc (g *Graph) SelectTopNodePtrs(maxNodes int, visualMode bool) NodePtrSet {\n\tset := make(NodePtrSet)\n\tfor _, node := range g.selectTopNodes(maxNodes, visualMode) {\n\t\tset[node] = true\n\t}\n\treturn set\n}\n\n// SelectTopNodes returns a set of the top maxNodes nodes in a graph.\nfunc (g *Graph) SelectTopNodes(maxNodes int, visualMode bool) NodeSet {\n\treturn makeNodeSet(g.selectTopNodes(maxNodes, visualMode), 0)\n}\n\n// selectTopNodes returns a slice of the top maxNodes nodes in a graph.\nfunc (g *Graph) selectTopNodes(maxNodes int, visualMode bool) Nodes {\n\tif maxNodes > 0 {\n\t\tif visualMode {\n\t\t\tvar count int\n\t\t\t// If generating a visual graph, count tags as nodes. Update\n\t\t\t// maxNodes to account for them.\n\t\t\tfor i, n := range g.Nodes {\n\t\t\t\ttags := countTags(n)\n\t\t\t\tif tags > maxNodelets {\n\t\t\t\t\ttags = maxNodelets\n\t\t\t\t}\n\t\t\t\tif count += tags + 1; count >= maxNodes {\n\t\t\t\t\tmaxNodes = i + 1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif maxNodes > len(g.Nodes) {\n\t\tmaxNodes = len(g.Nodes)\n\t}\n\treturn g.Nodes[:maxNodes]\n}\n\n// countTags counts the tags with flat count. This underestimates the\n// number of tags being displayed, but in practice is close enough.\nfunc countTags(n *Node) int {\n\tcount := 0\n\tfor _, e := range n.LabelTags {\n\t\tif e.Flat != 0 {\n\t\t\tcount++\n\t\t}\n\t}\n\tfor _, t := range n.NumericTags {\n\t\tfor _, e := range t {\n\t\t\tif e.Flat != 0 {\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t}\n\treturn count\n}\n\n// RemoveRedundantEdges removes residual edges if the destination can\n// be reached through another path. This is done to simplify the graph\n// while preserving connectivity.\nfunc (g *Graph) RemoveRedundantEdges() {\n\t// Walk the nodes and outgoing edges in reverse order to prefer\n\t// removing edges with the lowest weight.\n\tfor i := len(g.Nodes); i > 0; i-- {\n\t\tn := g.Nodes[i-1]\n\t\tin := n.In.Sort()\n\t\tfor j := len(in); j > 0; j-- {\n\t\t\te := in[j-1]\n\t\t\tif !e.Residual {\n\t\t\t\t// Do not remove edges heavier than a non-residual edge, to\n\t\t\t\t// avoid potential confusion.\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif isRedundantEdge(e) {\n\t\t\t\tdelete(e.Src.Out, e.Dest)\n\t\t\t\tdelete(e.Dest.In, e.Src)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// isRedundantEdge determines if there is a path that allows e.Src\n// to reach e.Dest after removing e.\nfunc isRedundantEdge(e *Edge) bool {\n\tsrc, n := e.Src, e.Dest\n\tseen := map[*Node]bool{n: true}\n\tqueue := Nodes{n}\n\tfor len(queue) > 0 {\n\t\tn := queue[0]\n\t\tqueue = queue[1:]\n\t\tfor _, ie := range n.In {\n\t\t\tif e == ie || seen[ie.Src] {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif ie.Src == src {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tseen[ie.Src] = true\n\t\t\tqueue = append(queue, ie.Src)\n\t\t}\n\t}\n\treturn false\n}\n\n// nodeSorter is a mechanism used to allow a report to be sorted\n// in different ways.\ntype nodeSorter struct {\n\trs Nodes\n\tless func(l, r *Node) bool\n}\n\nfunc (s nodeSorter) Len() int { return len(s.rs) }\nfunc (s nodeSorter) Swap(i, j int) { s.rs[i], s.rs[j] = s.rs[j], s.rs[i] }\nfunc (s nodeSorter) Less(i, j int) bool { return s.less(s.rs[i], s.rs[j]) }\n\n// Sort reorders a slice of nodes based on the specified ordering\n// criteria. The result is sorted in decreasing order for (absolute)\n// numeric quantities, alphabetically for text, and increasing for\n// addresses.\nfunc (ns Nodes) Sort(o NodeOrder) error {\n\tvar s nodeSorter\n\n\tswitch o {\n\tcase FlatNameOrder:\n\t\ts = nodeSorter{ns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase FlatCumNameOrder:\n\t\ts = nodeSorter{ns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {\n\t\t\t\t\treturn iv > jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase NameOrder:\n\t\ts = nodeSorter{ns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.Name, r.Info.Name; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase FileOrder:\n\t\ts = nodeSorter{ns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.File, r.Info.File; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\tif iv, jv := l.Info.StartLine, r.Info.StartLine; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase AddressOrder:\n\t\ts = nodeSorter{ns,\n\t\t\tfunc(l, r *Node) bool {\n\t\t\t\tif iv, jv := l.Info.Address, r.Info.Address; iv != jv {\n\t\t\t\t\treturn iv < jv\n\t\t\t\t}\n\t\t\t\treturn compareNodes(l, r)\n\t\t\t},\n\t\t}\n\tcase CumNameOrder, EntropyOrder:\n\t\t// Hold scoring for score-based ordering\n\t\tvar score map[*Node]int64\n\t\tscoreOrder := func(l, r *Node) bool {\n\t\t\tif iv, jv := abs64(score[l]), abs64(score[r]); iv != jv {\n\t\t\t\treturn iv > jv\n\t\t\t}\n\t\t\tif iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {\n\t\t\t\treturn iv < jv\n\t\t\t}\n\t\t\tif iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {\n\t\t\t\treturn iv > jv\n\t\t\t}\n\t\t\treturn compareNodes(l, r)\n\t\t}\n\n\t\tswitch o {\n\t\tcase CumNameOrder:\n\t\t\tscore = make(map[*Node]int64, len(ns))\n\t\t\tfor _, n := range ns {\n\t\t\t\tscore[n] = n.Cum\n\t\t\t}\n\t\t\ts = nodeSorter{ns, scoreOrder}\n\t\tcase EntropyOrder:\n\t\t\tscore = make(map[*Node]int64, len(ns))\n\t\t\tfor _, n := range ns {\n\t\t\t\tscore[n] = entropyScore(n)\n\t\t\t}\n\t\t\ts = nodeSorter{ns, scoreOrder}\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"report: unrecognized sort ordering: %d\", o)\n\t}\n\tsort.Sort(s)\n\treturn nil\n}\n\n// compareNodes compares two nodes to provide a deterministic ordering\n// between them. Two nodes cannot have the same Node.Info value.\nfunc compareNodes(l, r *Node) bool {\n\treturn fmt.Sprint(l.Info) < fmt.Sprint(r.Info)\n}\n\n// entropyScore computes a score for a node representing how important\n// it is to include this node on a graph visualization. It is used to\n// sort the nodes and select which ones to display if we have more\n// nodes than desired in the graph. This number is computed by looking\n// at the flat and cum weights of the node and the incoming/outgoing\n// edges. The fundamental idea is to penalize nodes that have a simple\n// fallthrough from their incoming to the outgoing edge.\nfunc entropyScore(n *Node) int64 {\n\tscore := float64(0)\n\n\tif len(n.In) == 0 {\n\t\tscore++ // Favor entry nodes\n\t} else {\n\t\tscore += edgeEntropyScore(n, n.In, 0)\n\t}\n\n\tif len(n.Out) == 0 {\n\t\tscore++ // Favor leaf nodes\n\t} else {\n\t\tscore += edgeEntropyScore(n, n.Out, n.Flat)\n\t}\n\n\treturn int64(score*float64(n.Cum)) + n.Flat\n}\n\n// edgeEntropyScore computes the entropy value for a set of edges\n// coming in or out of a node. Entropy (as defined in information\n// theory) refers to the amount of information encoded by the set of\n// edges. A set of edges that have a more interesting distribution of\n// samples gets a higher score.\nfunc edgeEntropyScore(n *Node, edges EdgeMap, self int64) float64 {\n\tscore := float64(0)\n\ttotal := self\n\tfor _, e := range edges {\n\t\tif e.Weight > 0 {\n\t\t\ttotal += abs64(e.Weight)\n\t\t}\n\t}\n\tif total != 0 {\n\t\tfor _, e := range edges {\n\t\t\tfrac := float64(abs64(e.Weight)) / float64(total)\n\t\t\tscore += -frac * math.Log2(frac)\n\t\t}\n\t\tif self > 0 {\n\t\t\tfrac := float64(abs64(self)) / float64(total)\n\t\t\tscore += -frac * math.Log2(frac)\n\t\t}\n\t}\n\treturn score\n}\n\n// NodeOrder sets the ordering for a Sort operation\ntype NodeOrder int\n\n// Sorting options for node sort.\nconst (\n\tFlatNameOrder NodeOrder = iota\n\tFlatCumNameOrder\n\tCumNameOrder\n\tNameOrder\n\tFileOrder\n\tAddressOrder\n\tEntropyOrder\n)\n\n// Sort returns a slice of the edges in the map, in a consistent\n// order. The sort order is first based on the edge weight\n// (higher-to-lower) and then by the node names to avoid flakiness.\nfunc (e EdgeMap) Sort() []*Edge {\n\tel := make(edgeList, 0, len(e))\n\tfor _, w := range e {\n\t\tel = append(el, w)\n\t}\n\n\tsort.Sort(el)\n\treturn el\n}\n\n// Sum returns the total weight for a set of nodes.\nfunc (e EdgeMap) Sum() int64 {\n\tvar ret int64\n\tfor _, edge := range e {\n\t\tret += edge.Weight\n\t}\n\treturn ret\n}\n\ntype edgeList []*Edge\n\nfunc (el edgeList) Len() int {\n\treturn len(el)\n}\n\nfunc (el edgeList) Less(i, j int) bool {\n\tif el[i].Weight != el[j].Weight {\n\t\treturn abs64(el[i].Weight) > abs64(el[j].Weight)\n\t}\n\n\tfrom1 := el[i].Src.Info.PrintableName()\n\tfrom2 := el[j].Src.Info.PrintableName()\n\tif from1 != from2 {\n\t\treturn from1 < from2\n\t}\n\n\tto1 := el[i].Dest.Info.PrintableName()\n\tto2 := el[j].Dest.Info.PrintableName()\n\n\treturn to1 < to2\n}\n\nfunc (el edgeList) Swap(i, j int) {\n\tel[i], el[j] = el[j], el[i]\n}\n\nfunc abs64(i int64) int64 {\n\tif i < 0 {\n\t\treturn -i\n\t}\n\treturn i\n}\n"}} | |
[Trace - 19:24:28.651 PM] Sending response 'window/workDoneProgress/create - (1)' in 1ms. | |
Result: | |
[Trace - 19:24:28.651 PM] Received notification '$/progress'. | |
Params: {"token":"5577006791947779410","value":{"kind":"begin","title":"Setting up workspace","message":"Loading packages..."}} | |
[Trace - 19:24:28.652 PM] Received request 'workspace/configuration - (2)'. | |
Params: {"items":[{"scopeUri":"file:///home/jake/zikaeroh/pprof","section":"gopls"},{"scopeUri":"file:///home/jake/zikaeroh/pprof","section":"gopls-pprof"}]} | |
[Trace - 19:24:28.654 PM] Sending response 'workspace/configuration - (2)' in 2ms. | |
Result: [{"allExperiments":true,"usePlaceholders":false,"tempModfile":false},null] | |
[Trace - 19:24:28.718 PM] Received request 'client/registerCapability - (3)'. | |
Params: {"registrations":[{"id":"workspace/didChangeWatchedFiles-0","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"**/*.{go,mod,sum}","kind":7},{"globPattern":"/home/jake/zikaeroh/pprof/**/*.{go,mod,sum}","kind":7}]}}]} | |
[Trace - 19:24:28.718 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go env for /home/jake/zikaeroh/pprof\n(root /home/jake/zikaeroh/pprof)\n(go version go version go1.15.2 linux/amd64)\n(valid build configuration = true)\n(build flags: [])\nGOROOT=/usr/lib/go\nGOPATH=/home/jake/go\nGOFLAGS=\nGONOPROXY=\nGONOSUMDB=\nGOCACHE=/home/jake/.cache/go-build\nGOMOD=/home/jake/zikaeroh/pprof/go.mod\nGOMODCACHE=/home/jake/go/pkg/mod\nGOPROXY=https://proxy.golang.org,direct\nGOPRIVATE=\nGO111MODULE=\nGOINSECURE=\nGOSUMDB=sum.golang.org\n\n"} | |
[Trace - 19:24:28.720 PM] Sending response 'client/registerCapability - (3)' in 1ms. | |
Result: | |
[Trace - 19:24:28.720 PM] Received request 'client/registerCapability - (4)'. | |
Params: {"registrations":[{"id":"workspace/didChangeConfiguration","method":"workspace/didChangeConfiguration"},{"id":"workspace/didChangeWorkspaceFolders","method":"workspace/didChangeWorkspaceFolders"}]} | |
[Trace - 19:24:28.720 PM] Sending response 'client/registerCapability - (4)' in 0ms. | |
Result: | |
[Trace - 19:24:28.731 PM] Sending request 'textDocument/documentSymbol - (1)'. | |
Params: {"textDocument":{"uri":"file:///home/jake/zikaeroh/pprof/internal/graph/graph.go"}} | |
[Trace - 19:24:28.732 PM] Sending request 'textDocument/documentLink - (2)'. | |
Params: {"textDocument":{"uri":"git:/home/jake/zikaeroh/pprof/internal/graph/graph.go?%7B%22path%22%3A%22%2Fhome%2Fjake%2Fzikaeroh%2Fpprof%2Finternal%2Fgraph%2Fgraph.go%22%2C%22ref%22%3A%22~%22%7D"}} | |
[Trace - 19:24:28.732 PM] Sending request 'textDocument/documentLink - (3)'. | |
Params: {"textDocument":{"uri":"file:///home/jake/zikaeroh/pprof/internal/graph/graph.go"}} | |
[Trace - 19:24:28.828 PM] Sending request 'textDocument/semanticTokens/range - (4)'. | |
Params: {"textDocument":{"uri":"git:/home/jake/zikaeroh/pprof/internal/graph/graph.go?%7B%22path%22%3A%22%2Fhome%2Fjake%2Fzikaeroh%2Fpprof%2Finternal%2Fgraph%2Fgraph.go%22%2C%22ref%22%3A%22~%22%7D"},"range":{"start":{"line":921,"character":0},"end":{"line":982,"character":55}}} | |
[Trace - 19:24:28.828 PM] Sending request 'textDocument/semanticTokens/range - (5)'. | |
Params: {"textDocument":{"uri":"file:///home/jake/zikaeroh/pprof/internal/graph/graph.go"},"range":{"start":{"line":921,"character":0},"end":{"line":982,"character":19}}} | |
[Trace - 19:24:28.929 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tdirectory=/tmp/gopls-mod436609246\n\tquery=[builtin github.com/google/pprof/...]\n\tpackages=39\n"} | |
[Trace - 19:24:28.929 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/elfexec\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/elfexec/elfexec.go]\n"} | |
[Trace - 19:24:28.929 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"builtin\"\n\tfiles=[/usr/lib/go/src/builtin/builtin.go]\n"} | |
[Trace - 19:24:28.954 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/profile\"\n\tfiles=[/home/jake/zikaeroh/pprof/profile/encode.go /home/jake/zikaeroh/pprof/profile/filter.go /home/jake/zikaeroh/pprof/profile/index.go /home/jake/zikaeroh/pprof/profile/legacy_java_profile.go /home/jake/zikaeroh/pprof/profile/legacy_profile.go /home/jake/zikaeroh/pprof/profile/merge.go /home/jake/zikaeroh/pprof/profile/profile.go /home/jake/zikaeroh/pprof/profile/proto.go /home/jake/zikaeroh/pprof/profile/prune.go]\n"} | |
[Trace - 19:24:28.957 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/plugin\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/plugin/plugin.go]\n"} | |
[Trace - 19:24:28.978 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/binutils\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/binutils/addr2liner.go /home/jake/zikaeroh/pprof/internal/binutils/addr2liner_llvm.go /home/jake/zikaeroh/pprof/internal/binutils/addr2liner_nm.go /home/jake/zikaeroh/pprof/internal/binutils/binutils.go /home/jake/zikaeroh/pprof/internal/binutils/disasm.go]\n"} | |
[Trace - 19:24:28.980 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/measurement\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/measurement/measurement.go]\n"} | |
[Trace - 19:24:28.980 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/graph\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/graph/dotgraph.go /home/jake/zikaeroh/pprof/internal/graph/graph.go]\n"} | |
[Trace - 19:24:28.980 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/report\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/report/report.go /home/jake/zikaeroh/pprof/internal/report/source.go /home/jake/zikaeroh/pprof/internal/report/source_html.go]\n"} | |
[Trace - 19:24:28.983 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolz\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/symbolz/symbolz.go]\n"} | |
[Trace - 19:24:28.983 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolizer\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/symbolizer/symbolizer.go]\n"} | |
[Trace - 19:24:28.984 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/transport\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/transport/transport.go]\n"} | |
[Trace - 19:24:28.984 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/third_party/d3\"\n\tfiles=[/home/jake/zikaeroh/pprof/third_party/d3/d3.go]\n"} | |
[Trace - 19:24:28.984 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/third_party/d3flamegraph\"\n\tfiles=[/home/jake/zikaeroh/pprof/third_party/d3flamegraph/d3_flame_graph.go]\n"} | |
[Trace - 19:24:28.984 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/third_party/svgpan\"\n\tfiles=[/home/jake/zikaeroh/pprof/third_party/svgpan/svgpan.go]\n"} | |
[Trace - 19:24:28.985 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/driver\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/driver/cli.go /home/jake/zikaeroh/pprof/internal/driver/commands.go /home/jake/zikaeroh/pprof/internal/driver/config.go /home/jake/zikaeroh/pprof/internal/driver/driver.go /home/jake/zikaeroh/pprof/internal/driver/driver_focus.go /home/jake/zikaeroh/pprof/internal/driver/fetch.go /home/jake/zikaeroh/pprof/internal/driver/flags.go /home/jake/zikaeroh/pprof/internal/driver/flamegraph.go /home/jake/zikaeroh/pprof/internal/driver/interactive.go /home/jake/zikaeroh/pprof/internal/driver/options.go /home/jake/zikaeroh/pprof/internal/driver/settings.go /home/jake/zikaeroh/pprof/internal/driver/svg.go /home/jake/zikaeroh/pprof/internal/driver/tempfile.go /home/jake/zikaeroh/pprof/internal/driver/webhtml.go /home/jake/zikaeroh/pprof/internal/driver/webui.go]\n"} | |
[Trace - 19:24:28.986 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/driver\"\n\tfiles=[/home/jake/zikaeroh/pprof/driver/driver.go]\n"} | |
[Trace - 19:24:28.986 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof\"\n\tfiles=[/home/jake/zikaeroh/pprof/pprof.go]\n"} | |
[Trace - 19:24:28.987 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/fuzz\"\n\tfiles=[/home/jake/zikaeroh/pprof/fuzz/main.go]\n"} | |
[Trace - 19:24:28.988 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/proftest\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/proftest/proftest.go]\n"} | |
[Trace - 19:24:28.988 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/fuzz\"\n\tfiles=[/home/jake/zikaeroh/pprof/fuzz/main.go /home/jake/zikaeroh/pprof/fuzz/fuzz_test.go]\n"} | |
[Trace - 19:24:28.989 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/binutils\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/binutils/addr2liner.go /home/jake/zikaeroh/pprof/internal/binutils/addr2liner_llvm.go /home/jake/zikaeroh/pprof/internal/binutils/addr2liner_nm.go /home/jake/zikaeroh/pprof/internal/binutils/binutils.go /home/jake/zikaeroh/pprof/internal/binutils/disasm.go /home/jake/zikaeroh/pprof/internal/binutils/binutils_test.go /home/jake/zikaeroh/pprof/internal/binutils/disasm_test.go]\n"} | |
[Trace - 19:24:28.989 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/fuzz.test\"\n\tfiles=[/home/jake/.cache/go-build/15/15eee8ffb0f04baa5ea39d4b929415f6149c236d98a161bffe1e1ab94131e2e6-d]\n"} | |
[Trace - 19:24:28.989 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/binutils.test\"\n\tfiles=[/home/jake/.cache/go-build/76/767435b83bfd4688665de67ed93b8cec44739df5b010a6e7568ee2e9715f2321-d]\n"} | |
[Trace - 19:24:28.989 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/driver\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/driver/cli.go /home/jake/zikaeroh/pprof/internal/driver/commands.go /home/jake/zikaeroh/pprof/internal/driver/config.go /home/jake/zikaeroh/pprof/internal/driver/driver.go /home/jake/zikaeroh/pprof/internal/driver/driver_focus.go /home/jake/zikaeroh/pprof/internal/driver/fetch.go /home/jake/zikaeroh/pprof/internal/driver/flags.go /home/jake/zikaeroh/pprof/internal/driver/flamegraph.go /home/jake/zikaeroh/pprof/internal/driver/interactive.go /home/jake/zikaeroh/pprof/internal/driver/options.go /home/jake/zikaeroh/pprof/internal/driver/settings.go /home/jake/zikaeroh/pprof/internal/driver/svg.go /home/jake/zikaeroh/pprof/internal/driver/tempfile.go /home/jake/zikaeroh/pprof/internal/driver/webhtml.go /home/jake/zikaeroh/pprof/internal/driver/webui.go /home/jake/zikaeroh/pprof/internal/driver/driver_test.go /home/jake/zikaeroh/pprof/internal/driver/fetch_test.go /home/jake/zikaeroh/pprof/internal/driver/interactive_test.go /home/jake/zikaeroh/pprof/internal/driver/settings_test.go /home/jake/zikaeroh/pprof/internal/driver/tempfile_test.go /home/jake/zikaeroh/pprof/internal/driver/webui_test.go]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/elfexec\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/elfexec/elfexec.go /home/jake/zikaeroh/pprof/internal/elfexec/elfexec_test.go]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/elfexec.test\"\n\tfiles=[/home/jake/.cache/go-build/34/3435cc7db263133291b7ebd62980cd6bd8ffbf988674eba8df5033004bd796ca-d]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/graph\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/graph/dotgraph.go /home/jake/zikaeroh/pprof/internal/graph/graph.go /home/jake/zikaeroh/pprof/internal/graph/dotgraph_test.go /home/jake/zikaeroh/pprof/internal/graph/graph_test.go]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/graph.test\"\n\tfiles=[/home/jake/.cache/go-build/cf/cff3364aff977561b98a8cb4e8145a56667ee7e81216f4d8b887357ecf83a484-d]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/driver.test\"\n\tfiles=[/home/jake/.cache/go-build/39/39be91947e067528d064386aedb215f9dd18db6662d941eadb36dd7a3f58e0ac-d]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/measurement\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/measurement/measurement.go /home/jake/zikaeroh/pprof/internal/measurement/measurement_test.go]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/measurement.test\"\n\tfiles=[/home/jake/.cache/go-build/e5/e56de8e57efed9bd5c85821e652cb4464cf9cf59d6b7d26ce02a83465f445d5b-d]\n"} | |
[Trace - 19:24:28.993 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/report\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/report/report.go /home/jake/zikaeroh/pprof/internal/report/source.go /home/jake/zikaeroh/pprof/internal/report/source_html.go /home/jake/zikaeroh/pprof/internal/report/report_test.go /home/jake/zikaeroh/pprof/internal/report/source_test.go]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolizer\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/symbolizer/symbolizer.go /home/jake/zikaeroh/pprof/internal/symbolizer/symbolizer_test.go]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/report.test\"\n\tfiles=[/home/jake/.cache/go-build/35/355621b0ee250f10154e8936db13fb1cf182c4ee799c119979591d6f21098636-d]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolizer.test\"\n\tfiles=[/home/jake/.cache/go-build/aa/aabc0691682f2f954808dbbfc21219c1fa966daf3213e926e373a0876ca8332a-d]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/profile\"\n\tfiles=[/home/jake/zikaeroh/pprof/profile/encode.go /home/jake/zikaeroh/pprof/profile/filter.go /home/jake/zikaeroh/pprof/profile/index.go /home/jake/zikaeroh/pprof/profile/legacy_java_profile.go /home/jake/zikaeroh/pprof/profile/legacy_profile.go /home/jake/zikaeroh/pprof/profile/merge.go /home/jake/zikaeroh/pprof/profile/profile.go /home/jake/zikaeroh/pprof/profile/proto.go /home/jake/zikaeroh/pprof/profile/prune.go /home/jake/zikaeroh/pprof/profile/filter_test.go /home/jake/zikaeroh/pprof/profile/index_test.go /home/jake/zikaeroh/pprof/profile/legacy_profile_test.go /home/jake/zikaeroh/pprof/profile/merge_test.go /home/jake/zikaeroh/pprof/profile/profile_test.go /home/jake/zikaeroh/pprof/profile/proto_test.go /home/jake/zikaeroh/pprof/profile/prune_test.go]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolz\"\n\tfiles=[/home/jake/zikaeroh/pprof/internal/symbolz/symbolz.go /home/jake/zikaeroh/pprof/internal/symbolz/symbolz_test.go]\n"} | |
[Trace - 19:24:28.994 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/internal/symbolz.test\"\n\tfiles=[/home/jake/.cache/go-build/cc/cc7143ea95224cc2ed871849156bc64ac9b096e53bca3afc8fd0d49ac99b04a0-d]\n"} | |
[Trace - 19:24:28.995 PM] Received notification 'window/logMessage'. | |
Params: {"type":3,"message":"2020/10/08 19:24:28 go/packages.Load\n\tsnapshot=0\n\tpackage_path=\"github.com/google/pprof/profile.test\"\n\tfiles=[/home/jake/.cache/go-build/14/14e4e977770281cf2482198eb91754111155b6028148f44eaf013f683ef6659e-d]\n"} | |
[Trace - 19:24:28.996 PM] Received notification '$/progress'. | |
Params: {"token":"5577006791947779410","value":{"kind":"end","message":"Finished loading packages."}} | |
[Trace - 19:24:29.122 PM] Sending request 'textDocument/semanticTokens/full - (6)'. | |
Params: {"textDocument":{"uri":"file:///home/jake/zikaeroh/pprof/internal/graph/graph.go"}} | |
[Trace - 19:24:29.122 PM] Sending request 'textDocument/semanticTokens/full - (7)'. | |
Params: {"textDocument":{"uri":"git:/home/jake/zikaeroh/pprof/internal/graph/graph.go?%7B%22path%22%3A%22%2Fhome%2Fjake%2Fzikaeroh%2Fpprof%2Finternal%2Fgraph%2Fgraph.go%22%2C%22ref%22%3A%22~%22%7D"}} | |
[Trace - 19:24:29.293 PM] Received response 'textDocument/documentSymbol - (1)' in 561ms. | |
Result: [{"name":"javaRegExp","detail":"*regexp.Regexp","kind":13,"range":{"start":{"line":29,"character":0},"end":{"line":45,"character":1}},"selectionRange":{"start":{"line":32,"character":1},"end":{"line":32,"character":11}}},{"name":"goRegExp","detail":"*regexp.Regexp","kind":13,"range":{"start":{"line":29,"character":0},"end":{"line":45,"character":1}},"selectionRange":{"start":{"line":35,"character":1},"end":{"line":35,"character":9}}},{"name":"goVerRegExp","detail":"*regexp.Regexp","kind":13,"range":{"start":{"line":29,"character":0},"end":{"line":45,"character":1}},"selectionRange":{"start":{"line":37,"character":1},"end":{"line":37,"character":12}}},{"name":"cppRegExp","detail":"*regexp.Regexp","kind":13,"range":{"start":{"line":29,"character":0},"end":{"line":45,"character":1}},"selectionRange":{"start":{"line":43,"character":1},"end":{"line":43,"character":10}}},{"name":"cppAnonymousPrefixRegExp","detail":"*regexp.Regexp","kind":13,"range":{"start":{"line":29,"character":0},"end":{"line":45,"character":1}},"selectionRange":{"start":{"line":44,"character":1},"end":{"line":44,"character":25}}},{"name":"Graph","detail":"struct{...}","kind":23,"range":{"start":{"line":49,"character":5},"end":{"line":51,"character":1}},"selectionRange":{"start":{"line":49,"character":5},"end":{"line":49,"character":10}},"children":[{"name":"Nodes","detail":"[]*Node","kind":8,"range":{"start":{"line":50,"character":1},"end":{"line":50,"character":12}},"selectionRange":{"start":{"line":50,"character":1},"end":{"line":50,"character":6}}}]},{"name":"Options","detail":"struct{...}","kind":23,"range":{"start":{"line":54,"character":5},"end":{"line":65,"character":1}},"selectionRange":{"start":{"line":54,"character":5},"end":{"line":54,"character":12}},"children":[{"name":"SampleValue","detail":"func(s []int64) int64","kind":8,"range":{"start":{"line":55,"character":1},"end":{"line":55,"character":40}},"selectionRange":{"start":{"line":55,"character":1},"end":{"line":55,"character":12}}},{"name":"SampleMeanDivisor","detail":"func(s []int64) int64","kind":8,"range":{"start":{"line":56,"character":1},"end":{"line":56,"character":40}},"selectionRange":{"start":{"line":56,"character":1},"end":{"line":56,"character":18}}},{"name":"FormatTag","detail":"func(int64, string) string","kind":8,"range":{"start":{"line":57,"character":1},"end":{"line":57,"character":45}},"selectionRange":{"start":{"line":57,"character":1},"end":{"line":57,"character":10}}},{"name":"ObjNames","detail":"bool","kind":8,"range":{"start":{"line":58,"character":1},"end":{"line":58,"character":23}},"selectionRange":{"start":{"line":58,"character":1},"end":{"line":58,"character":9}}},{"name":"OrigFnNames","detail":"bool","kind":8,"range":{"start":{"line":59,"character":1},"end":{"line":59,"character":23}},"selectionRange":{"start":{"line":59,"character":1},"end":{"line":59,"character":12}}},{"name":"CallTree","detail":"bool","kind":8,"range":{"start":{"line":61,"character":1},"end":{"line":61,"character":18}},"selectionRange":{"start":{"line":61,"character":1},"end":{"line":61,"character":9}}},{"name":"DropNegative","detail":"bool","kind":8,"range":{"start":{"line":62,"character":1},"end":{"line":62,"character":18}},"selectionRange":{"start":{"line":62,"character":1},"end":{"line":62,"character":13}}},{"name":"KeptNodes","detail":"map[NodeInfo]bool","kind":8,"range":{"start":{"line":64,"character":1},"end":{"line":64,"character":18}},"selectionRange":{"start":{"line":64,"character":1},"end":{"line":64,"character":10}}}]},{"name":"Nodes","detail":"[]*Node","kind":13,"range":{"start":{"line":68,"character":5},"end":{"line":68,"character":18}},"selectionRange":{"start":{"line":68,"character":5},"end":{"line":68,"character":10}}},{"name":"Node","detail":"struct{...}","kind":23,"range":{"start":{"line":72,"character":5},"end":{"line":99,"character":1}},"selectionRange":{"start":{"line":72,"character":5},"end":{"line":72,"character":9}},"children":[{"name":"Info","detail":"struct{...}","kind":8,"range":{"start":{"line":74,"character":1},"end":{"line":74,"character":14}},"selectionRange":{"start":{"line":74,"character":1},"end":{"line":74,"character":5}}},{"name":"Function","detail":"*Node","kind":8,"range":{"start":{"line":81,"character":1},"end":{"line":81,"character":15}},"selectionRange":{"start":{"line":81,"character":1},"end":{"line":81,"character":9}}},{"name":"Flat","detail":"int64","kind":8,"range":{"start":{"line":85,"character":1},"end":{"line":85,"character":33}},"selectionRange":{"start":{"line":85,"character":1},"end":{"line":85,"character":5}}},{"name":"FlatDiv","detail":"int64","kind":8,"range":{"start":{"line":85,"character":1},"end":{"line":85,"character":33}},"selectionRange":{"start":{"line":85,"character":7},"end":{"line":85,"character":14}}},{"name":"Cum","detail":"int64","kind":8,"range":{"start":{"line":85,"character":1},"end":{"line":85,"character":33}},"selectionRange":{"start":{"line":85,"character":16},"end":{"line":85,"character":19}}},{"name":"CumDiv","detail":"int64","kind":8,"range":{"start":{"line":85,"character":1},"end":{"line":85,"character":33}},"selectionRange":{"start":{"line":85,"character":21},"end":{"line":85,"character":27}}},{"name":"In","detail":"map[*Node]*Edge","kind":8,"range":{"start":{"line":89,"character":1},"end":{"line":89,"character":16}},"selectionRange":{"start":{"line":89,"character":1},"end":{"line":89,"character":3}}},{"name":"Out","detail":"map[*Node]*Edge","kind":8,"range":{"start":{"line":89,"character":1},"end":{"line":89,"character":16}},"selectionRange":{"start":{"line":89,"character":5},"end":{"line":89,"character":8}}},{"name":"LabelTags","detail":"map[string]*Tag","kind":8,"range":{"start":{"line":92,"character":1},"end":{"line":92,"character":17}},"selectionRange":{"start":{"line":92,"character":1},"end":{"line":92,"character":10}}},{"name":"NumericTags","detail":"map[string]TagMap","kind":8,"range":{"start":{"line":98,"character":1},"end":{"line":98,"character":30}},"selectionRange":{"start":{"line":98,"character":1},"end":{"line":98,"character":12}}}]},{"name":"(*Node).FlatValue","detail":"()","kind":6,"range":{"start":{"line":103,"character":0},"end":{"line":108,"character":1}},"selectionRange":{"start":{"line":103,"character":15},"end":{"line":103,"character":24}}},{"name":"(*Node).CumValue","detail":"()","kind":6,"range":{"start":{"line":112,"character":0},"end":{"line":117,"character":1}},"selectionRange":{"start":{"line":112,"character":15},"end":{"line":112,"character":23}}},{"name":"(*Node).AddToEdge","detail":"(to *Node, v int64, residual bool, inline bool)","kind":6,"range":{"start":{"line":121,"character":0},"end":{"line":123,"character":1}},"selectionRange":{"start":{"line":121,"character":15},"end":{"line":121,"character":24}}},{"name":"(*Node).AddToEdgeDiv","detail":"(to *Node, dv int64, v int64, residual bool, inline bool)","kind":6,"range":{"start":{"line":127,"character":0},"end":{"line":147,"character":1}},"selectionRange":{"start":{"line":127,"character":15},"end":{"line":127,"character":27}}},{"name":"NodeInfo","detail":"struct{...}","kind":23,"range":{"start":{"line":150,"character":5},"end":{"line":157,"character":1}},"selectionRange":{"start":{"line":150,"character":5},"end":{"line":150,"character":13}},"children":[{"name":"Name","detail":"string","kind":8,"range":{"start":{"line":151,"character":1},"end":{"line":151,"character":25}},"selectionRange":{"start":{"line":151,"character":1},"end":{"line":151,"character":5}}},{"name":"OrigName","detail":"string","kind":8,"range":{"start":{"line":152,"character":1},"end":{"line":152,"character":25}},"selectionRange":{"start":{"line":152,"character":1},"end":{"line":152,"character":9}}},{"name":"Address","detail":"uint64","kind":8,"range":{"start":{"line":153,"character":1},"end":{"line":153,"character":25}},"selectionRange":{"start":{"line":153,"character":1},"end":{"line":153,"character":8}}},{"name":"File","detail":"string","kind":8,"range":{"start":{"line":154,"character":1},"end":{"line":154,"character":25}},"selectionRange":{"start":{"line":154,"character":1},"end":{"line":154,"character":5}}},{"name":"StartLine","detail":"int","kind":8,"range":{"start":{"line":155,"character":1},"end":{"line":155,"character":22}},"selectionRange":{"start":{"line":155,"character":1},"end":{"line":155,"character":10}}},{"name":"Lineno","detail":"int","kind":8,"range":{"start":{"line":155,"character":1},"end":{"line":155,"character":22}},"selectionRange":{"start":{"line":155,"character":12},"end":{"line":155,"character":18}}},{"name":"Objfile","detail":"string","kind":8,"range":{"start":{"line":156,"character":1},"end":{"line":156,"character":25}},"selectionRange":{"start":{"line":156,"character":1},"end":{"line":156,"character":8}}}]},{"name":"(*NodeInfo).PrintableName","detail":"()","kind":6,"range":{"start":{"line":160,"character":0},"end":{"line":162,"character":1}},"selectionRange":{"start":{"line":160,"character":19},"end":{"line":160,"character":32}}},{"name":"(*NodeInfo).NameComponents","detail":"()","kind":6,"range":{"start":{"line":165,"character":0},"end":{"line":191,"character":1}},"selectionRange":{"start":{"line":165,"character":19},"end":{"line":165,"character":33}}},{"name":"NodeMap","detail":"map[NodeInfo]*Node","kind":13,"range":{"start":{"line":195,"character":5},"end":{"line":195,"character":31}},"selectionRange":{"start":{"line":195,"character":5},"end":{"line":195,"character":12}}},{"name":"NodeSet","detail":"map[NodeInfo]bool","kind":13,"range":{"start":{"line":198,"character":5},"end":{"line":198,"character":30}},"selectionRange":{"start":{"line":198,"character":5},"end":{"line":198,"character":12}}},{"name":"NodePtrSet","detail":"map[*Node]bool","kind":13,"range":{"start":{"line":208,"character":5},"end":{"line":208,"character":30}},"selectionRange":{"start":{"line":208,"character":5},"end":{"line":208,"character":15}}},{"name":"(NodeMap).FindOrInsertNode","detail":"(info NodeInfo, kept NodeSet)","kind":6,"range":{"start":{"line":213,"character":0},"end":{"line":243,"character":1}},"selectionRange":{"start":{"line":213,"character":18},"end":{"line":213,"character":34}}},{"name":"EdgeMap","detail":"map[*Node]*Edge","kind":13,"range":{"start":{"line":246,"character":5},"end":{"line":246,"character":28}},"selectionRange":{"start":{"line":246,"character":5},"end":{"line":246,"character":12}}},{"name":"Edge","detail":"struct{...}","kind":23,"range":{"start":{"line":249,"character":5},"end":{"line":259,"character":1}},"selectionRange":{"start":{"line":249,"character":5},"end":{"line":249,"character":9}},"children":[{"name":"Src","detail":"*Node","kind":8,"range":{"start":{"line":250,"character":1},"end":{"line":250,"character":16}},"selectionRange":{"start":{"line":250,"character":1},"end":{"line":250,"character":4}}},{"name":"Dest","detail":"*Node","kind":8,"range":{"start":{"line":250,"character":1},"end":{"line":250,"character":16}},"selectionRange":{"start":{"line":250,"character":6},"end":{"line":250,"character":10}}},{"name":"Weight","detail":"int64","kind":8,"range":{"start":{"line":252,"character":1},"end":{"line":252,"character":24}},"selectionRange":{"start":{"line":252,"character":1},"end":{"line":252,"character":7}}},{"name":"WeightDiv","detail":"int64","kind":8,"range":{"start":{"line":252,"character":1},"end":{"line":252,"character":24}},"selectionRange":{"start":{"line":252,"character":9},"end":{"line":252,"character":18}}},{"name":"Residual","detail":"bool","kind":8,"range":{"start":{"line":256,"character":1},"end":{"line":256,"character":14}},"selectionRange":{"start":{"line":256,"character":1},"end":{"line":256,"character":9}}},{"name":"Inline","detail":"bool","kind":8,"range":{"start":{"line":258,"character":1},"end":{"line":258,"character":12}},"selectionRange":{"start":{"line":258,"character":1},"end":{"line":258,"character":7}}}]},{"name":"(*Edge).WeightValue","detail":"()","kind":6,"range":{"start":{"line":263,"character":0},"end":{"line":268,"character":1}},"selectionRange":{"start":{"line":263,"character":15},"end":{"line":263,"character":26}}},{"name":"Tag","detail":"struct{...}","kind":23,"range":{"start":{"line":271,"character":5},"end":{"line":277,"character":1}},"selectionRange":{"start":{"line":271,"character":5},"end":{"line":271,"character":8}},"children":[{"name":"Name","detail":"string","kind":8,"range":{"start":{"line":272,"character":1},"end":{"line":272,"character":21}},"selectionRange":{"start":{"line":272,"character":1},"end":{"line":272,"character":5}}},{"name":"Unit","detail":"string","kind":8,"range":{"start":{"line":273,"character":1},"end":{"line":273,"character":21}},"selectionRange":{"start":{"line":273,"character":1},"end":{"line":273,"character":5}}},{"name":"Value","detail":"int64","kind":8,"range":{"start":{"line":274,"character":1},"end":{"line":274,"character":20}},"selectionRange":{"start":{"line":274,"character":1},"end":{"line":274,"character":6}}},{"name":"Flat","detail":"int64","kind":8,"range":{"start":{"line":275,"character":1},"end":{"line":275,"character":20}},"selectionRange":{"start":{"line":275,"character":1},"end":{"line":275,"character":5}}},{"name":"FlatDiv","detail":"int64","kind":8,"range":{"start":{"line":275,"character":1},"end":{"line":275,"character":20}},"selectionRange":{"start":{"line":275,"character":7},"end":{"line":275,"character":14}}},{"name":"Cum","detail":"int64","kind":8,"range":{"start":{"line":276,"character":1},"end":{"line":276,"character":20}},"selectionRange":{"start":{"line":276,"character":1},"end":{"line":276,"character":4}}},{"name":"CumDiv","detail":"int64","kind":8,"range":{"start":{"line":276,"character":1},"end":{"line":276,"character":20}},"selectionRange":{"start":{"line":276,"character":6},"end":{"line":276,"character":12}}}]},{"name":"(*Tag).FlatValue","detail":"()","kind":6,"range":{"start":{"line":281,"character":0},"end":{"line":286,"character":1}},"selectionRange":{"start":{"line":281,"character":14},"end":{"line":281,"character":23}}},{"name":"(*Tag).CumValue","detail":"()","kind":6,"range":{"start":{"line":290,"character":0},"end":{"line":295,"character":1}},"selectionRange":{"start":{"line":290,"character":14},"end":{"line":290,"character":22}}},{"name":"TagMap","detail":"map[string]*Tag","kind":13,"range":{"start":{"line":298,"character":5},"end":{"line":298,"character":27}},"selectionRange":{"start":{"line":298,"character":5},"end":{"line":298,"character":11}}},{"name":"SortTags","detail":"(t []*Tag, flat bool)","kind":12,"range":{"start":{"line":301,"character":0},"end":{"line":305,"character":1}},"selectionRange":{"start":{"line":301,"character":5},"end":{"line":301,"character":13}}},{"name":"New","detail":"(prof *profile.Profile, o *Options)","kind":12,"range":{"start":{"line":308,"character":0},"end":{"line":314,"character":1}},"selectionRange":{"start":{"line":308,"character":5},"end":{"line":308,"character":8}}},{"name":"newGraph","detail":"(prof *profile.Profile, o *Options)","kind":12,"range":{"start":{"line":319,"character":0},"end":{"line":368,"character":1}},"selectionRange":{"start":{"line":319,"character":5},"end":{"line":319,"character":13}}},{"name":"selectNodesForGraph","detail":"(nodes Nodes, dropNegative bool)","kind":12,"range":{"start":{"line":370,"character":0},"end":{"line":386,"character":1}},"selectionRange":{"start":{"line":370,"character":5},"end":{"line":370,"character":24}}},{"name":"nodePair","detail":"struct{...}","kind":23,"range":{"start":{"line":388,"character":5},"end":{"line":390,"character":1}},"selectionRange":{"start":{"line":388,"character":5},"end":{"line":388,"character":13}},"children":[{"name":"src","detail":"*Node","kind":8,"range":{"start":{"line":389,"character":1},"end":{"line":389,"character":16}},"selectionRange":{"start":{"line":389,"character":1},"end":{"line":389,"character":4}}},{"name":"dest","detail":"*Node","kind":8,"range":{"start":{"line":389,"character":1},"end":{"line":389,"character":16}},"selectionRange":{"start":{"line":389,"character":6},"end":{"line":389,"character":10}}}]},{"name":"newTree","detail":"(prof *profile.Profile, o *Options)","kind":12,"range":{"start":{"line":392,"character":0},"end":{"line":439,"character":1}},"selectionRange":{"start":{"line":392,"character":5},"end":{"line":392,"character":12}}},{"name":"ShortenFunctionName","detail":"(f string)","kind":12,"range":{"start":{"line":442,"character":0},"end":{"line":454,"character":1}},"selectionRange":{"start":{"line":442,"character":5},"end":{"line":442,"character":24}}},{"name":"shortenGoFunc","detail":"(f string, name string)","kind":12,"range":{"start":{"line":456,"character":0},"end":{"line":471,"character":1}},"selectionRange":{"start":{"line":456,"character":5},"end":{"line":456,"character":18}}},{"name":"(*Graph).TrimTree","detail":"(kept NodePtrSet)","kind":6,"range":{"start":{"line":475,"character":0},"end":{"line":533,"character":1}},"selectionRange":{"start":{"line":475,"character":16},"end":{"line":475,"character":24}}},{"name":"joinLabels","detail":"(s *profile.Sample)","kind":12,"range":{"start":{"line":535,"character":0},"end":{"line":548,"character":1}},"selectionRange":{"start":{"line":535,"character":5},"end":{"line":535,"character":15}}},{"name":"isNegative","detail":"(n *Node)","kind":12,"range":{"start":{"line":552,"character":0},"end":{"line":561,"character":1}},"selectionRange":{"start":{"line":552,"character":5},"end":{"line":552,"character":15}}},{"name":"CreateNodes","detail":"(prof *profile.Profile, o *Options)","kind":12,"range":{"start":{"line":566,"character":0},"end":{"line":581,"character":1}},"selectionRange":{"start":{"line":566,"character":5},"end":{"line":566,"character":16}}},{"name":"(NodeMap).nodes","detail":"()","kind":6,"range":{"start":{"line":583,"character":0},"end":{"line":589,"character":1}},"selectionRange":{"start":{"line":583,"character":18},"end":{"line":583,"character":23}}},{"name":"(NodeMap).findOrInsertLine","detail":"(l *profile.Location, li profile.Line, o *Options)","kind":6,"range":{"start":{"line":591,"character":0},"end":{"line":601,"character":1}},"selectionRange":{"start":{"line":591,"character":18},"end":{"line":591,"character":34}}},{"name":"nodeInfo","detail":"(l *profile.Location, line profile.Line, objfile string, o *Options)","kind":12,"range":{"start":{"line":603,"character":0},"end":{"line":623,"character":1}},"selectionRange":{"start":{"line":603,"character":5},"end":{"line":603,"character":13}}},{"name":"tags","detail":"struct{...}","kind":23,"range":{"start":{"line":625,"character":5},"end":{"line":628,"character":1}},"selectionRange":{"start":{"line":625,"character":5},"end":{"line":625,"character":9}},"children":[{"name":"t","detail":"[]*Tag","kind":8,"range":{"start":{"line":626,"character":1},"end":{"line":626,"character":12}},"selectionRange":{"start":{"line":626,"character":1},"end":{"line":626,"character":2}}},{"name":"flat","detail":"bool","kind":8,"range":{"start":{"line":627,"character":1},"end":{"line":627,"character":10}},"selectionRange":{"start":{"line":627,"character":1},"end":{"line":627,"character":5}}}]},{"name":"(tags).Len","detail":"()","kind":6,"range":{"start":{"line":630,"character":0},"end":{"line":630,"character":48}},"selectionRange":{"start":{"line":630,"character":14},"end":{"line":630,"character":17}}},{"name":"(tags).Swap","detail":"(i int, j int)","kind":6,"range":{"start":{"line":631,"character":0},"end":{"line":631,"character":64}},"selectionRange":{"start":{"line":631,"character":14},"end":{"line":631,"character":18}}},{"name":"(tags).Less","detail":"(i int, j int)","kind":6,"range":{"start":{"line":632,"character":0},"end":{"line":642,"character":1}},"selectionRange":{"start":{"line":632,"character":14},"end":{"line":632,"character":18}}},{"name":"(Nodes).Sum","detail":"()","kind":6,"range":{"start":{"line":645,"character":0},"end":{"line":651,"character":1}},"selectionRange":{"start":{"line":645,"character":16},"end":{"line":645,"character":19}}},{"name":"(*Node).addSample","detail":"(dw int64, w int64, labels string, numLabel map[string][]int64, numUnit map[string][]string, format func(int64, string) string, flat bool)","kind":6,"range":{"start":{"line":653,"character":0},"end":{"line":702,"character":1}},"selectionRange":{"start":{"line":653,"character":15},"end":{"line":653,"character":24}}},{"name":"defaultLabelFormat","detail":"(v int64, key string)","kind":12,"range":{"start":{"line":704,"character":0},"end":{"line":706,"character":1}},"selectionRange":{"start":{"line":704,"character":5},"end":{"line":704,"character":23}}},{"name":"(TagMap).findOrAddTag","detail":"(label string, unit string, value int64)","kind":6,"range":{"start":{"line":708,"character":0},"end":{"line":719,"character":1}},"selectionRange":{"start":{"line":708,"character":16},"end":{"line":708,"character":28}}},{"name":"(*Graph).String","detail":"()","kind":6,"range":{"start":{"line":722,"character":0},"end":{"line":744,"character":1}},"selectionRange":{"start":{"line":722,"character":16},"end":{"line":722,"character":22}}},{"name":"(*Graph).DiscardLowFrequencyNodes","detail":"(nodeCutoff int64)","kind":6,"range":{"start":{"line":748,"character":0},"end":{"line":750,"character":1}},"selectionRange":{"start":{"line":748,"character":16},"end":{"line":748,"character":40}}},{"name":"(*Graph).DiscardLowFrequencyNodePtrs","detail":"(nodeCutoff int64)","kind":6,"range":{"start":{"line":754,"character":0},"end":{"line":761,"character":1}},"selectionRange":{"start":{"line":754,"character":16},"end":{"line":754,"character":43}}},{"name":"makeNodeSet","detail":"(nodes Nodes, nodeCutoff int64)","kind":12,"range":{"start":{"line":763,"character":0},"end":{"line":770,"character":1}},"selectionRange":{"start":{"line":763,"character":5},"end":{"line":763,"character":16}}},{"name":"getNodesAboveCumCutoff","detail":"(nodes Nodes, nodeCutoff int64)","kind":12,"range":{"start":{"line":774,"character":0},"end":{"line":783,"character":1}},"selectionRange":{"start":{"line":774,"character":5},"end":{"line":774,"character":27}}},{"name":"(*Graph).TrimLowFrequencyTags","detail":"(tagCutoff int64)","kind":6,"range":{"start":{"line":787,"character":0},"end":{"line":795,"character":1}},"selectionRange":{"start":{"line":787,"character":16},"end":{"line":787,"character":36}}},{"name":"trimLowFreqTags","detail":"(tags TagMap, minValue int64)","kind":12,"range":{"start":{"line":797,"character":0},"end":{"line":805,"character":1}},"selectionRange":{"start":{"line":797,"character":5},"end":{"line":797,"character":20}}},{"name":"(*Graph).TrimLowFrequencyEdges","detail":"(edgeCutoff int64)","kind":6,"range":{"start":{"line":809,"character":0},"end":{"line":821,"character":1}},"selectionRange":{"start":{"line":809,"character":16},"end":{"line":809,"character":37}}},{"name":"(*Graph).SortNodes","detail":"(cum bool, visualMode bool)","kind":6,"range":{"start":{"line":824,"character":0},"end":{"line":835,"character":1}},"selectionRange":{"start":{"line":824,"character":16},"end":{"line":824,"character":25}}},{"name":"(*Graph).SelectTopNodePtrs","detail":"(maxNodes int, visualMode bool)","kind":6,"range":{"start":{"line":838,"character":0},"end":{"line":844,"character":1}},"selectionRange":{"start":{"line":838,"character":16},"end":{"line":838,"character":33}}},{"name":"(*Graph).SelectTopNodes","detail":"(maxNodes int, visualMode bool)","kind":6,"range":{"start":{"line":847,"character":0},"end":{"line":849,"character":1}},"selectionRange":{"start":{"line":847,"character":16},"end":{"line":847,"character":30}}},{"name":"(*Graph).selectTopNodes","detail":"(maxNodes int, visualMode bool)","kind":6,"range":{"start":{"line":852,"character":0},"end":{"line":874,"character":1}},"selectionRange":{"start":{"line":852,"character":16},"end":{"line":852,"character":30}}},{"name":"countTags","detail":"(n *Node)","kind":12,"range":{"start":{"line":878,"character":0},"end":{"line":893,"character":1}},"selectionRange":{"start":{"line":878,"character":5},"end":{"line":878,"character":14}}},{"name":"(*Graph).RemoveRedundantEdges","detail":"()","kind":6,"range":{"start":{"line":898,"character":0},"end":{"line":917,"character":1}},"selectionRange":{"start":{"line":898,"character":16},"end":{"line":898,"character":36}}},{"name":"isRedundantEdge","detail":"(e *Edge)","kind":12,"range":{"start":{"line":921,"character":0},"end":{"line":940,"character":1}},"selectionRange":{"start":{"line":921,"character":5},"end":{"line":921,"character":20}}},{"name":"nodeSorter","detail":"struct{...}","kind":23,"range":{"start":{"line":944,"character":5},"end":{"line":947,"character":1}},"selectionRange":{"start":{"line":944,"character":5},"end":{"line":944,"character":15}},"children":[{"name":"rs","detail":"[]*Node","kind":8,"range":{"start":{"line":945,"character":1},"end":{"line":945,"character":11}},"selectionRange":{"start":{"line":945,"character":1},"end":{"line":945,"character":3}}},{"name":"less","detail":"func(l *Node, r *Node) bool","kind":8,"range":{"start":{"line":946,"character":1},"end":{"line":946,"character":27}},"selectionRange":{"start":{"line":946,"character":1},"end":{"line":946,"character":5}}}]},{"name":"(nodeSorter).Len","detail":"()","kind":6,"range":{"start":{"line":949,"character":0},"end":{"line":949,"character":60}},"selectionRange":{"start":{"line":949,"character":20},"end":{"line":949,"character":23}}},{"name":"(nodeSorter).Swap","detail":"(i int, j int)","kind":6,"range":{"start":{"line":950,"character":0},"end":{"line":950,"character":79}},"selectionRange":{"start":{"line":950,"character":20},"end":{"line":950,"character":24}}},{"name":"(nodeSorter).Less","detail":"(i int, j int)","kind":6,"range":{"start":{"line":951,"character":0},"end":{"line":951,"character":75}},"selectionRange":{"start":{"line":951,"character":20},"end":{"line":951,"character":24}}},{"name":"(Nodes).Sort","detail":"(o NodeOrder)","kind":6,"range":{"start":{"line":957,"character":0},"end":{"line":1061,"character":1}},"selectionRange":{"start":{"line":957,"character":16},"end":{"line":957,"character":20}}},{"name":"compareNodes","detail":"(l *Node, r *Node)","kind":12,"range":{"start":{"line":1065,"character":0},"end":{"line":1067,"character":1}},"selectionRange":{"start":{"line":1065,"character":5},"end":{"line":1065,"character":17}}},{"name":"entropyScore","detail":"(n *Node)","kind":12,"range":{"start":{"line":1076,"character":0},"end":{"line":1092,"character":1}},"selectionRange":{"start":{"line":1076,"character":5},"end":{"line":1076,"character":17}}},{"name":"edgeEntropyScore","detail":"(n *Node, edges EdgeMap, self int64)","kind":12,"range":{"start":{"line":1099,"character":0},"end":{"line":1118,"character":1}},"selectionRange":{"start":{"line":1099,"character":5},"end":{"line":1099,"character":21}}},{"name":"NodeOrder","detail":"int","kind":16,"range":{"start":{"line":1121,"character":5},"end":{"line":1121,"character":18}},"selectionRange":{"start":{"line":1121,"character":5},"end":{"line":1121,"character":14}}},{"name":"FlatNameOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1125,"character":1},"end":{"line":1125,"character":14}}},{"name":"FlatCumNameOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1126,"character":1},"end":{"line":1126,"character":17}}},{"name":"CumNameOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1127,"character":1},"end":{"line":1127,"character":13}}},{"name":"NameOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1128,"character":1},"end":{"line":1128,"character":10}}},{"name":"FileOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1129,"character":1},"end":{"line":1129,"character":10}}},{"name":"AddressOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1130,"character":1},"end":{"line":1130,"character":13}}},{"name":"EntropyOrder","detail":"NodeOrder","kind":14,"range":{"start":{"line":1124,"character":0},"end":{"line":1132,"character":1}},"selectionRange":{"start":{"line":1131,"character":1},"end":{"line":1131,"character":13}}},{"name":"(EdgeMap).Sort","detail":"()","kind":6,"range":{"start":{"line":1137,"character":0},"end":{"line":1145,"character":1}},"selectionRange":{"start":{"line":1137,"character":17},"end":{"line":1137,"character":21}}},{"name":"(EdgeMap).Sum","detail":"()","kind":6,"range":{"start":{"line":1148,"character":0},"end":{"line":1154,"character":1}},"selectionRange":{"start":{"line":1148,"character":17},"end":{"line":1148,"character":20}}},{"name":"edgeList","detail":"[]*Edge","kind":13,"range":{"start":{"line":1156,"character":5},"end":{"line":1156,"character":21}},"selectionRange":{"start":{"line":1156,"character":5},"end":{"line":1156,"character":13}}},{"name":"(edgeList).Len","detail":"()","kind":6,"range":{"start":{"line":1158,"character":0},"end":{"line":1160,"character":1}},"selectionRange":{"start":{"line":1158,"character":19},"end":{"line":1158,"character":22}}},{"name":"(edgeList).Less","detail":"(i int, j int)","kind":6,"range":{"start":{"line":1162,"character":0},"end":{"line":1177,"character":1}},"selectionRange":{"start":{"line":1162,"character":19},"end":{"line":1162,"character":23}}},{"name":"(edgeList).Swap","detail":"(i int, j int)","kind":6,"range":{"start":{"line":1179,"character":0},"end":{"line":1181,"character":1}},"selectionRange":{"start":{"line":1179,"character":19},"end":{"line":1179,"character":23}}},{"name":"abs64","detail":"(i int64)","kind":12,"range":{"start":{"line":1183,"character":0},"end":{"line":1188,"character":1}},"selectionRange":{"start":{"line":1183,"character":5},"end":{"line":1183,"character":10}}}] | |
[Trace - 19:24:29.315 PM] Received response 'textDocument/documentLink - (2)' in 583ms. | |
Result: null | |
[Trace - 19:24:29.449 PM] Received response 'textDocument/documentLink - (3)' in 716ms. | |
Result: [{"range":{"start":{"line":18,"character":2},"end":{"line":18,"character":5}},"target":"https://pkg.go.dev/fmt"},{"range":{"start":{"line":19,"character":2},"end":{"line":19,"character":6}},"target":"https://pkg.go.dev/math"},{"range":{"start":{"line":20,"character":2},"end":{"line":20,"character":15}},"target":"https://pkg.go.dev/path/filepath"},{"range":{"start":{"line":21,"character":2},"end":{"line":21,"character":8}},"target":"https://pkg.go.dev/regexp"},{"range":{"start":{"line":22,"character":2},"end":{"line":22,"character":6}},"target":"https://pkg.go.dev/sort"},{"range":{"start":{"line":23,"character":2},"end":{"line":23,"character":9}},"target":"https://pkg.go.dev/strconv"},{"range":{"start":{"line":24,"character":2},"end":{"line":24,"character":9}},"target":"https://pkg.go.dev/strings"},{"range":{"start":{"line":26,"character":2},"end":{"line":26,"character":33}},"target":"https://pkg.go.dev/github.com/google/pprof/profile"},{"range":{"start":{"line":504,"character":39},"end":{"line":504,"character":45}},"target":"https://cur.In"},{"range":{"start":{"line":6,"character":7},"end":{"line":6,"character":49}},"target":"http://www.apache.org/licenses/LICENSE-2.0"},{"range":{"start":{"line":501,"character":52},"end":{"line":501,"character":58}},"target":"https://cur.In"},{"range":{"start":{"line":1064,"character":48},"end":{"line":1064,"character":57}},"target":"https://Node.Info"}] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment