1
0
mirror of https://github.com/golang/go synced 2024-11-05 18:36:10 -07:00

cmd/compile: parallelize another big chunk of rulegen

rulegen has a sanity check that ensures all the arch-specific opcodes
are handled by each of the gen files.

This is an expensive chunk of work, particularly since there are a lot
of opcodes in total, and each one of them compiles and runs a regular
expression.

Parallelize that for each architecture, which greatly speeds up 'go run
*.go' on my laptop with four real CPU cores.

	name     old time/op         new time/op         delta
	Rulegen          3.39s ± 1%          2.53s ± 2%  -25.34%  (p=0.008 n=5+5)

	name     old user-time/op    new user-time/op    delta
	Rulegen          10.6s ± 1%          11.2s ± 1%   +6.09%  (p=0.008 n=5+5)

	name     old sys-time/op     new sys-time/op     delta
	Rulegen          201ms ± 7%          218ms ±17%     ~     (p=0.548 n=5+5)

	name     old peak-RSS-bytes  new peak-RSS-bytes  delta
	Rulegen          182MB ± 3%          184MB ± 3%     ~     (p=0.690 n=5+5)

Change-Id: Iec538ed0fa7eb867eeeeaab3da1e2615ce32cbb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/195218
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Daniel Martí 2019-09-13 14:42:05 +01:00
parent 4d18a7ceb2
commit 357e8f83f8

View File

@ -392,18 +392,22 @@ func genOp() {
// Check that the arch genfile handles all the arch-specific opcodes. // Check that the arch genfile handles all the arch-specific opcodes.
// This is very much a hack, but it is better than nothing. // This is very much a hack, but it is better than nothing.
var wg sync.WaitGroup
for _, a := range archs { for _, a := range archs {
if a.genfile == "" { if a.genfile == "" {
continue continue
} }
a := a
wg.Add(1)
go func() {
src, err := ioutil.ReadFile(a.genfile) src, err := ioutil.ReadFile(a.genfile)
if err != nil { if err != nil {
log.Fatalf("can't read %s: %v", a.genfile, err) log.Fatalf("can't read %s: %v", a.genfile, err)
} }
for _, v := range a.ops { for _, v := range a.ops {
pattern := fmt.Sprintf("\\Wssa[.]Op%s%s\\W", a.name, v.name) pattern := fmt.Sprintf(`\Wssa\.Op%s%s\W`, a.name, v.name)
match, err := regexp.Match(pattern, src) match, err := regexp.Match(pattern, src)
if err != nil { if err != nil {
log.Fatalf("bad opcode regexp %s: %v", pattern, err) log.Fatalf("bad opcode regexp %s: %v", pattern, err)
@ -412,7 +416,10 @@ func genOp() {
log.Fatalf("Op%s%s has no code generation in %s", a.name, v.name, a.genfile) log.Fatalf("Op%s%s has no code generation in %s", a.name, v.name, a.genfile)
} }
} }
wg.Done()
}()
} }
wg.Wait()
} }
// Name returns the name of the architecture for use in Op* and Block* enumerations. // Name returns the name of the architecture for use in Op* and Block* enumerations.