Skip to content
This repository was archived by the owner on Oct 18, 2024. It is now read-only.

Commit 383f7cd

Browse files
hihoakartemikhaylov
andauthored
dramatically Increase performance of tool (#107)
* done * fix hardcode * remove import * remove comments * Revert "remove comments" This reverts commit e74459a. * Revert "remove import" This reverts commit 5aa5ffb. * Revert "fix hardcode" This reverts commit e5e62ed. * Revert "done" This reverts commit 0fe7a9e. * remade logic to support not only local modules * remove unused variables * rename variables * remade on package.Load function * make with one call * go mod tidy * fix potential bug with name collisions because of use HasSuffix * a bit optimize cycles and rename function to convertProfile back * change from filepath to path --------- Co-authored-by: artemikhaylov <[email protected]>
1 parent dd288a8 commit 383f7cd

File tree

3 files changed

+70
-49
lines changed

3 files changed

+70
-49
lines changed

go.mod

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
module github.com/axw/gocov
22

3-
go 1.12
3+
go 1.22.0
4+
5+
toolchain go1.22.7
46

57
require (
68
github.com/stretchr/testify v1.7.1
7-
golang.org/x/tools v0.0.0-20190617190820-da514acc4774
9+
golang.org/x/tools v0.13.0
10+
)
11+
12+
require (
13+
github.com/davecgh/go-spew v1.1.0 // indirect
14+
github.com/pmezard/go-difflib v1.0.0 // indirect
15+
golang.org/x/mod v0.21.0 // indirect
16+
golang.org/x/sys v0.12.0 // indirect
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
818
)

go.sum

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
55
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
66
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
77
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
8-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
9-
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
10-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
11-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
12-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13-
golang.org/x/tools v0.0.0-20190617190820-da514acc4774 h1:CQVOmarCBFzTx0kbOU0ru54Cvot8SdSrNYjZPhQl+gk=
14-
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
8+
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
9+
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
10+
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
11+
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
12+
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
13+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
14+
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
15+
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
1516
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1617
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1718
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=

gocov/convert/convert.go

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,26 @@ import (
2424
"bytes"
2525
"encoding/json"
2626
"fmt"
27+
"github.com/axw/gocov"
28+
"github.com/axw/gocov/gocovutil"
2729
"go/ast"
28-
"go/build"
2930
"go/parser"
3031
"go/token"
32+
"golang.org/x/tools/cover"
33+
goPackages "golang.org/x/tools/go/packages"
3134
"io"
35+
"path"
3236
"path/filepath"
3337
"strings"
34-
35-
"github.com/axw/gocov"
36-
"github.com/axw/gocov/gocovutil"
37-
"golang.org/x/tools/cover"
3838
)
3939

4040
func marshalJson(w io.Writer, packages []*gocov.Package) error {
4141
return json.NewEncoder(w).Encode(struct{ Packages []*gocov.Package }{packages})
4242
}
4343

44-
type packagesCache map[string]*build.Package
45-
4644
func ConvertProfiles(filenames ...string) ([]byte, error) {
4745
var (
48-
ps gocovutil.Packages
49-
packages = make(packagesCache)
46+
ps gocovutil.Packages
5047
)
5148

5249
for i := range filenames {
@@ -57,9 +54,42 @@ func ConvertProfiles(filenames ...string) ([]byte, error) {
5754
if err != nil {
5855
return nil, err
5956
}
60-
for _, p := range profiles {
61-
if err := converter.convertProfile(packages, p); err != nil {
62-
return nil, err
57+
58+
mapUniqPackageNames := make(map[string]interface{})
59+
uniqPackageNames := make([]string, 0, len(profiles))
60+
for _, profile := range profiles {
61+
packageName := path.Dir(profile.FileName)
62+
63+
if _, ok := mapUniqPackageNames[packageName]; ok {
64+
continue
65+
}
66+
67+
mapUniqPackageNames[packageName] = nil
68+
uniqPackageNames = append(uniqPackageNames, packageName)
69+
}
70+
71+
packages, err := goPackages.Load(&goPackages.Config{
72+
Mode: goPackages.NeedName | goPackages.NeedCompiledGoFiles,
73+
}, uniqPackageNames...)
74+
if err != nil {
75+
return nil, fmt.Errorf("load packages: %v", err)
76+
}
77+
78+
pkgmap := make(map[string]*goPackages.Package, len(packages))
79+
for _, pkg := range packages {
80+
pkgmap[pkg.PkgPath] = pkg
81+
}
82+
83+
for _, profile := range profiles {
84+
pkgpath, filename := path.Split(profile.FileName)
85+
pkgpath = strings.TrimSuffix(pkgpath, "/")
86+
pkg := pkgmap[pkgpath]
87+
for _, abspath := range pkg.CompiledGoFiles {
88+
if filepath.Base(abspath) == filename {
89+
if err := converter.convertProfile(profile, abspath, pkg.PkgPath); err != nil {
90+
return nil, fmt.Errorf("convert profile %s: %w", profile.FileName, err)
91+
}
92+
}
6393
}
6494
}
6595

@@ -84,29 +114,26 @@ type statement struct {
84114
*StmtExtent
85115
}
86116

87-
func (c *converter) convertProfile(packages packagesCache, p *cover.Profile) error {
88-
file, pkgpath, err := findFile(packages, p.FileName)
89-
if err != nil {
90-
return err
91-
}
92-
pkg := c.packages[pkgpath]
117+
func (c *converter) convertProfile(p *cover.Profile, absFilePath, pkgPath string) error {
118+
pkg := c.packages[pkgPath]
93119
if pkg == nil {
94-
pkg = &gocov.Package{Name: pkgpath}
95-
c.packages[pkgpath] = pkg
120+
pkg = &gocov.Package{Name: pkgPath}
121+
c.packages[pkgPath] = pkg
96122
}
97123
// Find function and statement extents; create corresponding
98124
// gocov.Functions and gocov.Statements, and keep a separate
99125
// slice of gocov.Statements so we can match them with profile
100126
// blocks.
101-
extents, err := findFuncs(file)
127+
extents, err := findFuncs(absFilePath)
102128
if err != nil {
103129
return err
104130
}
131+
105132
var stmts []statement
106133
for _, fe := range extents {
107134
f := &gocov.Function{
108135
Name: fe.name,
109-
File: file,
136+
File: absFilePath,
110137
Start: fe.startOffset,
111138
End: fe.endOffset,
112139
}
@@ -138,25 +165,8 @@ func (c *converter) convertProfile(packages packagesCache, p *cover.Profile) err
138165
break
139166
}
140167
}
141-
return nil
142-
}
143-
144-
// findFile finds the location of the named file in GOROOT, GOPATH etc.
145-
func findFile(packages packagesCache, file string) (filename, pkgpath string, err error) {
146-
dir, file := filepath.Split(file)
147-
if dir != "" {
148-
dir = strings.TrimSuffix(dir, "/")
149-
}
150-
pkg, ok := packages[dir]
151-
if !ok {
152-
pkg, err = build.Import(dir, ".", build.FindOnly)
153-
if err != nil {
154-
return "", "", fmt.Errorf("can't find %q: %w", file, err)
155-
}
156-
packages[dir] = pkg
157-
}
158168

159-
return filepath.Join(pkg.Dir, file), pkg.ImportPath, nil
169+
return nil
160170
}
161171

162172
// findFuncs parses the file and returns a slice of FuncExtent descriptors.

0 commit comments

Comments
 (0)