Skip to content

Commit 2bd8803

Browse files
authored
feat: speed up build graph (cloudwego#156)
1 parent 9dd957d commit 2bd8803

3 files changed

Lines changed: 62 additions & 9 deletions

File tree

lang/uniast/ast_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,17 @@ func TestRepository_BuildGraph(t *testing.T) {
4242
}
4343
}
4444
}
45+
46+
func BenchmarkRepository_BuildGraph(b *testing.B) {
47+
astFile := testutils.GetTestAstFile("large_ast")
48+
r, err := LoadRepo(astFile)
49+
if err != nil {
50+
b.Fatalf("failed to load repo: %v", err)
51+
}
52+
b.ResetTimer()
53+
for i := 0; i < b.N; i++ {
54+
if err := r.BuildGraph(); err != nil {
55+
b.Fatalf("failed to build graph: %v", err)
56+
}
57+
}
58+
}

lang/uniast/node.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,32 @@ func (r *Repository) AllNodesSetRepo() {
159159
}
160160

161161
func (r *Repository) BuildGraph() error {
162-
r.Graph = make(map[string]*Node)
162+
// Optimization: Pre-calculate total number of internal nodes to pre-allocate Graph map
163+
var totalNodes int
164+
for _, mod := range r.Modules {
165+
if mod.IsExternal() {
166+
continue
167+
}
168+
for _, pkg := range mod.Packages {
169+
totalNodes += len(pkg.Functions) + len(pkg.Types) + len(pkg.Vars)
170+
}
171+
}
172+
r.Graph = make(map[string]*Node, totalNodes)
163173
for _, mod := range r.Modules {
164174
if mod.IsExternal() {
165175
continue
166176
}
167177
for _, pkg := range mod.Packages {
168178
for _, f := range pkg.Functions {
169179
n := r.SetNode(f.Identity, FUNC)
180+
// Pre-allocate Dependencies
181+
capDeps := len(f.Params) + len(f.Results) + len(f.FunctionCalls) + len(f.MethodCalls) + len(f.Types) + len(f.GlobalVars)
182+
if f.Receiver != nil {
183+
capDeps++
184+
}
185+
if n.Dependencies == nil && capDeps > 0 {
186+
n.Dependencies = make([]Relation, 0, capDeps)
187+
}
170188
for _, dep := range f.Params {
171189
r.AddRelation(n, dep.Identity, dep.FileLine, DEPENDENCY)
172190
}
@@ -193,6 +211,16 @@ func (r *Repository) BuildGraph() error {
193211

194212
for _, t := range pkg.Types {
195213
n := r.SetNode(t.Identity, TYPE)
214+
// Pre-allocate Dependencies, Inherits, Implements
215+
if n.Dependencies == nil && len(t.SubStruct) > 0 {
216+
n.Dependencies = make([]Relation, 0, len(t.SubStruct))
217+
}
218+
if n.Inherits == nil && len(t.InlineStruct) > 0 {
219+
n.Inherits = make([]Relation, 0, len(t.InlineStruct))
220+
}
221+
if n.Implements == nil && len(t.Implements) > 0 {
222+
n.Implements = make([]Relation, 0, len(t.Implements))
223+
}
196224
for _, dep := range t.SubStruct {
197225
r.AddRelation(n, dep.Identity, dep.FileLine, DEPENDENCY)
198226
}
@@ -206,6 +234,17 @@ func (r *Repository) BuildGraph() error {
206234

207235
for _, v := range pkg.Vars {
208236
n := r.SetNode(v.Identity, VAR)
237+
// Pre-allocate Dependencies and Groups
238+
capDeps := len(v.Dependencies)
239+
if v.Type != nil {
240+
capDeps++
241+
}
242+
if n.Dependencies == nil && capDeps > 0 {
243+
n.Dependencies = make([]Relation, 0, capDeps)
244+
}
245+
if n.Groups == nil && len(v.Groups) > 0 {
246+
n.Groups = make([]Relation, 0, len(v.Groups))
247+
}
209248
if v.Type != nil {
210249
r.AddRelation(n, *v.Type, v.FileLine, DEPENDENCY)
211250
}

lang/uniast/utils.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,35 @@ import (
2222
)
2323

2424
func Append[T comparable](ids []T, id T) []T {
25-
for _, i := range ids {
26-
if i == id {
25+
for i := range ids {
26+
if ids[i] == id {
2727
return ids
2828
}
2929
}
3030
return append(ids, id)
3131
}
3232

3333
func InsertDependency(ids []Dependency, id Dependency) []Dependency {
34-
for _, i := range ids {
35-
if i.Identity == id.Identity {
34+
for i := range ids {
35+
if ids[i].Identity == id.Identity {
3636
return ids
3737
}
3838
}
3939
return append(ids, id)
4040
}
4141

4242
func InserImport(ids []Import, id Import) []Import {
43-
for _, i := range ids {
44-
if i.Path == id.Path {
43+
for i := range ids {
44+
if ids[i].Path == id.Path {
4545
return ids
4646
}
4747
}
4848
return append(ids, id)
4949
}
5050

5151
func InsertRelation(ids []Relation, id Relation) []Relation {
52-
for _, i := range ids {
53-
if i.Identity == id.Identity {
52+
for i := range ids {
53+
if ids[i].Identity == id.Identity {
5454
return ids
5555
}
5656
}

0 commit comments

Comments
 (0)