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  }