Skip to content

Instantly share code, notes, and snippets.

@zikaeroh
Created October 9, 2020 02:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zikaeroh/96741da55aad5964576e0aba864cbeb3 to your computer and use it in GitHub Desktop.
Save zikaeroh/96741da55aad5964576e0aba864cbeb3 to your computer and use it in GitHub Desktop.
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