gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/tools/go_marshal/test/benchmark_test.go (about) 1 // Copyright 2019 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 benchmark_test 16 17 import ( 18 "bytes" 19 encbin "encoding/binary" 20 "fmt" 21 "reflect" 22 "testing" 23 24 "gvisor.dev/gvisor/pkg/binary" 25 "gvisor.dev/gvisor/pkg/hostarch" 26 "gvisor.dev/gvisor/tools/go_marshal/analysis" 27 "gvisor.dev/gvisor/tools/go_marshal/test" 28 ) 29 30 // Marshalling using the standard encoding/binary package. 31 func BenchmarkEncodingBinary(b *testing.B) { 32 var s1, s2 test.Stat 33 analysis.RandomizeValue(&s1) 34 35 size := encbin.Size(&s1) 36 37 b.ResetTimer() 38 39 for n := 0; n < b.N; n++ { 40 buf := bytes.NewBuffer(make([]byte, size)) 41 buf.Reset() 42 if err := encbin.Write(buf, hostarch.ByteOrder, &s1); err != nil { 43 b.Error("Write:", err) 44 } 45 if err := encbin.Read(buf, hostarch.ByteOrder, &s2); err != nil { 46 b.Error("Read:", err) 47 } 48 } 49 50 b.StopTimer() 51 52 // Sanity check, make sure the values were preserved. 53 if !reflect.DeepEqual(s1, s2) { 54 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 55 } 56 } 57 58 // Marshalling using the sentry's binary.Marshal. 59 func BenchmarkBinary(b *testing.B) { 60 var s1, s2 test.Stat 61 analysis.RandomizeValue(&s1) 62 63 size := binary.Size(s1) 64 65 b.ResetTimer() 66 67 for n := 0; n < b.N; n++ { 68 buf := make([]byte, 0, size) 69 buf = binary.Marshal(buf, hostarch.ByteOrder, &s1) 70 binary.Unmarshal(buf, hostarch.ByteOrder, &s2) 71 } 72 73 b.StopTimer() 74 75 // Sanity check, make sure the values were preserved. 76 if !reflect.DeepEqual(s1, s2) { 77 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 78 } 79 } 80 81 // Marshalling field-by-field with manually-written code. 82 func BenchmarkMarshalManual(b *testing.B) { 83 var s1, s2 test.Stat 84 analysis.RandomizeValue(&s1) 85 86 b.ResetTimer() 87 88 for n := 0; n < b.N; n++ { 89 buf := make([]byte, 0, s1.SizeBytes()) 90 91 // Marshal 92 buf = binary.AppendUint64(buf, hostarch.ByteOrder, s1.Dev) 93 buf = binary.AppendUint64(buf, hostarch.ByteOrder, s1.Ino) 94 buf = binary.AppendUint64(buf, hostarch.ByteOrder, s1.Nlink) 95 buf = binary.AppendUint32(buf, hostarch.ByteOrder, s1.Mode) 96 buf = binary.AppendUint32(buf, hostarch.ByteOrder, s1.UID) 97 buf = binary.AppendUint32(buf, hostarch.ByteOrder, s1.GID) 98 buf = binary.AppendUint32(buf, hostarch.ByteOrder, 0) 99 buf = binary.AppendUint64(buf, hostarch.ByteOrder, s1.Rdev) 100 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.Size)) 101 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.Blksize)) 102 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.Blocks)) 103 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.ATime.Sec)) 104 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.ATime.Nsec)) 105 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.MTime.Sec)) 106 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.MTime.Nsec)) 107 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.CTime.Sec)) 108 buf = binary.AppendUint64(buf, hostarch.ByteOrder, uint64(s1.CTime.Nsec)) 109 110 // Unmarshal 111 s2.Dev = hostarch.ByteOrder.Uint64(buf[0:8]) 112 s2.Ino = hostarch.ByteOrder.Uint64(buf[8:16]) 113 s2.Nlink = hostarch.ByteOrder.Uint64(buf[16:24]) 114 s2.Mode = hostarch.ByteOrder.Uint32(buf[24:28]) 115 s2.UID = hostarch.ByteOrder.Uint32(buf[28:32]) 116 s2.GID = hostarch.ByteOrder.Uint32(buf[32:36]) 117 // Padding: buf[36:40] 118 s2.Rdev = hostarch.ByteOrder.Uint64(buf[40:48]) 119 s2.Size = int64(hostarch.ByteOrder.Uint64(buf[48:56])) 120 s2.Blksize = int64(hostarch.ByteOrder.Uint64(buf[56:64])) 121 s2.Blocks = int64(hostarch.ByteOrder.Uint64(buf[64:72])) 122 s2.ATime.Sec = int64(hostarch.ByteOrder.Uint64(buf[72:80])) 123 s2.ATime.Nsec = int64(hostarch.ByteOrder.Uint64(buf[80:88])) 124 s2.MTime.Sec = int64(hostarch.ByteOrder.Uint64(buf[88:96])) 125 s2.MTime.Nsec = int64(hostarch.ByteOrder.Uint64(buf[96:104])) 126 s2.CTime.Sec = int64(hostarch.ByteOrder.Uint64(buf[104:112])) 127 s2.CTime.Nsec = int64(hostarch.ByteOrder.Uint64(buf[112:120])) 128 } 129 130 b.StopTimer() 131 132 // Sanity check, make sure the values were preserved. 133 if !reflect.DeepEqual(s1, s2) { 134 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 135 } 136 } 137 138 // Marshalling with the go_marshal safe API. 139 func BenchmarkGoMarshalSafe(b *testing.B) { 140 var s1, s2 test.Stat 141 analysis.RandomizeValue(&s1) 142 143 b.ResetTimer() 144 145 for n := 0; n < b.N; n++ { 146 buf := make([]byte, s1.SizeBytes()) 147 s1.MarshalBytes(buf) 148 s2.UnmarshalBytes(buf) 149 } 150 151 b.StopTimer() 152 153 // Sanity check, make sure the values were preserved. 154 if !reflect.DeepEqual(s1, s2) { 155 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 156 } 157 } 158 159 // Marshalling with the go_marshal unsafe API. 160 func BenchmarkGoMarshalUnsafe(b *testing.B) { 161 var s1, s2 test.Stat 162 analysis.RandomizeValue(&s1) 163 164 b.ResetTimer() 165 166 for n := 0; n < b.N; n++ { 167 buf := make([]byte, s1.SizeBytes()) 168 s1.MarshalUnsafe(buf) 169 s2.UnmarshalUnsafe(buf) 170 } 171 172 b.StopTimer() 173 174 // Sanity check, make sure the values were preserved. 175 if !reflect.DeepEqual(s1, s2) { 176 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 177 } 178 } 179 180 func BenchmarkBinarySlice(b *testing.B) { 181 var s1, s2 [64]test.Stat 182 analysis.RandomizeValue(&s1) 183 184 size := binary.Size(s1) 185 186 b.ResetTimer() 187 188 for n := 0; n < b.N; n++ { 189 buf := make([]byte, 0, size) 190 buf = binary.Marshal(buf, hostarch.ByteOrder, &s1) 191 binary.Unmarshal(buf, hostarch.ByteOrder, &s2) 192 } 193 194 b.StopTimer() 195 196 // Sanity check, make sure the values were preserved. 197 if !reflect.DeepEqual(s1, s2) { 198 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 199 } 200 } 201 202 func BenchmarkGoMarshalUnsafeSlice(b *testing.B) { 203 var s1, s2 [64]test.Stat 204 analysis.RandomizeValue(&s1) 205 206 b.ResetTimer() 207 208 for n := 0; n < b.N; n++ { 209 buf := make([]byte, (*test.Stat)(nil).SizeBytes()*len(s1)) 210 test.MarshalUnsafeStatSlice(s1[:], buf) 211 test.UnmarshalUnsafeStatSlice(s2[:], buf) 212 } 213 214 b.StopTimer() 215 216 // Sanity check, make sure the values were preserved. 217 if !reflect.DeepEqual(s1, s2) { 218 panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2)) 219 } 220 }