@@ -3,11 +3,26 @@ package compiler
33import (
44 "fmt"
55 "sort"
6+ "time"
67)
78
89type DeclCache struct {
910 decls map [string ]* Decl
1011 changed bool
12+ stats declCacheStats
13+ }
14+
15+ var declCacheGlobalStats declCacheStats
16+
17+ type declCacheStats struct {
18+ reads int // number of times Read was called (should be 0 or 1 unless global)
19+ writes int // number of times Write was called (should be 0 or 1 unless global)
20+ loadedCount int // number of declarations loaded from storage
21+ addedCount int // number of declarations added to the cache
22+ skippedCount int // number of declarations not cached (for being generic or non-unique)
23+ usedCount int // number of times a declaration was retrieved from the cache
24+ readDur time.Duration
25+ writeDur time.Duration
1126}
1227
1328// Chacnged reports whether the cache has had declarations added to it since
@@ -25,7 +40,12 @@ func (dc *DeclCache) GetDecl(fullname string) *Decl {
2540 if dc == nil {
2641 return nil // cache is disabled
2742 }
28- return dc .decls [fullname ]
43+ if decl , ok := dc .decls [fullname ]; ok {
44+ dc .stats .usedCount ++
45+ declCacheGlobalStats .usedCount ++
46+ return decl
47+ }
48+ return nil
2949}
3050
3151func (dc * DeclCache ) PutDecl (decl * Decl ) {
@@ -44,32 +64,49 @@ func (dc *DeclCache) PutDecl(decl *Decl) {
4464 // Therefore, if the package depending on this one changes a type from
4565 // being blocking to non-blocking or vice versa, the cached declaration
4666 // may be invalid.
67+ //
68+ // TODO(grantnelson-wf): We could improve this by tracking which packages
69+ // the type arguments come from and allow caching if those are all from
70+ // dependencies. Since we don't use cache when a dependency changes,
71+ // (i.e. has stale cache) we can use generics in that case. We just can't
72+ // cache the instantiations that come from packages depending on this one
73+ // since those don't invalidate dependent packages' caches.
74+ dc .stats .skippedCount ++
75+ declCacheGlobalStats .skippedCount ++
4776 return
4877 }
4978
50- if isUnqueDeclFullName (decl .FullName ) {
79+ if ! isUniqueDeclFullName (decl .FullName ) {
5180 // Only cache declarations with unique names.
81+ dc .stats .skippedCount ++
82+ declCacheGlobalStats .skippedCount ++
5283 return
5384 }
5485
55- if dc .decls == nil {
56- dc .decls = map [string ]* Decl {}
57- }
5886 if existing , ok := dc .decls [decl .FullName ]; ok {
5987 if existing != decl {
6088 panic (fmt .Errorf (`decl cache conflict: different decls with same name: %q` , decl .FullName ))
6189 }
6290 return
6391 }
92+
93+ if dc .decls == nil {
94+ dc .decls = map [string ]* Decl {}
95+ }
6496 dc .decls [decl .FullName ] = decl
6597 dc .changed = true
98+ dc .stats .addedCount ++
99+ declCacheGlobalStats .addedCount ++
66100}
67101
68102func (dc * DeclCache ) Read (decode func (any ) error ) error {
69103 if dc == nil {
70104 return nil // cache is disabled
71105 }
72106
107+ dc .stats .reads ++
108+ declCacheGlobalStats .reads ++
109+ start := time .Now ()
73110 var count int
74111 if err := decode (& count ); err != nil {
75112 return err
@@ -83,12 +120,18 @@ func (dc *DeclCache) Read(decode func(any) error) error {
83120 if err := decode (decl ); err != nil {
84121 return err
85122 }
86- if decl .ForGeneric || isUnqueDeclFullName (decl .FullName ) {
123+ if decl .ForGeneric || ! isUniqueDeclFullName (decl .FullName ) {
87124 // These declarations should not have been cached.
88125 continue
89126 }
90127 dc .decls [decl .FullName ] = decl
91128 }
129+
130+ dc .stats .loadedCount += len (dc .decls )
131+ declCacheGlobalStats .loadedCount += len (dc .decls )
132+ dur := time .Since (start )
133+ dc .stats .readDur += dur
134+ declCacheGlobalStats .readDur += dur
92135 return nil
93136}
94137
@@ -97,6 +140,9 @@ func (dc *DeclCache) Write(encode func(any) error) error {
97140 return nil // cache is disabled
98141 }
99142
143+ dc .stats .writes ++
144+ declCacheGlobalStats .writes ++
145+ start := time .Now ()
100146 count := len (dc .decls )
101147 if err := encode (count ); err != nil {
102148 return err
@@ -113,5 +159,28 @@ func (dc *DeclCache) Write(encode func(any) error) error {
113159 return err
114160 }
115161 }
162+ dur := time .Since (start )
163+ dc .stats .writeDur += dur
164+ declCacheGlobalStats .writeDur += dur
116165 return nil
117166}
167+
168+ func (dc * DeclCache ) String () string {
169+ if dc == nil {
170+ return `[disabled]`
171+ }
172+ return dc .stats .String ()
173+ }
174+
175+ func (s declCacheStats ) String () string {
176+ return fmt .Sprintf (`reads=%d, writes=%d, ` +
177+ `loaded=%d, added=%d, skipped=%d, used=%d, ` +
178+ `readDur=%s, writeDur=%s` ,
179+ s .reads , s .writes ,
180+ s .loadedCount , s .addedCount , s .skippedCount , s .usedCount ,
181+ s .readDur .String (), s .writeDur .String ())
182+ }
183+
184+ func GlobalDeclCacheStats () string {
185+ return declCacheGlobalStats .String ()
186+ }
0 commit comments