1// Copyright 2013-2020 Aerospike, Inc. 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 15package aerospike 16 17import ( 18 "bytes" 19 "encoding/binary" 20 "math" 21 "math/rand" 22 "runtime" 23 "strings" 24 "testing" 25 // "time" 26 27 _ "net/http/pprof" 28) 29 30var buf *benchBuffer 31 32func init() { 33 buf = &benchBuffer{dataBuffer: make([]byte, 1024*1024), dataOffset: 0} 34} 35 36func Benchmark_Pack_binary_Write(b *testing.B) { 37 buf := new(bytes.Buffer) 38 for i := 0; i < b.N; i++ { 39 buf.Reset() 40 binary.Write(buf, binary.BigEndian, int64(0)) 41 } 42} 43 44func Benchmark_Pack_binary_PutUint64(b *testing.B) { 45 buf := make([]byte, 8) 46 for i := 0; i < b.N; i++ { 47 binary.BigEndian.PutUint64(buf, 0) 48 } 49} 50 51func doPack(val interface{}, b *testing.B) { 52 var err error 53 v := NewValue(val) 54 runtime.GC() 55 b.ResetTimer() 56 for i := 0; i < b.N; i++ { 57 buf.dataOffset = 0 58 _, err = v.pack(buf) 59 if err != nil { 60 panic(err) 61 } 62 } 63} 64 65func Benchmark_Pack_________Int64(b *testing.B) { 66 val := rand.Int63() 67 doPack(val, b) 68} 69 70func Benchmark_Pack_________Int32(b *testing.B) { 71 val := rand.Int31() 72 doPack(val, b) 73} 74 75func Benchmark_Pack_String______1(b *testing.B) { 76 val := strings.Repeat("s", 1) 77 doPack(val, b) 78} 79 80func Benchmark_Pack_String_____10(b *testing.B) { 81 val := strings.Repeat("s", 10) 82 doPack(val, b) 83} 84 85func Benchmark_Pack_String____100(b *testing.B) { 86 val := strings.Repeat("s", 100) 87 doPack(val, b) 88} 89 90func Benchmark_Pack_String___1000(b *testing.B) { 91 val := strings.Repeat("s", 1000) 92 doPack(val, b) 93} 94 95func Benchmark_Pack_String__10000(b *testing.B) { 96 val := strings.Repeat("s", 10000) 97 doPack(val, b) 98} 99 100func Benchmark_Pack_String_100000(b *testing.B) { 101 val := strings.Repeat("s", 100000) 102 doPack(val, b) 103} 104 105func Benchmark_Pack_Complex_IfcArray_Direct(b *testing.B) { 106 val := []interface{}{1, 1, 1, "a simple string", nil, rand.Int63(), []byte{12, 198, 211}} 107 doPack(val, b) 108} 109 110var _ ListIter = myList([]string{}) 111 112// supports old generic slices 113type myList []string 114 115func (cs myList) PackList(buf BufferEx) (int, error) { 116 size := 0 117 for _, elem := range cs { 118 n, err := packString(buf, elem) 119 size += n 120 if err != nil { 121 return size, err 122 } 123 } 124 return size, nil 125} 126 127func (m myList) Len() int { 128 return len(m) 129} 130 131func Benchmark_Pack_Complex_Array_ListIter(b *testing.B) { 132 val := myList([]string{strings.Repeat("s", 1), strings.Repeat("s", 2), strings.Repeat("s", 3), strings.Repeat("s", 4), strings.Repeat("s", 5), strings.Repeat("s", 6), strings.Repeat("s", 7), strings.Repeat("s", 8), strings.Repeat("s", 9), strings.Repeat("s", 10)}) 133 doPack(val, b) 134} 135 136func Benchmark_Pack_Complex_ValueArray(b *testing.B) { 137 val := []Value{NewValue(1), NewValue(strings.Repeat("s", 100000)), NewValue(1.75), NewValue(nil)} 138 doPack(val, b) 139} 140 141func Benchmark_Pack_Complex_Map(b *testing.B) { 142 val := map[interface{}]interface{}{ 143 rand.Int63(): rand.Int63(), 144 nil: 1, 145 "s": 491871, 146 15892987: strings.Repeat("s", 100), 147 "s2": []interface{}{"a simple string", nil, rand.Int63(), []byte{12, 198, 211}}, 148 } 149 doPack(val, b) 150} 151 152func Benchmark_Pack_Complex_JsonMap(b *testing.B) { 153 val := map[string]interface{}{ 154 "rand.Int63()": rand.Int63(), 155 "nil": 1, 156 "s": 491871, 157 "15892987": strings.Repeat("s", 100), 158 "s2": []interface{}{"a simple string", nil, rand.Int63(), []byte{12, 198, 211}}, 159 } 160 doPack(val, b) 161} 162 163//////////////////////////////////////////////////////////////////////////////////////// 164type benchBuffer struct { 165 dataBuffer []byte 166 dataOffset int 167} 168 169// Int64ToBytes converts an int64 into slice of Bytes. 170func (bb *benchBuffer) WriteInt64(num int64) (int, error) { 171 return bb.WriteUint64(uint64(num)) 172} 173 174// Uint64ToBytes converts an uint64 into slice of Bytes. 175func (bb *benchBuffer) WriteUint64(num uint64) (int, error) { 176 binary.BigEndian.PutUint64(bb.dataBuffer[bb.dataOffset:bb.dataOffset+8], num) 177 bb.dataOffset += 8 178 return 8, nil 179} 180 181// Int32ToBytes converts an int32 to a byte slice of size 4 182func (bb *benchBuffer) WriteInt32(num int32) (int, error) { 183 return bb.WriteUint32(uint32(num)) 184} 185 186// Uint32ToBytes converts an uint32 to a byte slice of size 4 187func (bb *benchBuffer) WriteUint32(num uint32) (int, error) { 188 binary.BigEndian.PutUint32(bb.dataBuffer[bb.dataOffset:bb.dataOffset+4], num) 189 bb.dataOffset += 4 190 return 4, nil 191} 192 193// Int16ToBytes converts an int16 to slice of bytes 194func (bb *benchBuffer) WriteInt16(num int16) (int, error) { 195 return bb.WriteUint16(uint16(num)) 196} 197 198// Int16ToBytes converts an int16 to slice of bytes 199func (bb *benchBuffer) WriteUint16(num uint16) (int, error) { 200 binary.BigEndian.PutUint16(bb.dataBuffer[bb.dataOffset:bb.dataOffset+2], num) 201 bb.dataOffset += 2 202 return 2, nil 203} 204 205func (bb *benchBuffer) WriteFloat32(float float32) (int, error) { 206 bits := math.Float32bits(float) 207 binary.BigEndian.PutUint32(bb.dataBuffer[bb.dataOffset:bb.dataOffset+4], bits) 208 bb.dataOffset += 4 209 return 4, nil 210} 211 212func (bb *benchBuffer) WriteFloat64(float float64) (int, error) { 213 bits := math.Float64bits(float) 214 binary.BigEndian.PutUint64(bb.dataBuffer[bb.dataOffset:bb.dataOffset+8], bits) 215 bb.dataOffset += 8 216 return 8, nil 217} 218 219func (bb *benchBuffer) WriteByte(b byte) error { 220 bb.dataBuffer[bb.dataOffset] = b 221 bb.dataOffset++ 222 return nil 223} 224 225func (bb *benchBuffer) WriteString(s string) (int, error) { 226 copy(bb.dataBuffer[bb.dataOffset:bb.dataOffset+len(s)], s) 227 bb.dataOffset += len(s) 228 return len(s), nil 229} 230 231func (bb *benchBuffer) Write(b []byte) (int, error) { 232 copy(bb.dataBuffer[bb.dataOffset:bb.dataOffset+len(b)], b) 233 bb.dataOffset += len(b) 234 return len(b), nil 235} 236