diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-04-25 10:06:37 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-04-26 05:58:31 +0200 |
| commit | 0ce7569ee76fda7e5a68b0fe14c93a3e8eb7d108 (patch) | |
| tree | 79adf4f1b16a3d58c2b436dceaff2e873e2f51bd /prog/target.go | |
| parent | 99b258ddc33e296f07588a15397ae426c6ed236c (diff) | |
pkg/compiler: deduplicate Types in descriptions
Add prog.Ref Type that serves as a proxy for real types
and allows to deduplicate Types in generated descriptions.
The Ref type is effectively an index in an array of types.
Just before serialization pkg/compiler replaces real types
with the Ref types and prepares corresponding array of real types.
When a Target is registered in prog package, we do the opposite
operation and replace Ref's with the corresponding real types.
This brings improvements across the board:
compiler memory consumption is reduced by 15%,
test building time by 25%, descriptions size by 33%.
Before:
$ du -h sys/linux/gen
54M sys/linux/gen
$ time GOMAXPROCS=1 go test -p=1 -c ./prog
real 0m54.200s
real 0m53.883s
$ time GOMAXPROCS=1 go install -p=1 ./tools/syz-execprog
real 0m27.911s
real 0m27.767s
$ TIME="%e %P %M" GOMAXPROCS=1 time go tool compile ./sys/linux/gen
20.59 100% 3200016
20.97 100% 3445976
20.25 100% 3209684
After:
$ du -h sys/linux/gen
36M sys/linux/gen
$ time GOMAXPROCS=1 go test -p=1 -c ./prog
real 0m42.290s
real 0m43.230s
$ time GOMAXPROCS=1 go install -p=1 ./tools/syz-execprog
real 0m24.337s
real 0m24.727s
$ TIME="%e %P %M" GOMAXPROCS=1 time go tool compile ./sys/linux/gen
19.11 100% 2764952
19.66 100% 2787624
19.35 100% 2749376
Update #1580
Diffstat (limited to 'prog/target.go')
| -rw-r--r-- | prog/target.go | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/prog/target.go b/prog/target.go index 5c97b5e50..f9e10b6f4 100644 --- a/prog/target.go +++ b/prog/target.go @@ -24,6 +24,7 @@ type Target struct { Resources []*ResourceDesc Structs []*KeyedStruct Consts []ConstValue + Types []Type // MakeDataMmap creates calls that mmaps target data memory range. MakeDataMmap func() []*Call @@ -136,8 +137,9 @@ func (target *Target) initTarget() { target.ConstMap[c.Name] = c.Value } - target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.Structs) + target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.Structs, target.Types) target.Structs = nil + target.Types = nil target.SyscallMap = make(map[string]*Syscall) for i, c := range target.Syscalls { @@ -171,11 +173,12 @@ func (target *Target) sanitize(c *Call, fix bool) error { return nil } -func RestoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*KeyedStruct) { - restoreLinks(syscalls, resources, structs) +func RestoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*KeyedStruct, types []Type) { + restoreLinks(syscalls, resources, structs, types) } -func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*KeyedStruct) map[string]*ResourceDesc { +func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*KeyedStruct, + types []Type) map[string]*ResourceDesc { resourceMap := make(map[string]*ResourceDesc) for _, res := range resources { resourceMap[res.Name] = res @@ -183,10 +186,23 @@ func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*Key keyedStructs := make(map[StructKey]*StructDesc) for _, desc := range structs { keyedStructs[desc.Key] = desc.Desc + for i := range desc.Desc.Fields { + unref(&desc.Desc.Fields[i], types) + } } for _, c := range syscalls { + for i := range c.Args { + unref(&c.Args[i], types) + } + if c.Ret != nil { + unref(&c.Ret, types) + } ForeachType(c, func(t0 Type) { switch t := t0.(type) { + case *PtrType: + unref(&t.Type, types) + case *ArrayType: + unref(&t.Type, types) case *ResourceType: t.Desc = resourceMap[t.TypeName] if t.Desc == nil { @@ -208,6 +224,12 @@ func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, structs []*Key return resourceMap } +func unref(tp *Type, types []Type) { + if ref, ok := (*tp).(Ref); ok { + *tp = types[ref] + } +} + type Gen struct { r *randGen s *state |
