github.com/matrixorigin/matrixone@v1.2.0/pkg/common/reuse/pool_test.go (about) 1 // Copyright 2023 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 reuse 16 17 import ( 18 "reflect" 19 "runtime/debug" 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 var ( 26 providers = map[string]SPI{ 27 "sync-pool": SyncBased, 28 "mpool": MpoolBased, 29 } 30 ) 31 32 func TestGetAndFree(t *testing.T) { 33 for name, spi := range providers { 34 t.Run(name, func(t *testing.T) { 35 for key := range pools { 36 delete(pools, key) 37 } 38 use(spi) 39 CreatePool[person]( 40 func() *person { return &person{} }, 41 func(p *person) { 42 names := p.names[:0] 43 *p = person{} 44 p.names = names 45 }, 46 DefaultOptions[person](), 47 ) 48 49 p := Alloc[person](nil) 50 assert.Empty(t, p.names) 51 assert.Equal(t, 0, p.age) 52 p.names = append(p.names, "hello") 53 p.age = 10 54 Free(p, nil) 55 56 p2 := Alloc[person](nil) 57 assert.Empty(t, p2.names) 58 assert.Equal(t, 0, p2.age) 59 Free(p2, nil) 60 }) 61 } 62 } 63 64 func TestCheckDoubleFree(t *testing.T) { 65 RunReuseTests(func() { 66 for name, spi := range providers { 67 t.Run(name, func(t *testing.T) { 68 for key := range pools { 69 delete(pools, key) 70 } 71 use(spi) 72 CreatePool[person]( 73 func() *person { return &person{} }, 74 func(p *person) { 75 names := p.names[:0] 76 *p = person{} 77 p.names = names 78 }, 79 DefaultOptions[person]().WithEnableChecker(), 80 ) 81 82 p := Alloc[person](nil) 83 assert.Empty(t, p.names) 84 assert.Equal(t, 0, p.age) 85 p.names = append(p.names, "hello") 86 p.age = 10 87 Free(p, nil) 88 89 defer func() { 90 assert.NotNil(t, recover()) 91 }() 92 Free(p, nil) 93 }) 94 } 95 }) 96 } 97 98 func TestCheckLeakFree(t *testing.T) { 99 RunReuseTests(func() { 100 for name, spi := range providers { 101 // mpool not support leak free check 102 if spi == MpoolBased { 103 continue 104 } 105 106 t.Run(name, func(t *testing.T) { 107 for key := range pools { 108 delete(pools, key) 109 } 110 use(spi) 111 CreatePool[person]( 112 func() *person { return &person{} }, 113 func(p *person) { 114 names := p.names[:0] 115 *p = person{} 116 p.names = names 117 }, 118 DefaultOptions[person](). 119 WithEnableChecker(). 120 withGCRecover(func() { 121 assert.NotNil(t, recover()) 122 }), 123 ) 124 125 p := Alloc[person](nil) 126 assert.Empty(t, p.names) 127 assert.Equal(t, 0, p.age) 128 p = nil 129 debug.FreeOSMemory() 130 }) 131 } 132 }) 133 } 134 135 func BenchmarkGet(b *testing.B) { 136 fn := func(spi SPI, b *testing.B) { 137 for key := range pools { 138 delete(pools, key) 139 } 140 use(SyncBased) 141 CreatePool[person]( 142 func() *person { return &person{} }, 143 func(p *person) { 144 names := p.names[:0] 145 *p = person{} 146 p.names = names 147 }, 148 DefaultOptions[person](), 149 ) 150 b.ResetTimer() 151 152 sum := uint64(0) 153 for i := 0; i < b.N; i++ { 154 p := Alloc[person](nil) 155 Free(p, nil) 156 sum++ 157 } 158 _ = sum 159 } 160 161 b.Run("sync-pool", func(b *testing.B) { 162 fn(SyncBased, b) 163 }) 164 b.Run("mpool", func(b *testing.B) { 165 fn(MpoolBased, b) 166 }) 167 } 168 169 func BenchmarkGetParallel(b *testing.B) { 170 fn := func(spi SPI, b *testing.B) { 171 for key := range pools { 172 delete(pools, key) 173 } 174 use(SyncBased) 175 CreatePool[person]( 176 func() *person { return &person{} }, 177 func(p *person) { 178 names := p.names[:0] 179 *p = person{} 180 p.names = names 181 }, 182 DefaultOptions[person](), 183 ) 184 b.ResetTimer() 185 186 b.RunParallel(func(pb *testing.PB) { 187 sum := uint64(0) 188 for { 189 if pb.Next() { 190 p := Alloc[person](nil) 191 Free(p, nil) 192 sum++ 193 } else { 194 break 195 } 196 } 197 _ = sum 198 }) 199 } 200 201 b.Run("sync-pool", func(b *testing.B) { 202 fn(SyncBased, b) 203 }) 204 b.Run("mpool", func(b *testing.B) { 205 fn(MpoolBased, b) 206 }) 207 } 208 209 type person struct { 210 names []string 211 age int 212 } 213 214 func (p person) TypeName() string { 215 return "person" 216 } 217 218 func TestTypeOf(t *testing.T) { 219 rt := reflect.TypeOf((*person)(nil)) 220 want := reflect.ValueOf(rt).Pointer() 221 got := uintptr(typeOf[person]()) 222 assert.Equal(t, want, got) 223 }