diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-03-20 15:07:42 +0100 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-03-20 14:50:51 +0000 |
| commit | 6753db5cdc04330ec9d1a5116b890c19481d69b3 (patch) | |
| tree | 040473e4831ebe962743fe9f88fc0b3b2c218f4d /prog | |
| parent | 5b7d42ae0076f983317dceae96a942ea9d07c29c (diff) | |
prog: optimize resourceCentric()
In practice, we need to try out many different corpus programs before we
may find a matching resource. It's very inefficient to Clone() each of
them.
This change gives a +76% speed improvement in the BenchmarkMutate()
test.
Diffstat (limited to 'prog')
| -rw-r--r-- | prog/clone.go | 5 | ||||
| -rw-r--r-- | prog/rand.go | 13 |
2 files changed, 12 insertions, 6 deletions
diff --git a/prog/clone.go b/prog/clone.go index 4523be0eb..6ec28e39e 100644 --- a/prog/clone.go +++ b/prog/clone.go @@ -8,7 +8,10 @@ import ( ) func (p *Prog) Clone() *Prog { - newargs := make(map[*ResultArg]*ResultArg) + return p.cloneWithMap(make(map[*ResultArg]*ResultArg)) +} + +func (p *Prog) cloneWithMap(newargs map[*ResultArg]*ResultArg) *Prog { p1 := &Prog{ Target: p.Target, Calls: cloneCalls(p.Calls, newargs), diff --git a/prog/rand.go b/prog/rand.go index 742dbaa7c..0e3727c7f 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -943,12 +943,15 @@ func (r *randGen) resourceCentric(s *state, t *ResourceType, dir Dir) (arg Arg, var p *Prog var resource *ResultArg for _, idx := range r.Perm(len(s.corpus)) { - p = s.corpus[idx].Clone() - resources := getCompatibleResources(p, t.TypeName, r) - if len(resources) > 0 { - resource = resources[r.Intn(len(resources))] - break + corpusProg := s.corpus[idx] + resources := getCompatibleResources(corpusProg, t.TypeName, r) + if len(resources) == 0 { + continue } + argMap := make(map[*ResultArg]*ResultArg) + p = corpusProg.cloneWithMap(argMap) + resource = argMap[resources[r.Intn(len(resources))]] + break } // No compatible resource was found. |
