github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/state/tests/bench_test.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tests 16 17 import ( 18 "bytes" 19 "context" 20 "encoding/gob" 21 "fmt" 22 "testing" 23 24 "github.com/SagerNet/gvisor/pkg/state" 25 "github.com/SagerNet/gvisor/pkg/state/wire" 26 ) 27 28 // buildPtrObject builds a benchmark object. 29 func buildPtrObject(n int) interface{} { 30 b := new(benchStruct) 31 for i := 0; i < n; i++ { 32 b = &benchStruct{B: b} 33 } 34 return b 35 } 36 37 // buildMapObject builds a benchmark object. 38 func buildMapObject(n int) interface{} { 39 b := new(benchStruct) 40 m := make(map[int]*benchStruct) 41 for i := 0; i < n; i++ { 42 m[i] = b 43 } 44 return &m 45 } 46 47 // buildSliceObject builds a benchmark object. 48 func buildSliceObject(n int) interface{} { 49 b := new(benchStruct) 50 s := make([]*benchStruct, 0, n) 51 for i := 0; i < n; i++ { 52 s = append(s, b) 53 } 54 return &s 55 } 56 57 var allObjects = map[string]struct { 58 New func(int) interface{} 59 }{ 60 "ptr": { 61 New: buildPtrObject, 62 }, 63 "map": { 64 New: buildMapObject, 65 }, 66 "slice": { 67 New: buildSliceObject, 68 }, 69 } 70 71 func buildObjects(n int, fn func(int) interface{}) (iters int, v interface{}) { 72 // maxSize is the maximum size of an individual object below. For an N 73 // larger than this, we start to return multiple objects. 74 const maxSize = 1024 75 if n <= maxSize { 76 return 1, fn(n) 77 } 78 iters = (n + maxSize - 1) / maxSize 79 return iters, fn(maxSize) 80 } 81 82 // gobSave is a version of save using gob (no stats available). 83 func gobSave(_ context.Context, w wire.Writer, v interface{}) (_ state.Stats, err error) { 84 enc := gob.NewEncoder(w) 85 err = enc.Encode(v) 86 return 87 } 88 89 // gobLoad is a version of load using gob (no stats available). 90 func gobLoad(_ context.Context, r wire.Reader, v interface{}) (_ state.Stats, err error) { 91 dec := gob.NewDecoder(r) 92 err = dec.Decode(v) 93 return 94 } 95 96 var allAlgos = map[string]struct { 97 Save func(context.Context, wire.Writer, interface{}) (state.Stats, error) 98 Load func(context.Context, wire.Reader, interface{}) (state.Stats, error) 99 MaxPtr int 100 }{ 101 "state": { 102 Save: state.Save, 103 Load: state.Load, 104 }, 105 "gob": { 106 Save: gobSave, 107 Load: gobLoad, 108 }, 109 } 110 111 func BenchmarkEncoding(b *testing.B) { 112 for objName, objInfo := range allObjects { 113 for algoName, algoInfo := range allAlgos { 114 b.Run(fmt.Sprintf("%s/%s", objName, algoName), func(b *testing.B) { 115 b.StopTimer() 116 n, v := buildObjects(b.N, objInfo.New) 117 b.ReportAllocs() 118 b.StartTimer() 119 for i := 0; i < n; i++ { 120 if _, err := algoInfo.Save(context.Background(), discard{}, v); err != nil { 121 b.Errorf("save failed: %v", err) 122 } 123 } 124 b.StopTimer() 125 }) 126 } 127 } 128 } 129 130 func BenchmarkDecoding(b *testing.B) { 131 for objName, objInfo := range allObjects { 132 for algoName, algoInfo := range allAlgos { 133 b.Run(fmt.Sprintf("%s/%s", objName, algoName), func(b *testing.B) { 134 b.StopTimer() 135 n, v := buildObjects(b.N, objInfo.New) 136 buf := new(bytes.Buffer) 137 if _, err := algoInfo.Save(context.Background(), buf, v); err != nil { 138 b.Errorf("save failed: %v", err) 139 } 140 b.ReportAllocs() 141 b.StartTimer() 142 var r bytes.Reader 143 for i := 0; i < n; i++ { 144 r.Reset(buf.Bytes()) 145 if _, err := algoInfo.Load(context.Background(), &r, v); err != nil { 146 b.Errorf("load failed: %v", err) 147 } 148 } 149 b.StopTimer() 150 }) 151 } 152 } 153 }