Skip to content

Commit 71b7fa9

Browse files
John Dethridgezpavlinovic
John Dethridge
authored andcommitted
go/callgraph/vta: save some heap allocations in the trie implementation
The mkLeaf and mkBranch functions use hash consing to dedup values, by constructing the leaf or branch value, and inserting it into a hash map if the value is not already there. This change uses two variables, one as the key for the map lookup, and a second for the map value. This leads the compiler to place the first on the stack and the second on the heap, so that a heap allocation is only done if there is a cache miss. This can be a significant saving for large VTA type graphs. name old time/op new time/op delta TrieStandard-16 2.35µs ± 6% 2.03µs ± 5% -13.48% (p=0.008 n=5+5) TrieSmallWide-16 1.70µs ± 8% 1.41µs ± 5% -16.76% (p=0.008 n=5+5) name old alloc/op new alloc/op delta TrieStandard-16 1.20kB ± 9% 0.89kB ± 5% -26.33% (p=0.008 n=5+5) TrieSmallWide-16 812B ±12% 480B ± 5% -40.94% (p=0.008 n=5+5) name old allocs/op new allocs/op delta TrieStandard-16 6.00 ± 0% 3.00 ± 0% -50.00% (p=0.008 n=5+5) TrieSmallWide-16 8.00 ± 0% 1.00 ± 0% -87.50% (p=0.008 n=5+5) Change-Id: I7faeb5458320972f9a267ff7ead04b4e5c31dfb8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/588217 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Zvonimir Pavlinovic <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Tim King <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Run-TryBot: Zvonimir Pavlinovic <[email protected]>
1 parent 2f8e378 commit 71b7fa9

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

go/callgraph/vta/internal/trie/builder.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,12 @@ func (b *Builder) create(leaves []*leaf) node {
260260

261261
// mkLeaf returns the hash-consed representative of (k, v) in the current scope.
262262
func (b *Builder) mkLeaf(k key, v interface{}) *leaf {
263-
l := &leaf{k: k, v: v}
264-
if rep, ok := b.leaves[*l]; ok {
265-
return rep
263+
rep, ok := b.leaves[leaf{k, v}]
264+
if !ok {
265+
rep = &leaf{k, v} // heap-allocated copy
266+
b.leaves[leaf{k, v}] = rep
266267
}
267-
b.leaves[*l] = l
268-
return l
268+
return rep
269269
}
270270

271271
// mkBranch returns the hash-consed representative of the tuple
@@ -274,18 +274,20 @@ func (b *Builder) mkLeaf(k key, v interface{}) *leaf {
274274
//
275275
// in the current scope.
276276
func (b *Builder) mkBranch(p prefix, bp bitpos, left node, right node) *branch {
277-
br := &branch{
277+
br := branch{
278278
sz: left.size() + right.size(),
279279
prefix: p,
280280
branching: bp,
281281
left: left,
282282
right: right,
283283
}
284-
if rep, ok := b.branches[*br]; ok {
285-
return rep
284+
rep, ok := b.branches[br]
285+
if !ok {
286+
rep = new(branch) // heap-allocated copy
287+
*rep = br
288+
b.branches[br] = rep
286289
}
287-
b.branches[*br] = br
288-
return br
290+
return rep
289291
}
290292

291293
// join two maps with prefixes p0 and p1 that are *known* to disagree.

0 commit comments

Comments
 (0)