|  | // Copyright 2013 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "math/rand" | 
|  | "runtime" | 
|  | "sync" | 
|  | ) | 
|  |  | 
|  | func mapTypes() []MapType { | 
|  | // TODO(bradfitz): bunch more map types of all different key and value types. | 
|  | // Use reflect.MapOf and a program to generate lots of types & struct types. | 
|  | // For now, just one: | 
|  | return []MapType{intMapType{}} | 
|  | } | 
|  |  | 
|  | type MapType interface { | 
|  | NewMap() Map | 
|  | } | 
|  |  | 
|  | type Map interface { | 
|  | AddItem() | 
|  | DelItem() | 
|  | Len() int | 
|  | GetItem() | 
|  | RangeAll() | 
|  | } | 
|  |  | 
|  | func stressMapType(mt MapType, done func()) { | 
|  | defer done() | 
|  | m := mt.NewMap() | 
|  | for m.Len() < 10000 { | 
|  | Println("map at ", m.Len()) | 
|  | if m.Len()%100 == 0 { | 
|  | runtime.Gosched() | 
|  | } | 
|  | m.AddItem() | 
|  | m.AddItem() | 
|  | m.DelItem() | 
|  | var wg sync.WaitGroup | 
|  | const numGets = 10 | 
|  | wg.Add(numGets) | 
|  | for i := 0; i < numGets; i++ { | 
|  | go func(i int) { | 
|  | if i&1 == 0 { | 
|  | m.GetItem() | 
|  | } else { | 
|  | m.RangeAll() | 
|  | } | 
|  | wg.Done() | 
|  | }(i) | 
|  | } | 
|  | wg.Wait() | 
|  | } | 
|  | for m.Len() > 0 { | 
|  | m.DelItem() | 
|  | } | 
|  | } | 
|  |  | 
|  | type intMapType struct{} | 
|  |  | 
|  | func (intMapType) NewMap() Map { | 
|  | return make(intMap) | 
|  | } | 
|  |  | 
|  | var deadcafe = []byte("\xDE\xAD\xCA\xFE") | 
|  |  | 
|  | type intMap map[int][]byte | 
|  |  | 
|  | func (m intMap) AddItem() { | 
|  | s0 := len(m) | 
|  | for len(m) == s0 { | 
|  | key := rand.Intn(s0 + 1) | 
|  | m[key] = make([]byte, rand.Intn(64<<10)) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (m intMap) DelItem() { | 
|  | for k := range m { | 
|  | delete(m, k) | 
|  | return | 
|  | } | 
|  | } | 
|  |  | 
|  | func (m intMap) GetItem() { | 
|  | key := rand.Intn(len(m)) | 
|  | if s, ok := m[key]; ok { | 
|  | copy(s, deadcafe) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (m intMap) Len() int { return len(m) } | 
|  |  | 
|  | func (m intMap) RangeAll() { | 
|  | for _ = range m { | 
|  | } | 
|  | for range m { | 
|  | } | 
|  | } | 
|  |  | 
|  | func stressMaps() { | 
|  | for { | 
|  | var wg sync.WaitGroup | 
|  | for _, mt := range mapTypes() { | 
|  | wg.Add(1) | 
|  | go stressMapType(mt, wg.Done) | 
|  | } | 
|  | wg.Wait() | 
|  | } | 
|  | } |