From a6d5f3ad1385fe724cdb2c9ee3b05c7d4ce48ef6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sun, 23 Aug 2020 11:16:10 +0200 Subject: prog: prune recursion for resourceCentric/createResource Currently we only prune recursion for createResource. But createResource can still recurse into resourceCentric, this can produce huge programs and may be very slow (esp. if we already in createResource doing failing attempts). With this change: $ CI=yes go test -run TestMutateCorpus -count=2 ./prog passes in ~3 seconds. If I comment out inGenerateResource logic, it times out after 100 seconds. So this can indeed have significant effect on generation/mutation performance. --- prog/rand.go | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'prog/rand.go') diff --git a/prog/rand.go b/prog/rand.go index 05a9c30df..cfe20fb0b 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -26,9 +26,9 @@ const ( type randGen struct { *rand.Rand - target *Target - inCreateResource bool - recDepth map[string]int + target *Target + inGenerateResource bool + recDepth map[string]int } func newRand(target *Target, rs rand.Source) *randGen { @@ -345,12 +345,6 @@ func (r *randGen) allocVMA(s *state, typ Type, dir Dir, numPages uint64) *Pointe } func (r *randGen) createResource(s *state, res *ResourceType, dir Dir) (arg Arg, calls []*Call) { - if r.inCreateResource { - return nil, nil - } - r.inCreateResource = true - defer func() { r.inCreateResource = false }() - kind := res.Desc.Name // We may have no resources, but still be in createResource due to ANYRES. if len(r.target.resourceMap) != 0 && r.oneOf(1000) { @@ -659,20 +653,28 @@ func (r *randGen) generateArgImpl(s *state, typ Type, dir Dir, ignoreSpecial boo } func (a *ResourceType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) { - if r.oneOf(3) { - arg = r.existingResource(s, a, dir) - if arg != nil { - return + if !r.inGenerateResource { + // Don't allow recursion for resourceCentric/createResource. + // That can lead to generation of huge programs and may be very slow + // (esp. if we are generating some failing attempts in createResource already). + r.inGenerateResource = true + defer func() { r.inGenerateResource = false }() + + if r.oneOf(4) { + arg, calls = r.resourceCentric(s, a, dir) + if arg != nil { + return + } } - } - if r.nOutOf(2, 3) { - arg, calls = r.resourceCentric(s, a, dir) - if arg != nil { - return + if r.oneOf(3) { + arg, calls = r.createResource(s, a, dir) + if arg != nil { + return + } } } - if r.nOutOf(4, 5) { - arg, calls = r.createResource(s, a, dir) + if r.nOutOf(9, 10) { + arg = r.existingResource(s, a, dir) if arg != nil { return } -- cgit mrf-deployment