github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/fixed/pool_test.go (about)

     1  package fixed
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io/ioutil"
     6  	"os"
     7  	"sync"
     8  	"syscall"
     9  	"testing"
    10  
    11  	"github.com/dshulyak/uring"
    12  	"github.com/dshulyak/uring/loop"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestWrite(t *testing.T) {
    17  	l, err := loop.Setup(1024, nil, nil)
    18  	require.NoError(t, err)
    19  	t.Cleanup(func() { l.Close() })
    20  
    21  	f, err := ioutil.TempFile("", "test")
    22  	require.NoError(t, err)
    23  	defer os.Remove(f.Name())
    24  
    25  	n := 100
    26  	size := 10
    27  	pool, err := New(l, size, n)
    28  	require.NoError(t, err)
    29  
    30  	run := func() {
    31  		for i := 0; i < n; i++ {
    32  			buf := pool.Get()
    33  			defer pool.Put(buf)
    34  			cqe, err := l.Syscall(func(sqe *uring.SQEntry) {
    35  				uring.WriteFixed(sqe, f.Fd(), buf.Base(), buf.Len(), 0, 0, buf.Index())
    36  			})
    37  			require.NoError(t, err)
    38  			require.Equal(t, int32(10), cqe.Result(), syscall.Errno(-cqe.Result()))
    39  		}
    40  	}
    41  	// run it couple of times to test that buffers are reused correctly
    42  	for i := 0; i < 3; i++ {
    43  		run()
    44  	}
    45  }
    46  
    47  func TestConcurrentWrites(t *testing.T) {
    48  	l, err := loop.Setup(1024, nil, nil)
    49  	require.NoError(t, err)
    50  	t.Cleanup(func() { l.Close() })
    51  
    52  	f, err := ioutil.TempFile("", "test-concurrent-writes-")
    53  	require.NoError(t, err)
    54  	defer os.Remove(f.Name())
    55  
    56  	var wg sync.WaitGroup
    57  	var n int64 = 10000
    58  
    59  	pool, err := New(l, 8, int(n))
    60  	require.NoError(t, err)
    61  	for i := int64(0); i < n; i++ {
    62  		wg.Add(1)
    63  		go func(i uint64) {
    64  			buf := pool.Get()
    65  			defer pool.Put(buf)
    66  			binary.BigEndian.PutUint64(buf.Bytes(), i)
    67  			_, _ = l.Syscall(func(sqe *uring.SQEntry) {
    68  				uring.WriteFixed(sqe, f.Fd(), buf.Base(), buf.Len(), i*8, 0, buf.Index())
    69  			})
    70  			wg.Done()
    71  		}(uint64(i))
    72  	}
    73  	wg.Wait()
    74  
    75  	buf2 := make([]byte, 8)
    76  	for i := int64(0); i < n; i++ {
    77  		_, err := f.ReadAt(buf2, i*8)
    78  		require.NoError(t, err)
    79  		rst := binary.BigEndian.Uint64(buf2[:])
    80  		require.Equal(t, i, int64(rst))
    81  	}
    82  }
    83  
    84  func BenchmarkPool(b *testing.B) {
    85  	l, err := loop.Setup(1024, nil, nil)
    86  	require.NoError(b, err)
    87  	b.Cleanup(func() { l.Close() })
    88  
    89  	pool, err := New(l, 8, 50000)
    90  	require.NoError(b, err)
    91  
    92  	b.ResetTimer()
    93  	b.RunParallel(func(pb *testing.PB) {
    94  		for pb.Next() {
    95  			buf := pool.Get()
    96  			buf.B[0] = 10
    97  			pool.Put(buf)
    98  		}
    99  	})
   100  }
   101  
   102  func BenchmarkSyncPool(b *testing.B) {
   103  	pool := sync.Pool{
   104  		New: func() interface{} {
   105  			return make([]byte, 8)
   106  		},
   107  	}
   108  	b.RunParallel(func(pb *testing.PB) {
   109  		for pb.Next() {
   110  			buf := pool.Get().([]byte)
   111  			buf[0] = 10
   112  			pool.Put(buf)
   113  		}
   114  	})
   115  }