github.com/matrixorigin/matrixone@v1.2.0/pkg/common/mpool/mpool_test.go (about)

     1  // Copyright 2021 Matrix Origin
     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 mpool
    16  
    17  import (
    18  	"sync"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  func TestMPool(t *testing.T) {
    25  	m, err := NewMPool("test-mpool-small", 0, 0)
    26  	require.True(t, err == nil, "new mpool failed %v", err)
    27  
    28  	nb0 := m.CurrNB()
    29  	hw0 := m.Stats().HighWaterMark.Load()
    30  	nalloc0 := m.Stats().NumAlloc.Load()
    31  	nfree0 := m.Stats().NumFree.Load()
    32  
    33  	require.True(t, nalloc0 == 0, "bad nalloc")
    34  	require.True(t, nfree0 == 0, "bad nfree")
    35  
    36  	for i := 1; i <= 10000; i++ {
    37  		a, err := m.Alloc(i * 10)
    38  		require.True(t, err == nil, "alloc failure, %v", err)
    39  		require.True(t, len(a) == i*10, "allocation i size error")
    40  		a[0] = 0xF0
    41  		require.True(t, a[1] == 0, "allocation result not zeroed.")
    42  		a[i*10-1] = 0xBA
    43  		a, err = m.reAlloc(a, i*20)
    44  		require.True(t, err == nil, "realloc failure %v", err)
    45  		require.True(t, len(a) == i*20, "allocation i size error")
    46  		require.True(t, a[0] == 0xF0, "reallocation not copied")
    47  		require.True(t, a[i*10-1] == 0xBA, "reallocation not copied")
    48  		require.True(t, a[i*10] == 0, "reallocation not zeroed")
    49  		require.True(t, a[i*20-1] == 0, "reallocation not zeroed")
    50  		m.Free(a)
    51  	}
    52  
    53  	require.True(t, nb0 == m.CurrNB(), "leak")
    54  	// 30 -- we realloc, need alloc first, then copy.
    55  	// therefore, (10 + 20) * max(i) and 2 header size (old and new), is the high water.
    56  	require.True(t, (hw0+10000*30+2*kMemHdrSz) == m.Stats().HighWaterMark.Load(), "hw")
    57  	// >, because some alloc is absorbed by fixed pool
    58  	require.True(t, nalloc0+10000*2 > m.Stats().NumAlloc.Load(), "alloc")
    59  	require.True(t, nalloc0-nfree0 == m.Stats().NumAlloc.Load()-m.Stats().NumFree.Load(), "free")
    60  }
    61  
    62  func TestReportMemUsage(t *testing.T) {
    63  	// Just test a mid sized
    64  	m, err := NewMPool("testjson", 0, 0)
    65  	m.EnableDetailRecording()
    66  
    67  	require.True(t, err == nil, "new mpool failed %v", err)
    68  	mem, err := m.Alloc(1000000)
    69  	require.True(t, err == nil, "mpool alloc failed %v", err)
    70  
    71  	j1 := ReportMemUsage("")
    72  	j2 := ReportMemUsage("global")
    73  	j3 := ReportMemUsage("testjson")
    74  	t.Logf("mem usage: %s", j1)
    75  	t.Logf("global mem usage: %s", j2)
    76  	t.Logf("testjson mem usage: %s", j3)
    77  
    78  	m.Free(mem)
    79  	j1 = ReportMemUsage("")
    80  	j2 = ReportMemUsage("global")
    81  	j3 = ReportMemUsage("testjson")
    82  	t.Logf("mem usage: %s", j1)
    83  	t.Logf("global mem usage: %s", j2)
    84  	t.Logf("testjson mem usage: %s", j3)
    85  
    86  	DeleteMPool(m)
    87  	j1 = ReportMemUsage("")
    88  	j2 = ReportMemUsage("global")
    89  	j3 = ReportMemUsage("testjson")
    90  	t.Logf("mem usage: %s", j1)
    91  	t.Logf("global mem usage: %s", j2)
    92  	t.Logf("testjson mem usage: %s", j3)
    93  }
    94  
    95  func TestMP(t *testing.T) {
    96  	pool, err := NewMPool("default", 0, 0)
    97  	if err != nil {
    98  		panic(err)
    99  	}
   100  	var wg sync.WaitGroup
   101  	run := func() {
   102  		defer wg.Done()
   103  		for i := 0; i < 1000; i++ {
   104  			buf, err := pool.Alloc(10)
   105  			if err != nil {
   106  				panic(err)
   107  			}
   108  			pool.Free(buf)
   109  		}
   110  	}
   111  	for i := 0; i < 800; i++ {
   112  		wg.Add(1)
   113  		go run()
   114  	}
   115  	wg.Wait()
   116  
   117  }
   118  
   119  func TestMpoolReAllocate(t *testing.T) {
   120  	m := MustNewZero()
   121  	d1, err := m.Alloc(1023)
   122  	require.NoError(t, err)
   123  	require.Equal(t, int64(cap(d1)+kMemHdrSz), m.CurrNB())
   124  
   125  	d2, err := m.reAlloc(d1, cap(d1)-1)
   126  	require.NoError(t, err)
   127  	require.Equal(t, cap(d1), cap(d2))
   128  	require.Equal(t, int64(cap(d1)+kMemHdrSz), m.CurrNB())
   129  
   130  	d3, err := m.reAlloc(d2, cap(d2)+1025)
   131  	require.NoError(t, err)
   132  	require.Equal(t, int64(cap(d3)+kMemHdrSz), m.CurrNB())
   133  
   134  	if cap(d3) > 5 {
   135  		d3 = d3[:cap(d3)-4]
   136  		d3_1, err := m.Grow(d3, cap(d3)-2)
   137  		require.NoError(t, err)
   138  		require.Equal(t, cap(d3), cap(d3_1))
   139  		require.Equal(t, int64(cap(d3)+kMemHdrSz), m.CurrNB())
   140  		d3 = d3_1
   141  	}
   142  
   143  	d4, err := m.Grow(d3, cap(d3)+10)
   144  	require.NoError(t, err)
   145  	require.Equal(t, int64(cap(d4)+kMemHdrSz), m.CurrNB())
   146  
   147  	if cap(d4) > 0 {
   148  		d4 = d4[:cap(d4)-1]
   149  	}
   150  	m.Free(d4)
   151  	require.Equal(t, int64(0), m.CurrNB())
   152  }