diff --git a/driver/driver.go b/driver/driver.go index 5a8222f70..d5860036c 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -186,9 +186,10 @@ type ObjFile interface { // A Frame describes a single line in a source file. type Frame struct { - Func string // name of function - File string // source file name - Line int // line in file + Func string // name of function + File string // source file name + Line int // line in file + Column int // column in file } // A Sym describes a single symbol in an object file. diff --git a/internal/binutils/addr2liner_llvm.go b/internal/binutils/addr2liner_llvm.go index 491422fcd..3049545b6 100644 --- a/internal/binutils/addr2liner_llvm.go +++ b/internal/binutils/addr2liner_llvm.go @@ -129,6 +129,7 @@ func (d *llvmSymbolizer) readFrame() (plugin.Frame, bool) { } linenumber := 0 + columnnumber := 0 // The llvm-symbolizer outputs the ::. // When it cannot identify the source code location, it outputs "??:0:0". // Older versions output just the filename and line number, so we check for @@ -137,22 +138,27 @@ func (d *llvmSymbolizer) readFrame() (plugin.Frame, bool) { fileline = "" } else { switch split := strings.Split(fileline, ":"); len(split) { - case 1: - // filename - fileline = split[0] - case 2, 3: - // filename:line , or - // filename:line:disc , or - fileline = split[0] + case 3: + // filename:line:column + if col, err := strconv.Atoi(split[2]); err == nil { + columnnumber = col + } + fallthrough + case 2: + // filename:line if line, err := strconv.Atoi(split[1]); err == nil { linenumber = line } + fallthrough + case 1: + // filename + fileline = split[0] default: // Unrecognized, ignore } } - return plugin.Frame{Func: funcname, File: fileline, Line: linenumber}, false + return plugin.Frame{Func: funcname, File: fileline, Line: linenumber, Column: columnnumber}, false } // addrInfo returns the stack frame information for a specific program diff --git a/internal/binutils/binutils_test.go b/internal/binutils/binutils_test.go index b45fe9842..dd931f4b5 100644 --- a/internal/binutils/binutils_test.go +++ b/internal/binutils/binutils_test.go @@ -461,8 +461,8 @@ func TestLLVMSymbolizer(t *testing.T) { frames []plugin.Frame }{ {0x10, false, []plugin.Frame{ - {Func: "Inlined_0x10", File: "foo.h", Line: 0}, - {Func: "Func_0x10", File: "foo.c", Line: 2}, + {Func: "Inlined_0x10", File: "foo.h", Line: 0, Column: 0}, + {Func: "Func_0x10", File: "foo.c", Line: 2, Column: 1}, }}, {0x20, true, []plugin.Frame{ {Func: "foo_0x20", File: "0x20 8"}, @@ -532,7 +532,7 @@ func TestPEFile(t *testing.T) { t.Fatalf("SourceLine: unexpected error %v", err) } wantFrames := []plugin.Frame{ - {Func: "main", File: "hello.c", Line: 3}, + {Func: "main", File: "hello.c", Line: 3, Column: 12}, } if !reflect.DeepEqual(gotFrames, wantFrames) { t.Fatalf("SourceLine for main: got %v; want %v\n", gotFrames, wantFrames) diff --git a/internal/driver/commands.go b/internal/driver/commands.go index c9edf10bb..f990780d7 100644 --- a/internal/driver/commands.go +++ b/internal/driver/commands.go @@ -247,6 +247,8 @@ var configHelp = map[string]string{ "noinlines": helpText( "Ignore inlines.", "Attributes inlined functions to their first out-of-line caller."), + "showcolumns": helpText( + "Show column numbers at the source code line level."), } func helpText(s ...string) string { diff --git a/internal/driver/config.go b/internal/driver/config.go index 9fcdd459b..f7d227416 100644 --- a/internal/driver/config.go +++ b/internal/driver/config.go @@ -51,6 +51,7 @@ type config struct { TagShow string `json:"tagshow,omitempty"` TagHide string `json:"taghide,omitempty"` NoInlines bool `json:"noinlines,omitempty"` + ShowColumns bool `json:"showcolumns,omitempty"` // Output granularity Granularity string `json:"granularity,omitempty"` @@ -157,6 +158,7 @@ func init() { "sort": "sort", "granularity": "g", "noinlines": "noinlines", + "showcolumns": "showcolumns", } def := defaultConfig() diff --git a/internal/driver/driver.go b/internal/driver/driver.go index 27681c540..74ce8cb42 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -256,7 +256,7 @@ func aggregate(prof *profile.Profile, cfg config) error { default: return fmt.Errorf("unexpected granularity") } - return prof.Aggregate(inlines, function, filename, linenumber, address) + return prof.Aggregate(inlines, function, filename, linenumber, cfg.ShowColumns, address) } func reportOptions(p *profile.Profile, numLabelUnits map[string]string, cfg config) (*report.Options, error) { diff --git a/internal/driver/driver_test.go b/internal/driver/driver_test.go index abe3597eb..bc7a97eb7 100644 --- a/internal/driver/driver_test.go +++ b/internal/driver/driver_test.go @@ -1680,8 +1680,9 @@ func (m *mockFile) BuildID() string { func (*mockFile) SourceLine(addr uint64) ([]plugin.Frame, error) { // Return enough data to support the SourceLine() calls needed for // weblist on cpuProfile() contents. - frame := func(fn, file string, line int) plugin.Frame { - return plugin.Frame{Func: fn, File: file, Line: line} + frame := func(fn, file string, num int) plugin.Frame { + // Reuse the same num for line number and column number. + return plugin.Frame{Func: fn, File: file, Line: num, Column: num} } switch addr { case 0x1000: diff --git a/internal/driver/settings_test.go b/internal/driver/settings_test.go index 7d3aad9a0..07bf6acb4 100644 --- a/internal/driver/settings_test.go +++ b/internal/driver/settings_test.go @@ -86,6 +86,7 @@ func TestParseConfig(t *testing.T) { Sort: "cum", Granularity: "functions", NoInlines: true, + ShowColumns: true, } url, changed := cfg.makeURL(url.URL{}) if !changed { diff --git a/internal/graph/graph.go b/internal/graph/graph.go index b64ef2799..5ad10a2ae 100644 --- a/internal/graph/graph.go +++ b/internal/graph/graph.go @@ -154,6 +154,7 @@ type NodeInfo struct { Address uint64 File string StartLine, Lineno int + Columnno int Objfile string } @@ -174,8 +175,12 @@ func (i *NodeInfo) NameComponents() []string { switch { case i.Lineno != 0: + s := fmt.Sprintf("%s:%d", i.File, i.Lineno) + if i.Columnno != 0 { + s += fmt.Sprintf(":%d", i.Columnno) + } // User requested line numbers, provide what we have. - name = append(name, fmt.Sprintf("%s:%d", i.File, i.Lineno)) + name = append(name, s) case i.File != "": // User requested file name, provide it. name = append(name, i.File) @@ -239,6 +244,7 @@ func (nm NodeMap) FindOrInsertNode(info NodeInfo, kept NodeSet) *Node { // Find a node that represents the whole function. info.Address = 0 info.Lineno = 0 + info.Columnno = 0 n.Function = nm.FindOrInsertNode(info, nil) return n } @@ -592,9 +598,10 @@ func nodeInfo(l *profile.Location, line profile.Line, objfile string, o *Options return &NodeInfo{Address: l.Address, Objfile: objfile} } ni := &NodeInfo{ - Address: l.Address, - Lineno: int(line.Line), - Name: line.Function.Name, + Address: l.Address, + Lineno: int(line.Line), + Columnno: int(line.Column), + Name: line.Function.Name, } if fname := line.Function.Filename; fname != "" { ni.File = filepath.Clean(fname) diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index 98eb1dd81..c93455103 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -157,11 +157,12 @@ type ObjFile interface { Close() error } -// A Frame describes a single line in a source file. +// A Frame describes a location in a single line in a source file. type Frame struct { - Func string // name of function - File string // source file name - Line int // line in file + Func string // name of function + File string // source file name + Line int // line in file + Column int // column in line (if available) } // A Sym describes a single symbol in an object file. diff --git a/internal/report/report.go b/internal/report/report.go index f73e49a17..47e514449 100644 --- a/internal/report/report.go +++ b/internal/report/report.go @@ -339,6 +339,7 @@ func printTopProto(w io.Writer, rpt *Report) error { Line: []profile.Line{ { Line: int64(n.Info.Lineno), + Column: int64(n.Info.Columnno), Function: f, }, }, diff --git a/internal/report/report_test.go b/internal/report/report_test.go index eb13e7c18..bc0b5dc1b 100644 --- a/internal/report/report_test.go +++ b/internal/report/report_test.go @@ -191,6 +191,7 @@ var testL = []*profile.Location{ { Function: testF[0], Line: 2, + Column: 2, }, }, }, @@ -201,6 +202,7 @@ var testL = []*profile.Location{ { Function: testF[1], Line: 4, + Column: 4, }, }, }, diff --git a/internal/report/testdata/source.dot b/internal/report/testdata/source.dot index e0dadb1bc..83ee42e91 100644 --- a/internal/report/testdata/source.dot +++ b/internal/report/testdata/source.dot @@ -2,16 +2,16 @@ digraph "unnamed" { node [style=filled fillcolor="#f8f8f8"] subgraph cluster_L { "Duration: 10s, Total samples = 11111 " [shape=box fontsize=16 label="Duration: 10s, Total samples = 11111 \lShowing nodes accounting for 11111, 100% of 11111 total\l\lSee https://git.io/JfYMW for how to read the graph\l"] } N1 [label="tee\nsource2:8\n10000 (90.00%)" id="node1" fontsize=24 shape=box tooltip="tee testdata/source2:8 (10000)" color="#b20500" fillcolor="#edd6d5"] -N2 [label="main\nsource1:2\n1 (0.009%)\nof 11111 (100%)" id="node2" fontsize=9 shape=box tooltip="main testdata/source1:2 (11111)" color="#b20000" fillcolor="#edd5d5"] +N2 [label="main\nsource1:2:2\n1 (0.009%)\nof 11111 (100%)" id="node2" fontsize=9 shape=box tooltip="main testdata/source1:2:2 (11111)" color="#b20000" fillcolor="#edd5d5"] N3 [label="tee\nsource2:2\n1000 (9.00%)\nof 11000 (99.00%)" id="node3" fontsize=14 shape=box tooltip="tee testdata/source2:2 (11000)" color="#b20000" fillcolor="#edd5d5"] N4 [label="tee\nsource2:8\n100 (0.9%)" id="node4" fontsize=10 shape=box tooltip="tee testdata/source2:8 (100)" color="#b2b0aa" fillcolor="#edecec"] N5 [label="bar\nsource1:10\n10 (0.09%)" id="node5" fontsize=9 shape=box tooltip="bar testdata/source1:10 (10)" color="#b2b2b1" fillcolor="#ededed"] N6 [label="bar\nsource1:10\n0 of 100 (0.9%)" id="node6" fontsize=8 shape=box tooltip="bar testdata/source1:10 (100)" color="#b2b0aa" fillcolor="#edecec"] -N7 [label="foo\nsource1:4\n0 of 10 (0.09%)" id="node7" fontsize=8 shape=box tooltip="foo testdata/source1:4 (10)" color="#b2b2b1" fillcolor="#ededed"] -N2 -> N3 [label=" 11000" weight=100 penwidth=5 color="#b20000" tooltip="main testdata/source1:2 -> tee testdata/source2:2 (11000)" labeltooltip="main testdata/source1:2 -> tee testdata/source2:2 (11000)"] +N7 [label="foo\nsource1:4:4\n0 of 10 (0.09%)" id="node7" fontsize=8 shape=box tooltip="foo testdata/source1:4:4 (10)" color="#b2b2b1" fillcolor="#ededed"] +N2 -> N3 [label=" 11000" weight=100 penwidth=5 color="#b20000" tooltip="main testdata/source1:2:2 -> tee testdata/source2:2 (11000)" labeltooltip="main testdata/source1:2:2 -> tee testdata/source2:2 (11000)"] N3 -> N1 [label=" 10000" weight=91 penwidth=5 color="#b20500" tooltip="tee testdata/source2:2 -> tee testdata/source2:8 (10000)" labeltooltip="tee testdata/source2:2 -> tee testdata/source2:8 (10000)"] N6 -> N4 [label=" 100" color="#b2b0aa" tooltip="bar testdata/source1:10 -> tee testdata/source2:8 (100)" labeltooltip="bar testdata/source1:10 -> tee testdata/source2:8 (100)"] -N2 -> N6 [label=" 100" color="#b2b0aa" tooltip="main testdata/source1:2 -> bar testdata/source1:10 (100)" labeltooltip="main testdata/source1:2 -> bar testdata/source1:10 (100)"] -N7 -> N5 [label=" 10" color="#b2b2b1" tooltip="foo testdata/source1:4 -> bar testdata/source1:10 (10)" labeltooltip="foo testdata/source1:4 -> bar testdata/source1:10 (10)"] -N2 -> N7 [label=" 10" color="#b2b2b1" tooltip="main testdata/source1:2 -> foo testdata/source1:4 (10)" labeltooltip="main testdata/source1:2 -> foo testdata/source1:4 (10)"] +N2 -> N6 [label=" 100" color="#b2b0aa" tooltip="main testdata/source1:2:2 -> bar testdata/source1:10 (100)" labeltooltip="main testdata/source1:2:2 -> bar testdata/source1:10 (100)"] +N7 -> N5 [label=" 10" color="#b2b2b1" tooltip="foo testdata/source1:4:4 -> bar testdata/source1:10 (10)" labeltooltip="foo testdata/source1:4:4 -> bar testdata/source1:10 (10)"] +N2 -> N7 [label=" 10" color="#b2b2b1" tooltip="main testdata/source1:2:2 -> foo testdata/source1:4:4 (10)" labeltooltip="main testdata/source1:2:2 -> foo testdata/source1:4:4 (10)"] } diff --git a/internal/symbolizer/symbolizer.go b/internal/symbolizer/symbolizer.go index c3f6cc628..5ca71ab8b 100644 --- a/internal/symbolizer/symbolizer.go +++ b/internal/symbolizer/symbolizer.go @@ -181,6 +181,7 @@ func doLocalSymbolize(prof *profile.Profile, fast, force bool, obj plugin.ObjToo l.Line[i] = profile.Line{ Function: f, Line: int64(frame.Line), + Column: int64(frame.Column), } } diff --git a/internal/symbolizer/symbolizer_test.go b/internal/symbolizer/symbolizer_test.go index adb5f835a..35134ef11 100644 --- a/internal/symbolizer/symbolizer_test.go +++ b/internal/symbolizer/symbolizer_test.go @@ -242,23 +242,27 @@ func checkSymbolizedLocation(a uint64, got []profile.Line) error { if g.Line != int64(w.Line) { return fmt.Errorf("want lineno: %d, got %d", w.Line, g.Line) } + if g.Column != int64(w.Column) { + return fmt.Errorf("want columnno: %d, got %d", w.Column, g.Column) + } } return nil } var mockAddresses = map[uint64][]plugin.Frame{ - 1000: {frame("fun11", "file11.src", 10)}, - 2000: {frame("fun21", "file21.src", 20), frame("fun22", "file22.src", 20)}, - 3000: {frame("fun31", "file31.src", 30), frame("fun32", "file32.src", 30), frame("fun33", "file33.src", 30)}, - 4000: {frame("fun41", "file41.src", 40), frame("fun42", "file42.src", 40), frame("fun43", "file43.src", 40), frame("fun44", "file44.src", 40)}, - 5000: {frame("fun51", "file51.src", 50), frame("fun52", "file52.src", 50), frame("fun53", "file53.src", 50), frame("fun54", "file54.src", 50), frame("fun55", "file55.src", 50)}, + 1000: {frame("fun11", "file11.src", 10, 1)}, + 2000: {frame("fun21", "file21.src", 20, 2), frame("fun22", "file22.src", 20, 2)}, + 3000: {frame("fun31", "file31.src", 30, 3), frame("fun32", "file32.src", 30, 3), frame("fun33", "file33.src", 30, 3)}, + 4000: {frame("fun41", "file41.src", 40, 4), frame("fun42", "file42.src", 40, 4), frame("fun43", "file43.src", 40, 4), frame("fun44", "file44.src", 40, 4)}, + 5000: {frame("fun51", "file51.src", 50, 5), frame("fun52", "file52.src", 50, 5), frame("fun53", "file53.src", 50, 5), frame("fun54", "file54.src", 50, 5), frame("fun55", "file55.src", 50, 5)}, } -func frame(fname, file string, line int) plugin.Frame { +func frame(fname, file string, line int, column int) plugin.Frame { return plugin.Frame{ - Func: fname, - File: file, - Line: line} + Func: fname, + File: file, + Line: line, + Column: column} } func TestDemangleSingleFunction(t *testing.T) { diff --git a/profile/encode.go b/profile/encode.go index 182c926b9..860bb304c 100644 --- a/profile/encode.go +++ b/profile/encode.go @@ -530,6 +530,7 @@ func (p *Line) decoder() []decoder { func (p *Line) encode(b *buffer) { encodeUint64Opt(b, 1, p.functionIDX) encodeInt64Opt(b, 2, p.Line) + encodeInt64Opt(b, 3, p.Column) } var lineDecoder = []decoder{ @@ -538,6 +539,8 @@ var lineDecoder = []decoder{ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) }, // optional int64 line = 2 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) }, + // optional int64 column = 3 + func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Column) }, } func (p *Function) decoder() []decoder { diff --git a/profile/legacy_java_profile.go b/profile/legacy_java_profile.go index 91f45e53c..4580bab18 100644 --- a/profile/legacy_java_profile.go +++ b/profile/legacy_java_profile.go @@ -56,7 +56,7 @@ func javaCPUProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte } // Strip out addresses for better merge. - if err = p.Aggregate(true, true, true, true, false); err != nil { + if err = p.Aggregate(true, true, true, true, false, false); err != nil { return nil, err } @@ -99,7 +99,7 @@ func parseJavaProfile(b []byte) (*Profile, error) { } // Strip out addresses for better merge. - if err = p.Aggregate(true, true, true, true, false); err != nil { + if err = p.Aggregate(true, true, true, true, false, false); err != nil { return nil, err } diff --git a/profile/merge.go b/profile/merge.go index 4b66282cb..eee0132e7 100644 --- a/profile/merge.go +++ b/profile/merge.go @@ -326,12 +326,13 @@ func (l *Location) key() locationKey { key.addr -= l.Mapping.Start key.mappingID = l.Mapping.ID } - lines := make([]string, len(l.Line)*2) + lines := make([]string, len(l.Line)*3) for i, line := range l.Line { if line.Function != nil { lines[i*2] = strconv.FormatUint(line.Function.ID, 16) } lines[i*2+1] = strconv.FormatInt(line.Line, 16) + lines[i*2+2] = strconv.FormatInt(line.Column, 16) } key.lines = strings.Join(lines, "|") return key @@ -418,6 +419,7 @@ func (pm *profileMerger) mapLine(src Line) Line { ln := Line{ Function: pm.mapFunction(src.Function), Line: src.Line, + Column: src.Column, } return ln } diff --git a/profile/profile.go b/profile/profile.go index 60ef7e926..62df80a55 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -145,6 +145,7 @@ type Location struct { type Line struct { Function *Function Line int64 + Column int64 functionIDX uint64 } @@ -436,7 +437,7 @@ func (p *Profile) CheckValid() error { // Aggregate merges the locations in the profile into equivalence // classes preserving the request attributes. It also updates the // samples to point to the merged locations. -func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address bool) error { +func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, columnnumber, address bool) error { for _, m := range p.Mapping { m.HasInlineFrames = m.HasInlineFrames && inlineFrame m.HasFunctions = m.HasFunctions && function @@ -458,7 +459,7 @@ func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address } // Aggregate locations - if !inlineFrame || !address || !linenumber { + if !inlineFrame || !address || !linenumber || !columnnumber { for _, l := range p.Location { if !inlineFrame && len(l.Line) > 1 { l.Line = l.Line[len(l.Line)-1:] @@ -466,6 +467,12 @@ func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address if !linenumber { for i := range l.Line { l.Line[i].Line = 0 + l.Line[i].Column = 0 + } + } + if !columnnumber { + for i := range l.Line { + l.Line[i].Column = 0 } } if !address { @@ -627,10 +634,11 @@ func (l *Location) string() string { for li := range l.Line { lnStr := "??" if fn := l.Line[li].Function; fn != nil { - lnStr = fmt.Sprintf("%s %s:%d s=%d", + lnStr = fmt.Sprintf("%s %s:%d:%d s=%d", fn.Name, fn.Filename, l.Line[li].Line, + l.Line[li].Column, fn.StartLine) if fn.Name != fn.SystemName { lnStr = lnStr + "(" + fn.SystemName + ")" diff --git a/profile/profile_test.go b/profile/profile_test.go index 674ced2c7..c9e39a623 100644 --- a/profile/profile_test.go +++ b/profile/profile_test.go @@ -274,7 +274,7 @@ var cpuL = []*Location{ Mapping: cpuM[1], Address: 0x1000, Line: []Line{ - {Function: cpuF[0], Line: 1}, + {Function: cpuF[0], Line: 1, Column: 1}, }, }, { @@ -282,8 +282,8 @@ var cpuL = []*Location{ Mapping: cpuM[0], Address: 0x2000, Line: []Line{ - {Function: cpuF[1], Line: 2}, - {Function: cpuF[2], Line: 1}, + {Function: cpuF[1], Line: 2, Column: 2}, + {Function: cpuF[2], Line: 1, Column: 1}, }, }, { @@ -291,8 +291,8 @@ var cpuL = []*Location{ Mapping: cpuM[0], Address: 0x3000, Line: []Line{ - {Function: cpuF[1], Line: 2}, - {Function: cpuF[2], Line: 1}, + {Function: cpuF[1], Line: 2, Column: 2}, + {Function: cpuF[2], Line: 1, Column: 1}, }, }, { @@ -300,7 +300,7 @@ var cpuL = []*Location{ Mapping: cpuM[0], Address: 0x3001, Line: []Line{ - {Function: cpuF[2], Line: 2}, + {Function: cpuF[2], Line: 2, Column: 2}, }, }, { @@ -308,7 +308,16 @@ var cpuL = []*Location{ Mapping: cpuM[0], Address: 0x3002, Line: []Line{ - {Function: cpuF[2], Line: 3}, + {Function: cpuF[2], Line: 3, Column: 3}, + }, + }, + // Differs from 1000 due to address and column number. + { + ID: 1001, + Mapping: cpuM[1], + Address: 0x1001, + Line: []Line{ + {Function: cpuF[0], Line: 1, Column: 2}, }, }, } @@ -564,26 +573,92 @@ var testProfile5 = &Profile{ Mapping: cpuM, } +var testProfile6 = &Profile{ + TimeNanos: 10000, + PeriodType: &ValueType{Type: "cpu", Unit: "milliseconds"}, + Period: 1, + DurationNanos: 10e9, + SampleType: []*ValueType{ + {Type: "samples", Unit: "count"}, + {Type: "cpu", Unit: "milliseconds"}, + }, + Sample: []*Sample{ + { + Location: []*Location{cpuL[0]}, + Value: []int64{1000, 1000}, + Label: map[string][]string{ + "key1": {"tag1"}, + "key2": {"tag1"}, + }, + }, + { + Location: []*Location{cpuL[1], cpuL[0]}, + Value: []int64{100, 100}, + Label: map[string][]string{ + "key1": {"tag2"}, + "key3": {"tag2"}, + }, + }, + { + Location: []*Location{cpuL[2], cpuL[0]}, + Value: []int64{10, 10}, + Label: map[string][]string{ + "key1": {"tag3"}, + "key2": {"tag2"}, + }, + }, + { + Location: []*Location{cpuL[3], cpuL[0]}, + Value: []int64{10000, 10000}, + Label: map[string][]string{ + "key1": {"tag4"}, + "key2": {"tag1"}, + }, + }, + { + Location: []*Location{cpuL[4], cpuL[0]}, + Value: []int64{1, 1}, + Label: map[string][]string{ + "key1": {"tag4"}, + "key2": {"tag1"}, + }, + }, + { + Location: []*Location{cpuL[5]}, + Value: []int64{1, 1}, + Label: map[string][]string{ + "key1": {"tag5"}, + "key2": {"tag1"}, + }, + }, + }, + Location: cpuL, + Function: cpuF, + Mapping: cpuM, +} + var aggTests = map[string]aggTest{ - "precise": {true, true, true, true, 5}, - "fileline": {false, true, true, true, 4}, - "inline_function": {false, true, false, true, 3}, - "function": {false, true, false, false, 2}, + "precise": {true, true, true, true, true, 6}, + "columns": {false, true, true, true, true, 5}, + "fileline": {false, true, true, false, true, 4}, + "inline_function": {false, true, false, false, true, 3}, + "function": {false, true, false, false, false, 2}, } type aggTest struct { - precise, function, fileline, inlineFrame bool - rows int + precise, function, fileline, column, inlineFrame bool + rows int } -const totalSamples = int64(11111) +// totalSamples is the sum of sample.Value[0] for testProfile6. +const totalSamples = int64(11112) func TestAggregation(t *testing.T) { - prof := testProfile1.Copy() - for _, resolution := range []string{"precise", "fileline", "inline_function", "function"} { + prof := testProfile6.Copy() + for _, resolution := range []string{"precise", "columns", "fileline", "inline_function", "function"} { a := aggTests[resolution] if !a.precise { - if err := prof.Aggregate(a.inlineFrame, a.function, a.fileline, a.fileline, false); err != nil { + if err := prof.Aggregate(a.inlineFrame, a.function, a.fileline, a.fileline, a.column, false); err != nil { t.Error("aggregating to " + resolution + ":" + err.Error()) } } @@ -638,6 +713,9 @@ func checkAggregation(prof *Profile, a *aggTest) error { } for _, ln := range l.Line { + if !a.column && ln.Column != 0 { + return fmt.Errorf("found column %d on location %d, want:0", ln.Column, l.ID) + } if !a.fileline && (ln.Function.Filename != "" || ln.Line != 0) { return fmt.Errorf("found line %s:%d on location %d, want :0", ln.Function.Filename, ln.Line, l.ID) @@ -753,7 +831,7 @@ func TestMerge(t *testing.T) { } // Use aggregation to merge locations at function granularity. - if err := prof.Aggregate(false, true, false, false, false); err != nil { + if err := prof.Aggregate(false, true, false, false, false, false); err != nil { t.Errorf("aggregating after merge: %v", err) } @@ -900,7 +978,7 @@ func TestEmptyMappingMerge(t *testing.T) { } // Use aggregation to merge locations at function granularity. - if err := prof.Aggregate(false, true, false, false, false); err != nil { + if err := prof.Aggregate(false, true, false, false, false, false); err != nil { t.Errorf("aggregating after merge: %v", err) } @@ -997,7 +1075,7 @@ func locationHash(s *Sample) string { var tb string for _, l := range s.Location { for _, ln := range l.Line { - tb = tb + fmt.Sprintf("%s:%d@%d ", ln.Function.Name, ln.Line, l.Address) + tb = tb + fmt.Sprintf("%s:%d:%d@%d ", ln.Function.Name, ln.Line, ln.Column, l.Address) } } return tb diff --git a/profile/prune_test.go b/profile/prune_test.go index 75d7c6d4f..aaf76b99a 100644 --- a/profile/prune_test.go +++ b/profile/prune_test.go @@ -61,7 +61,7 @@ var locs1 = []*Location{ { ID: 1, Line: []Line{ - {Function: funs[0], Line: 1}, + {Function: funs[0], Line: 1, Column: 7}, }, }, { @@ -75,7 +75,7 @@ var locs1 = []*Location{ ID: 3, Line: []Line{ {Function: funs[3], Line: 2}, - {Function: funs[1], Line: 1}, + {Function: funs[1], Line: 1, Column: 7}, }, }, { @@ -135,11 +135,11 @@ samples/count cpu/milliseconds 1 1: 4 1 1 1: 2 1 Locations - 1: 0x0 main main.c:1 s=0 - 2: 0x0 fun2 fun.c:1 s=0 - 3: 0x0 fun3 fun.c:2 s=0 - fun1 fun.c:1 s=0 - 4: 0x0 fun5 fun.c:2 s=0 + 1: 0x0 main main.c:1:7 s=0 + 2: 0x0 fun2 fun.c:1:0 s=0 + 3: 0x0 fun3 fun.c:2:0 s=0 + fun1 fun.c:1:7 s=0 + 4: 0x0 fun5 fun.c:2:0 s=0 Mappings ` @@ -221,10 +221,10 @@ samples/count cpu/milliseconds 1 1: 4 1 1 1: 1 Locations - 1: 0x0 main main.c:1 s=0 - 2: 0x0 unsimplified_fun(int) fun.c:1 s=0 - 3: 0x0 Foo::(anonymous namespace)::Test::Bar fun.c:1 s=0 - 4: 0x0 Hello::(anonymous namespace)::World(const Foo::(anonymous namespace)::Test::Bar) fun.c:1 s=0 - 5: 0x0 Foo::operator()(::Bar) fun.c:1 s=0 + 1: 0x0 main main.c:1:0 s=0 + 2: 0x0 unsimplified_fun(int) fun.c:1:0 s=0 + 3: 0x0 Foo::(anonymous namespace)::Test::Bar fun.c:1:0 s=0 + 4: 0x0 Hello::(anonymous namespace)::World(const Foo::(anonymous namespace)::Test::Bar) fun.c:1:0 s=0 + 5: 0x0 Foo::operator()(::Bar) fun.c:1:0 s=0 Mappings ` diff --git a/profile/testdata/java.contention.string b/profile/testdata/java.contention.string index 985ffe1cc..34b811d09 100644 --- a/profile/testdata/java.contention.string +++ b/profile/testdata/java.contention.string @@ -8,36 +8,36 @@ contentions/count delay/microseconds 200 200: 1 2 300 200: 30 31 32 Locations - 1: 0x0 com.example.function03 source.java:3 s=0 - 2: 0x0 com.example.function04 source.java:4 s=0 - 3: 0x0 com.example.function0d source.java:0 s=0 - 4: 0x0 com.example.function0e source.java:0 s=0 - 5: 0x0 com.example.function0f source.java:0 s=0 - 6: 0x0 com.example.function10 source.java:10 s=0 - 7: 0x0 com.example.function11 source.java:11 s=0 - 8: 0x0 com.example.function12 source.java:12 s=0 - 9: 0x0 com.example.function13 source.java:13 s=0 - 10: 0x0 com.example.function14 source.java:14 s=0 - 11: 0x0 com.example.function17 source.java:17 s=0 - 12: 0x0 com.example.function18 source.java:18 s=0 - 13: 0x0 com.example.function19 source.java:19 s=0 - 14: 0x0 com.example.function1a source.java:1 s=0 - 15: 0x0 com.example.function1b source.java:1 s=0 - 16: 0x0 com.example.function1c source.java:1 s=0 - 17: 0x0 com.example.function29 source.java:29 s=0 - 18: 0x0 com.example.function2a source.java:2 s=0 - 19: 0x0 com.example.function2b source.java:2 s=0 - 20: 0x0 com.example.function2c source.java:2 s=0 - 21: 0x0 com.example.function2d source.java:2 s=0 - 22: 0x0 com.example.function2e source.java:2 s=0 - 23: 0x0 com.example.function2f source.java:2 s=0 - 24: 0x0 com.example.function30 source.java:30 s=0 - 25: 0x0 com.example.function31 source.java:31 s=0 - 26: 0x0 com.example.function32 source.java:32 s=0 - 27: 0x0 com.example.function33 source.java:33 s=0 - 28: 0x0 com.example.function34 source.java:34 s=0 - 29: 0x0 com.example.function35 source.java:35 s=0 - 30: 0x0 com.example.function36 source.java:36 s=0 - 31: 0x0 com.example.function37 source.java:37 s=0 - 32: 0x0 com.example.function38 source.java:38 s=0 + 1: 0x0 com.example.function03 source.java:3:0 s=0 + 2: 0x0 com.example.function04 source.java:4:0 s=0 + 3: 0x0 com.example.function0d source.java:0:0 s=0 + 4: 0x0 com.example.function0e source.java:0:0 s=0 + 5: 0x0 com.example.function0f source.java:0:0 s=0 + 6: 0x0 com.example.function10 source.java:10:0 s=0 + 7: 0x0 com.example.function11 source.java:11:0 s=0 + 8: 0x0 com.example.function12 source.java:12:0 s=0 + 9: 0x0 com.example.function13 source.java:13:0 s=0 + 10: 0x0 com.example.function14 source.java:14:0 s=0 + 11: 0x0 com.example.function17 source.java:17:0 s=0 + 12: 0x0 com.example.function18 source.java:18:0 s=0 + 13: 0x0 com.example.function19 source.java:19:0 s=0 + 14: 0x0 com.example.function1a source.java:1:0 s=0 + 15: 0x0 com.example.function1b source.java:1:0 s=0 + 16: 0x0 com.example.function1c source.java:1:0 s=0 + 17: 0x0 com.example.function29 source.java:29:0 s=0 + 18: 0x0 com.example.function2a source.java:2:0 s=0 + 19: 0x0 com.example.function2b source.java:2:0 s=0 + 20: 0x0 com.example.function2c source.java:2:0 s=0 + 21: 0x0 com.example.function2d source.java:2:0 s=0 + 22: 0x0 com.example.function2e source.java:2:0 s=0 + 23: 0x0 com.example.function2f source.java:2:0 s=0 + 24: 0x0 com.example.function30 source.java:30:0 s=0 + 25: 0x0 com.example.function31 source.java:31:0 s=0 + 26: 0x0 com.example.function32 source.java:32:0 s=0 + 27: 0x0 com.example.function33 source.java:33:0 s=0 + 28: 0x0 com.example.function34 source.java:34:0 s=0 + 29: 0x0 com.example.function35 source.java:35:0 s=0 + 30: 0x0 com.example.function36 source.java:36:0 s=0 + 31: 0x0 com.example.function37 source.java:37:0 s=0 + 32: 0x0 com.example.function38 source.java:38:0 s=0 Mappings diff --git a/profile/testdata/java.cpu.string b/profile/testdata/java.cpu.string index f728cf26a..e15decbfe 100644 --- a/profile/testdata/java.cpu.string +++ b/profile/testdata/java.cpu.string @@ -11,68 +11,68 @@ samples/count cpu/nanoseconds 1 10000000: 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 29 30 31 32 1 10000000: 54 55 56 57 58 59 60 61 62 11 63 64 16 17 18 Locations - 1: 0x0 GC :0 s=0 - 2: 0x0 Compile :0 s=0 - 3: 0x0 VM :0 s=0 - 4: 0x0 com.example.function06 source.java:6 s=0 - 5: 0x0 com.example.function07 source.java:7 s=0 - 6: 0x0 com.example.function08 source.java:8 s=0 - 7: 0x0 com.example.function09 source.java:9 s=0 - 8: 0x0 com.example.function0a source.java:0 s=0 - 9: 0x0 com.example.function0b source.java:0 s=0 - 10: 0x0 com.example.function0c source.java:0 s=0 - 11: 0x0 com.example.function0d source.java:0 s=0 - 12: 0x0 com.example.function0e source.java:0 s=0 - 13: 0x0 com.example.function0f source.java:0 s=0 - 14: 0x0 com.example.function10 source.java:10 s=0 - 15: 0x0 com.example.function11 source.java:11 s=0 - 16: 0x0 com.example.function12 source.java:12 s=0 - 17: 0x0 com.example.function13 source.java:13 s=0 - 18: 0x0 com.example.function14 source.java:14 s=0 - 19: 0x0 com.example.function1d source.java:1 s=0 - 20: 0x0 com.example.function1e source.java:1 s=0 - 21: 0x0 com.example.function1f source.java:1 s=0 - 22: 0x0 com.example.function20 source.java:20 s=0 - 23: 0x0 com.example.function21 source.java:21 s=0 - 24: 0x0 com.example.function22 source.java:22 s=0 - 25: 0x0 com.example.function23 source.java:23 s=0 - 26: 0x0 com.example.function24 source.java:24 s=0 - 27: 0x0 com.example.function25 source.java:25 s=0 - 28: 0x0 com.example.function26 source.java:26 s=0 - 29: 0x0 com.example.function27 source.java:27 s=0 - 30: 0x0 com.example.function28 source.java:28 s=0 - 31: 0x0 com.example.function29 source.java:29 s=0 - 32: 0x0 com.example.function2a source.java:2 s=0 - 33: 0x0 com.example.function2b source.java:2 s=0 - 34: 0x0 com.example.function2c source.java:2 s=0 - 35: 0x0 com.example.function2d source.java:2 s=0 - 36: 0x0 com.example.function2e source.java:2 s=0 - 37: 0x0 com.example.function2f source.java:2 s=0 - 38: 0x0 com.example.function30 source.java:30 s=0 - 39: 0x0 com.example.function31 source.java:31 s=0 - 40: 0x0 com.example.function32 source.java:32 s=0 - 41: 0x0 com.example.function33 source.java:33 s=0 - 42: 0x0 com.example.function34 source.java:34 s=0 - 43: 0x0 com.example.function35 source.java:35 s=0 - 44: 0x0 com.example.function36 source.java:36 s=0 - 45: 0x0 com.example.function37 source.java:37 s=0 - 46: 0x0 com.example.function38 source.java:38 s=0 - 47: 0x0 com.example.function39 source.java:39 s=0 - 48: 0x0 com.example.function3a source.java:3 s=0 - 49: 0x0 com.example.function3b source.java:3 s=0 - 50: 0x0 com.example.function3c source.java:3 s=0 - 51: 0x0 com.example.function3d source.java:3 s=0 - 52: 0x0 com.example.function3e source.java:3 s=0 - 53: 0x0 com.example.function3f source.java:3 s=0 - 54: 0x0 com.example.function40 source.java:40 s=0 - 55: 0x0 com.example.function41 source.java:41 s=0 - 56: 0x0 com.example.function42 source.java:42 s=0 - 57: 0x0 com.example.function43 source.java:43 s=0 - 58: 0x0 com.example.function44 source.java:44 s=0 - 59: 0x0 com.example.function45 source.java:45 s=0 - 60: 0x0 com.example.function46 source.java:46 s=0 - 61: 0x0 com.example.function47 source.java:47 s=0 - 62: 0x0 com.example.function48 source.java:48 s=0 - 63: 0x0 com.example.function49 source.java:49 s=0 - 64: 0x0 com.example.function4a source.java:4 s=0 + 1: 0x0 GC :0:0 s=0 + 2: 0x0 Compile :0:0 s=0 + 3: 0x0 VM :0:0 s=0 + 4: 0x0 com.example.function06 source.java:6:0 s=0 + 5: 0x0 com.example.function07 source.java:7:0 s=0 + 6: 0x0 com.example.function08 source.java:8:0 s=0 + 7: 0x0 com.example.function09 source.java:9:0 s=0 + 8: 0x0 com.example.function0a source.java:0:0 s=0 + 9: 0x0 com.example.function0b source.java:0:0 s=0 + 10: 0x0 com.example.function0c source.java:0:0 s=0 + 11: 0x0 com.example.function0d source.java:0:0 s=0 + 12: 0x0 com.example.function0e source.java:0:0 s=0 + 13: 0x0 com.example.function0f source.java:0:0 s=0 + 14: 0x0 com.example.function10 source.java:10:0 s=0 + 15: 0x0 com.example.function11 source.java:11:0 s=0 + 16: 0x0 com.example.function12 source.java:12:0 s=0 + 17: 0x0 com.example.function13 source.java:13:0 s=0 + 18: 0x0 com.example.function14 source.java:14:0 s=0 + 19: 0x0 com.example.function1d source.java:1:0 s=0 + 20: 0x0 com.example.function1e source.java:1:0 s=0 + 21: 0x0 com.example.function1f source.java:1:0 s=0 + 22: 0x0 com.example.function20 source.java:20:0 s=0 + 23: 0x0 com.example.function21 source.java:21:0 s=0 + 24: 0x0 com.example.function22 source.java:22:0 s=0 + 25: 0x0 com.example.function23 source.java:23:0 s=0 + 26: 0x0 com.example.function24 source.java:24:0 s=0 + 27: 0x0 com.example.function25 source.java:25:0 s=0 + 28: 0x0 com.example.function26 source.java:26:0 s=0 + 29: 0x0 com.example.function27 source.java:27:0 s=0 + 30: 0x0 com.example.function28 source.java:28:0 s=0 + 31: 0x0 com.example.function29 source.java:29:0 s=0 + 32: 0x0 com.example.function2a source.java:2:0 s=0 + 33: 0x0 com.example.function2b source.java:2:0 s=0 + 34: 0x0 com.example.function2c source.java:2:0 s=0 + 35: 0x0 com.example.function2d source.java:2:0 s=0 + 36: 0x0 com.example.function2e source.java:2:0 s=0 + 37: 0x0 com.example.function2f source.java:2:0 s=0 + 38: 0x0 com.example.function30 source.java:30:0 s=0 + 39: 0x0 com.example.function31 source.java:31:0 s=0 + 40: 0x0 com.example.function32 source.java:32:0 s=0 + 41: 0x0 com.example.function33 source.java:33:0 s=0 + 42: 0x0 com.example.function34 source.java:34:0 s=0 + 43: 0x0 com.example.function35 source.java:35:0 s=0 + 44: 0x0 com.example.function36 source.java:36:0 s=0 + 45: 0x0 com.example.function37 source.java:37:0 s=0 + 46: 0x0 com.example.function38 source.java:38:0 s=0 + 47: 0x0 com.example.function39 source.java:39:0 s=0 + 48: 0x0 com.example.function3a source.java:3:0 s=0 + 49: 0x0 com.example.function3b source.java:3:0 s=0 + 50: 0x0 com.example.function3c source.java:3:0 s=0 + 51: 0x0 com.example.function3d source.java:3:0 s=0 + 52: 0x0 com.example.function3e source.java:3:0 s=0 + 53: 0x0 com.example.function3f source.java:3:0 s=0 + 54: 0x0 com.example.function40 source.java:40:0 s=0 + 55: 0x0 com.example.function41 source.java:41:0 s=0 + 56: 0x0 com.example.function42 source.java:42:0 s=0 + 57: 0x0 com.example.function43 source.java:43:0 s=0 + 58: 0x0 com.example.function44 source.java:44:0 s=0 + 59: 0x0 com.example.function45 source.java:45:0 s=0 + 60: 0x0 com.example.function46 source.java:46:0 s=0 + 61: 0x0 com.example.function47 source.java:47:0 s=0 + 62: 0x0 com.example.function48 source.java:48:0 s=0 + 63: 0x0 com.example.function49 source.java:49:0 s=0 + 64: 0x0 com.example.function4a source.java:4:0 s=0 Mappings diff --git a/profile/testdata/java.heap.string b/profile/testdata/java.heap.string index 261bee13a..5e1b549d3 100644 --- a/profile/testdata/java.heap.string +++ b/profile/testdata/java.heap.string @@ -17,123 +17,123 @@ inuse_objects/count inuse_space/bytes 54615 2621560: 119 bytes:[48] Locations - 1: 0x0 com.example.function003 Source003.java:103 s=0 - 2: 0x0 com.example.function004 Source004.java:104 s=0 - 3: 0x0 com.example.function005 Source005.java:105 s=0 - 4: 0x0 com.example.function006 Source006.java:106 s=0 - 5: 0x0 com.example.function007 Source007.java:107 s=0 - 6: 0x0 com.example.function008 Source008.java:108 s=0 - 7: 0x0 com.example.function009 Source009.java:109 s=0 - 8: 0x0 com.example.function00a Source00a.java:10 s=0 - 9: 0x0 com.example.function00b Source00b.java:10 s=0 - 10: 0x0 com.example.function00c Source00c.java:10 s=0 - 11: 0x0 com.example.function00d Source00d.java:10 s=0 - 12: 0x0 com.example.function00e Source00e.java:10 s=0 - 13: 0x0 com.example.function00f Source00f.java:10 s=0 - 14: 0x0 com.example.function010 Source010.java:110 s=0 - 15: 0x0 com.example.function011 Source011.java:111 s=0 - 16: 0x0 com.example.function018 Source018.java:118 s=0 - 17: 0x0 com.example.function019 Source019.java:119 s=0 - 18: 0x0 com.example.function01a Source01a.java:11 s=0 - 19: 0x0 com.example.function01b Source01b.java:11 s=0 - 20: 0x0 com.example.function01c Source01c.java:11 s=0 - 21: 0x0 com.example.function01d Source01d.java:11 s=0 - 22: 0x0 com.example.function01e Source01e.java:11 s=0 - 23: 0x0 com.example.function01f Source01f.java:11 s=0 - 24: 0x0 com.example.function020 Source020.java:120 s=0 - 25: 0x0 com.example.function021 Source021.java:121 s=0 - 26: 0x0 com.example.function022 Source022.java:122 s=0 - 27: 0x0 com.example.function023 Source023.java:123 s=0 - 28: 0x0 com.example.function024 Source024.java:124 s=0 - 29: 0x0 com.example.function025 Source025.java:125 s=0 - 30: 0x0 com.example.function026 Source026.java:126 s=0 - 31: 0x0 com.example.function027 Source027.java:127 s=0 - 32: 0x0 com.example.function028 Source028.java:128 s=0 - 33: 0x0 com.example.function029 Source029.java:129 s=0 - 34: 0x0 com.example.function02a Source02a.java:12 s=0 - 35: 0x0 com.example.function02b Source02b.java:12 s=0 - 36: 0x0 com.example.function02c Source02c.java:12 s=0 - 37: 0x0 com.example.function02d Source02d.java:12 s=0 - 38: 0x0 com.example.function02e Source02e.java:12 s=0 - 39: 0x0 com.example.function035 Source035.java:135 s=0 - 40: 0x0 com.example.function036 Source036.java:136 s=0 - 41: 0x0 com.example.function037 Source037.java:137 s=0 - 42: 0x0 com.example.function038 Source038.java:138 s=0 - 43: 0x0 com.example.function039 Source039.java:139 s=0 - 44: 0x0 com.example.function03a Source03a.java:13 s=0 - 45: 0x0 com.example.function03b Source03b.java:13 s=0 - 46: 0x0 com.example.function03d Source03d.java:13 s=0 - 47: 0x0 com.example.function03e Source03e.java:13 s=0 - 48: 0x0 com.example.function03f Source03f.java:13 s=0 - 49: 0x0 com.example.function040 Source040.java:140 s=0 - 50: 0x0 com.example.function041 Source041.java:141 s=0 - 51: 0x0 com.example.function042 Source042.java:142 s=0 - 52: 0x0 com.example.function049 Source049.java:149 s=0 - 53: 0x0 com.example.function04a Source04a.java:14 s=0 - 54: 0x0 com.example.function04b Source04b.java:14 s=0 - 55: 0x0 com.example.function04c Source04c.java:14 s=0 - 56: 0x0 com.example.function04d Source04d.java:14 s=0 - 57: 0x0 com.example.function04e Source04e.java:14 s=0 - 58: 0x0 com.example.function04f Source04f.java:14 s=0 - 59: 0x0 com.example.function050 Source050.java:150 s=0 - 60: 0x0 com.example.function051 Source051.java:151 s=0 - 61: 0x0 com.example.function052 Source052.java:152 s=0 - 62: 0x0 com.example.function053 Source053.java:153 s=0 - 63: 0x0 com.example.function054 Source054.java:154 s=0 - 64: 0x0 com.example.function055 Source055.java:155 s=0 - 65: 0x0 com.example.function056 Source056.java:156 s=0 - 66: 0x0 com.example.function057 Source057.java:157 s=0 - 67: 0x0 com.example.function05e Source05e.java:15 s=0 - 68: 0x0 com.example.function05f Source05f.java:15 s=0 - 69: 0x0 com.example.function060 Source060.java:160 s=0 - 70: 0x0 com.example.function061 Source061.java:161 s=0 - 71: 0x0 com.example.function062 Source062.java:162 s=0 - 72: 0x0 com.example.function063 Source063.java:163 s=0 - 73: 0x0 com.example.function064 Source064.java:164 s=0 - 74: 0x0 com.example.function065 Source065.java:165 s=0 - 75: 0x0 com.example.function066 Source066.java:166 s=0 - 76: 0x0 com.example.function067 Source067.java:167 s=0 - 77: 0x0 com.example.function068 Source068.java:168 s=0 - 78: 0x0 com.example.function069 Source069.java:169 s=0 - 79: 0x0 com.example.function06a Source06a.java:16 s=0 - 80: 0x0 com.example.function06b Source06b.java:16 s=0 - 81: 0x0 com.example.function06c Source06c.java:16 s=0 - 82: 0x0 com.example.function06d Source06d.java:16 s=0 - 83: 0x0 com.example.function06e Source06e.java:16 s=0 - 84: 0x0 com.example.function06f Source06f.java:16 s=0 - 85: 0x0 com.example.function070 Source070.java:170 s=0 - 86: 0x0 com.example.function071 Source071.java:171 s=0 - 87: 0x0 com.example.function072 Source072.java:172 s=0 - 88: 0x0 com.example.function073 Source073.java:173 s=0 - 89: 0x0 com.example.function074 Source074.java:174 s=0 - 90: 0x0 com.example.function075 Source075.java:175 s=0 - 91: 0x0 com.example.function076 Source076.java:176 s=0 - 92: 0x0 com.example.function077 Source077.java:177 s=0 - 93: 0x0 com.example.function078 Source078.java:178 s=0 - 94: 0x0 com.example.function079 Source079.java:179 s=0 - 95: 0x0 com.example.function07a Source07a.java:17 s=0 - 96: 0x0 com.example.function07b Source07b.java:17 s=0 - 97: 0x0 com.example.function081 Source081.java:181 s=0 - 98: 0x0 com.example.function082 Source082.java:182 s=0 - 99: 0x0 com.example.function083 Source083.java:183 s=0 - 100: 0x0 com.example.function084 Source084.java:184 s=0 - 101: 0x0 com.example.function085 Source085.java:185 s=0 - 102: 0x0 com.example.function086 Source086.java:186 s=0 - 103: 0x0 com.example.function087 Source087.java:187 s=0 - 104: 0x0 com.example.function088 Source088.java:188 s=0 - 105: 0x0 com.example.function089 Source089.java:189 s=0 - 106: 0x0 com.example.function08a Source08a.java:18 s=0 - 107: 0x0 com.example.function08b Source08b.java:18 s=0 - 108: 0x0 com.example.function08c Source08c.java:18 s=0 - 109: 0x0 com.example.function08d Source08d.java:18 s=0 - 110: 0x0 com.example.function08e Source08e.java:18 s=0 - 111: 0x0 com.example.function08f Source08f.java:18 s=0 - 112: 0x0 com.example.function090 Source090.java:190 s=0 - 113: 0x0 com.example.function091 Source091.java:191 s=0 - 114: 0x0 com.example.function092 Source092.java:192 s=0 - 115: 0x0 com.example.function093 Source093.java:193 s=0 - 116: 0x0 com.example.function094 Source094.java:194 s=0 - 117: 0x0 com.example.function095 Source095.java:195 s=0 - 118: 0x0 com.example.function096 Source096.java:196 s=0 - 119: 0x0 com.example.function097 Source097.java:197 s=0 + 1: 0x0 com.example.function003 Source003.java:103:0 s=0 + 2: 0x0 com.example.function004 Source004.java:104:0 s=0 + 3: 0x0 com.example.function005 Source005.java:105:0 s=0 + 4: 0x0 com.example.function006 Source006.java:106:0 s=0 + 5: 0x0 com.example.function007 Source007.java:107:0 s=0 + 6: 0x0 com.example.function008 Source008.java:108:0 s=0 + 7: 0x0 com.example.function009 Source009.java:109:0 s=0 + 8: 0x0 com.example.function00a Source00a.java:10:0 s=0 + 9: 0x0 com.example.function00b Source00b.java:10:0 s=0 + 10: 0x0 com.example.function00c Source00c.java:10:0 s=0 + 11: 0x0 com.example.function00d Source00d.java:10:0 s=0 + 12: 0x0 com.example.function00e Source00e.java:10:0 s=0 + 13: 0x0 com.example.function00f Source00f.java:10:0 s=0 + 14: 0x0 com.example.function010 Source010.java:110:0 s=0 + 15: 0x0 com.example.function011 Source011.java:111:0 s=0 + 16: 0x0 com.example.function018 Source018.java:118:0 s=0 + 17: 0x0 com.example.function019 Source019.java:119:0 s=0 + 18: 0x0 com.example.function01a Source01a.java:11:0 s=0 + 19: 0x0 com.example.function01b Source01b.java:11:0 s=0 + 20: 0x0 com.example.function01c Source01c.java:11:0 s=0 + 21: 0x0 com.example.function01d Source01d.java:11:0 s=0 + 22: 0x0 com.example.function01e Source01e.java:11:0 s=0 + 23: 0x0 com.example.function01f Source01f.java:11:0 s=0 + 24: 0x0 com.example.function020 Source020.java:120:0 s=0 + 25: 0x0 com.example.function021 Source021.java:121:0 s=0 + 26: 0x0 com.example.function022 Source022.java:122:0 s=0 + 27: 0x0 com.example.function023 Source023.java:123:0 s=0 + 28: 0x0 com.example.function024 Source024.java:124:0 s=0 + 29: 0x0 com.example.function025 Source025.java:125:0 s=0 + 30: 0x0 com.example.function026 Source026.java:126:0 s=0 + 31: 0x0 com.example.function027 Source027.java:127:0 s=0 + 32: 0x0 com.example.function028 Source028.java:128:0 s=0 + 33: 0x0 com.example.function029 Source029.java:129:0 s=0 + 34: 0x0 com.example.function02a Source02a.java:12:0 s=0 + 35: 0x0 com.example.function02b Source02b.java:12:0 s=0 + 36: 0x0 com.example.function02c Source02c.java:12:0 s=0 + 37: 0x0 com.example.function02d Source02d.java:12:0 s=0 + 38: 0x0 com.example.function02e Source02e.java:12:0 s=0 + 39: 0x0 com.example.function035 Source035.java:135:0 s=0 + 40: 0x0 com.example.function036 Source036.java:136:0 s=0 + 41: 0x0 com.example.function037 Source037.java:137:0 s=0 + 42: 0x0 com.example.function038 Source038.java:138:0 s=0 + 43: 0x0 com.example.function039 Source039.java:139:0 s=0 + 44: 0x0 com.example.function03a Source03a.java:13:0 s=0 + 45: 0x0 com.example.function03b Source03b.java:13:0 s=0 + 46: 0x0 com.example.function03d Source03d.java:13:0 s=0 + 47: 0x0 com.example.function03e Source03e.java:13:0 s=0 + 48: 0x0 com.example.function03f Source03f.java:13:0 s=0 + 49: 0x0 com.example.function040 Source040.java:140:0 s=0 + 50: 0x0 com.example.function041 Source041.java:141:0 s=0 + 51: 0x0 com.example.function042 Source042.java:142:0 s=0 + 52: 0x0 com.example.function049 Source049.java:149:0 s=0 + 53: 0x0 com.example.function04a Source04a.java:14:0 s=0 + 54: 0x0 com.example.function04b Source04b.java:14:0 s=0 + 55: 0x0 com.example.function04c Source04c.java:14:0 s=0 + 56: 0x0 com.example.function04d Source04d.java:14:0 s=0 + 57: 0x0 com.example.function04e Source04e.java:14:0 s=0 + 58: 0x0 com.example.function04f Source04f.java:14:0 s=0 + 59: 0x0 com.example.function050 Source050.java:150:0 s=0 + 60: 0x0 com.example.function051 Source051.java:151:0 s=0 + 61: 0x0 com.example.function052 Source052.java:152:0 s=0 + 62: 0x0 com.example.function053 Source053.java:153:0 s=0 + 63: 0x0 com.example.function054 Source054.java:154:0 s=0 + 64: 0x0 com.example.function055 Source055.java:155:0 s=0 + 65: 0x0 com.example.function056 Source056.java:156:0 s=0 + 66: 0x0 com.example.function057 Source057.java:157:0 s=0 + 67: 0x0 com.example.function05e Source05e.java:15:0 s=0 + 68: 0x0 com.example.function05f Source05f.java:15:0 s=0 + 69: 0x0 com.example.function060 Source060.java:160:0 s=0 + 70: 0x0 com.example.function061 Source061.java:161:0 s=0 + 71: 0x0 com.example.function062 Source062.java:162:0 s=0 + 72: 0x0 com.example.function063 Source063.java:163:0 s=0 + 73: 0x0 com.example.function064 Source064.java:164:0 s=0 + 74: 0x0 com.example.function065 Source065.java:165:0 s=0 + 75: 0x0 com.example.function066 Source066.java:166:0 s=0 + 76: 0x0 com.example.function067 Source067.java:167:0 s=0 + 77: 0x0 com.example.function068 Source068.java:168:0 s=0 + 78: 0x0 com.example.function069 Source069.java:169:0 s=0 + 79: 0x0 com.example.function06a Source06a.java:16:0 s=0 + 80: 0x0 com.example.function06b Source06b.java:16:0 s=0 + 81: 0x0 com.example.function06c Source06c.java:16:0 s=0 + 82: 0x0 com.example.function06d Source06d.java:16:0 s=0 + 83: 0x0 com.example.function06e Source06e.java:16:0 s=0 + 84: 0x0 com.example.function06f Source06f.java:16:0 s=0 + 85: 0x0 com.example.function070 Source070.java:170:0 s=0 + 86: 0x0 com.example.function071 Source071.java:171:0 s=0 + 87: 0x0 com.example.function072 Source072.java:172:0 s=0 + 88: 0x0 com.example.function073 Source073.java:173:0 s=0 + 89: 0x0 com.example.function074 Source074.java:174:0 s=0 + 90: 0x0 com.example.function075 Source075.java:175:0 s=0 + 91: 0x0 com.example.function076 Source076.java:176:0 s=0 + 92: 0x0 com.example.function077 Source077.java:177:0 s=0 + 93: 0x0 com.example.function078 Source078.java:178:0 s=0 + 94: 0x0 com.example.function079 Source079.java:179:0 s=0 + 95: 0x0 com.example.function07a Source07a.java:17:0 s=0 + 96: 0x0 com.example.function07b Source07b.java:17:0 s=0 + 97: 0x0 com.example.function081 Source081.java:181:0 s=0 + 98: 0x0 com.example.function082 Source082.java:182:0 s=0 + 99: 0x0 com.example.function083 Source083.java:183:0 s=0 + 100: 0x0 com.example.function084 Source084.java:184:0 s=0 + 101: 0x0 com.example.function085 Source085.java:185:0 s=0 + 102: 0x0 com.example.function086 Source086.java:186:0 s=0 + 103: 0x0 com.example.function087 Source087.java:187:0 s=0 + 104: 0x0 com.example.function088 Source088.java:188:0 s=0 + 105: 0x0 com.example.function089 Source089.java:189:0 s=0 + 106: 0x0 com.example.function08a Source08a.java:18:0 s=0 + 107: 0x0 com.example.function08b Source08b.java:18:0 s=0 + 108: 0x0 com.example.function08c Source08c.java:18:0 s=0 + 109: 0x0 com.example.function08d Source08d.java:18:0 s=0 + 110: 0x0 com.example.function08e Source08e.java:18:0 s=0 + 111: 0x0 com.example.function08f Source08f.java:18:0 s=0 + 112: 0x0 com.example.function090 Source090.java:190:0 s=0 + 113: 0x0 com.example.function091 Source091.java:191:0 s=0 + 114: 0x0 com.example.function092 Source092.java:192:0 s=0 + 115: 0x0 com.example.function093 Source093.java:193:0 s=0 + 116: 0x0 com.example.function094 Source094.java:194:0 s=0 + 117: 0x0 com.example.function095 Source095.java:195:0 s=0 + 118: 0x0 com.example.function096 Source096.java:196:0 s=0 + 119: 0x0 com.example.function097 Source097.java:197:0 s=0 Mappings diff --git a/proto/profile.proto b/proto/profile.proto index c41ec50e8..ff987a617 100644 --- a/proto/profile.proto +++ b/proto/profile.proto @@ -208,6 +208,8 @@ message Line { uint64 function_id = 1; // Line number in source code. int64 line = 2; + // Column number in source code. + int64 column = 3; } message Function {