github.com/userpro/linearpool@v0.5.3-0.20231115092206-0ca073169b71/memorypool_test.go (about) 1 package memorypool 2 3 import ( 4 "fmt" 5 "math/rand" 6 "runtime" 7 "strconv" 8 "testing" 9 "unsafe" 10 11 "github.com/stretchr/testify/assert" 12 ) 13 14 type testNewF struct { 15 t []*testNew 16 t1 [16]int 17 } 18 19 type testNew struct { 20 a string 21 b int 22 } 23 24 func TestNew(t *testing.T) { 25 ac := NewAlloctorFromPool(0) 26 a := New[testNew](ac) 27 a.a = ac.NewString("hello") 28 a.b = 12 29 t.Logf("%s %d\n", a.a, a.b) 30 ac.Debug() 31 runtime.GC() 32 ac.Debug() 33 assert.EqualValues(t, a.a, "hello") 34 assert.EqualValues(t, a.b, 12) 35 runtime.KeepAlive(ac) 36 } 37 38 func TestNewSlice(t *testing.T) { 39 ac := NewAlloctorFromPool(0) 40 tmpInt := rand.Int31() 41 f := func(tmpstr []byte) *testNewF { 42 tf := New[testNewF](ac) 43 a := NewSlice[*testNew](ac, 1, 1) 44 45 t1 := New[testNew](ac) 46 t1.a = "anihao" // 常量字符串可以这么操作 47 t1.b = 12 48 49 t2 := New[testNew](ac) 50 t2.a = "anihao2" + string(tmpstr) 51 t2.b = 122 52 53 a = AppendMulti[*testNew](ac, a, t1, t2) 54 tf.t = a 55 return tf 56 } 57 tf := f([]byte(strconv.Itoa(int(tmpInt)))) 58 59 b := NewSlice[testNew](ac, 0, 100) 60 b = AppendMulti[testNew](ac, b, []testNew{{a: "bnihaob", b: 123}}...) 61 62 runtime.GC() 63 64 assert.EqualValues(t, "anihao", tf.t[1].a) 65 assert.EqualValues(t, 12, tf.t[1].b) 66 assert.EqualValues(t, "anihao2"+strconv.Itoa(int(tmpInt)), tf.t[2].a) 67 assert.EqualValues(t, 122, tf.t[2].b) 68 69 assert.EqualValues(t, "bnihaob", b[0].a) 70 assert.EqualValues(t, 123, b[0].b) 71 runtime.KeepAlive(ac) 72 } 73 74 func TestSliceAppend(t *testing.T) { 75 maxn := 50_000 76 ac := NewAlloctorFromPool(0) 77 a := NewSlice[testNew](ac, 0, 1) 78 for i := 0; i < maxn; i++ { 79 a = AppendMulti[testNew](ac, a, []testNew{{a: "nihao", b: 12}, {a: "nihao2", b: 21}}...) 80 } 81 t.Logf("%s %d\n", a[0].a, a[0].b) 82 t.Logf("[first] bidx: %d, blocks: %d\n", ac.bidx, len(ac.blocks)) 83 assert.EqualValues(t, len(a), maxn*2) 84 85 for i := 0; i < maxn; i++ { 86 if i%2 != 0 { 87 assert.EqualValues(t, a[i].a, "nihao2") 88 assert.EqualValues(t, a[i].b, 21) 89 } else { 90 assert.EqualValues(t, a[i].a, "nihao") 91 assert.EqualValues(t, a[i].b, 12) 92 } 93 } 94 95 ac.ReturnAlloctorToPool() 96 97 ac = NewAlloctorFromPool(0) 98 a = NewSlice[testNew](ac, 0, 1) 99 for i := 0; i < maxn; i++ { 100 a = AppendMulti[testNew](ac, a, []testNew{{a: "nihao", b: 12}, {a: "nihao2", b: 21}}...) 101 } 102 t.Logf("[second] bidx: %d, blocks: %d\n", ac.bidx, len(ac.blocks)) 103 runtime.KeepAlive(ac) 104 } 105 106 // TestSliceAppend1 交错slice append 107 func TestSliceAppend1(t *testing.T) { 108 ac := NewAlloctorFromPool(0) 109 a1 := NewSlice[int](ac, 0, 1) 110 a1 = AppendMulti[int](ac, a1, []int{1, 2}...) // 扩容 111 a2 := NewSlice[int](ac, 0, 2) 112 a2 = AppendMulti[int](ac, a2, []int{3, 4}...) // 不扩容 113 a3 := NewSlice[int](ac, 0, 1) 114 a3 = AppendMulti[int](ac, a3, []int{5, 6}...) // 扩容 115 116 assert.EqualValues(t, 1, a1[0]) 117 assert.EqualValues(t, 2, a1[1]) 118 assert.EqualValues(t, 3, a2[0]) 119 assert.EqualValues(t, 4, a2[1]) 120 assert.EqualValues(t, 5, a3[0]) 121 assert.EqualValues(t, 6, a3[1]) 122 123 runtime.KeepAlive(ac) 124 } 125 126 // TestSliceAppend2 slice 扩容机制 127 func TestSliceAppend2(t *testing.T) { 128 ac := NewAlloctorFromPool(0) 129 a1 := NewSlice[int](ac, 0, 1) 130 for i := 0; i < 10_000; i++ { 131 a1 = AppendMulti[int](ac, a1, []int{1, 2}...) // 扩容 132 // t.Log(len(a1), cap(a1)) 133 assert.EqualValues(t, roundupsize(uintptr(len(a1))), cap(a1)) 134 } 135 for i := 0; i < 10_000; i++ { 136 if i&1 == 0 { 137 assert.EqualValues(t, 1, a1[i]) 138 } else { 139 assert.EqualValues(t, 2, a1[i]) 140 } 141 } 142 143 runtime.KeepAlive(ac) 144 } 145 146 // TestSliceAppendInplace3 slice 原地扩容机制 147 func TestSliceAppendInplace3(t *testing.T) { 148 ac := NewAlloctorFromPool(0) 149 a1 := NewSlice[int](ac, 0, 1) 150 for i := 0; i < 100_000; i++ { 151 a1 = AppendInplaceMulti[int](ac, a1, []int{1, 2}...) // 扩容 152 assert.EqualValues(t, roundupsize(uintptr(len(a1))), cap(a1)) 153 } 154 for i := 0; i < 100_000; i++ { 155 if i&1 == 0 { 156 assert.EqualValues(t, 1, a1[i]) 157 } else { 158 assert.EqualValues(t, 2, a1[i]) 159 } 160 } 161 162 runtime.KeepAlive(ac) 163 } 164 165 func TestAllocPoolReuse(t *testing.T) { 166 ac := NewAlloctorFromPool(128) 167 for _, block := range ac.blocks { 168 b := (*(*[]byte)(unsafe.Pointer(block))) 169 for _, bt := range b { 170 assert.EqualValues(t, byte('0'), bt) 171 } 172 } 173 a := New[testNew](ac) 174 a.a = ac.NewString("hello") 175 a.b = 12 176 t.Logf("%s %d\n", a.a, a.b) 177 assert.EqualValues(t, a.a, "hello") 178 assert.EqualValues(t, a.b, 12) 179 ac.ReturnAlloctorToPool() 180 181 ac = NewAlloctorFromPool(128) 182 for _, block := range ac.blocks { 183 b := (*(*[]byte)(unsafe.Pointer(block))) 184 for _, bt := range b { 185 assert.EqualValues(t, byte('0'), bt) 186 } 187 } 188 a = New[testNew](ac) 189 a.a = ac.NewString("ni") 190 a.b = 1123 191 t.Logf("%s %d\n", a.a, a.b) 192 assert.EqualValues(t, a.a, "ni") 193 assert.EqualValues(t, a.b, 1123) 194 ac.ReturnAlloctorToPool() 195 196 ac = NewAlloctorFromPool(128) 197 for _, block := range ac.blocks { 198 b := (*(*[]byte)(unsafe.Pointer(block))) 199 for _, bt := range b { 200 assert.EqualValues(t, byte('0'), bt) 201 } 202 } 203 a = New[testNew](ac) 204 a.a = ac.NewString("ni") 205 a.b = 1123 206 t.Logf("%s %d\n", a.a, a.b) 207 assert.EqualValues(t, a.a, "ni") 208 assert.EqualValues(t, a.b, 1123) 209 210 runtime.KeepAlive(ac) 211 } 212 213 func TestPoolAlloc(t *testing.T) { 214 maxn := 5_000 215 ac := NewAlloctorFromPool(0) 216 for i := 0; i < maxn; i++ { 217 a := New[testNew](ac) 218 assert.EqualValues(t, "", a.a) 219 assert.EqualValues(t, 0, a.b) 220 } 221 t.Logf("[first] bidx: %d, blocks: %d\n", ac.bidx, len(ac.blocks)) 222 223 ac.ReturnAlloctorToPool() 224 ac = NewAlloctorFromPool(0) 225 for i := 0; i < maxn; i++ { 226 a := New[testNew](ac) 227 assert.EqualValues(t, "", a.a) 228 assert.EqualValues(t, 0, a.b) 229 } 230 t.Logf("[second] bidx: %d, blocks: %d\n", ac.bidx, len(ac.blocks)) 231 232 ac.ReturnAlloctorToPool() 233 ac = NewAlloctorFromPool(0) 234 for i := 0; i < maxn; i++ { 235 a := New[testNew](ac) 236 assert.EqualValues(t, "", a.a) 237 assert.EqualValues(t, 0, a.b) 238 } 239 t.Logf("[third] bidx: %d, blocks: %d\n", ac.bidx, len(ac.blocks)) 240 241 runtime.KeepAlive(ac) 242 } 243 244 func TestAllocPoolMerge(t *testing.T) { 245 ac := NewAlloctorFromPool(0) 246 a := New[testNew](ac) 247 a.a = ac.NewString("hello") 248 a.b = 12 249 assert.EqualValues(t, a.a, "hello") 250 assert.EqualValues(t, a.b, 12) 251 252 // 新内存池1 253 ac1 := NewAlloctorFromPool(ac.BlockSize()) 254 a1 := New[testNew](ac) 255 a1.a = ac1.NewString("ni1") 256 a1.b = 1123 257 ac.Merge(ac1) 258 runtime.KeepAlive(ac1) 259 assert.EqualValues(t, a1.a, "ni1") 260 assert.EqualValues(t, a1.b, 1123) 261 262 // 新内存池2 263 ac2 := NewAlloctorFromPool(ac.BlockSize()) 264 a2 := New[testNew](ac) 265 a2.a = ac2.NewString("ni2") 266 a2.b = 1123 267 ac.Merge(ac2) 268 runtime.KeepAlive(ac2) 269 assert.EqualValues(t, a2.a, "ni2") 270 assert.EqualValues(t, a2.b, 1123) 271 272 // 合并后内存信息 273 assert.EqualValues(t, len(ac.blocks), 3) 274 assert.EqualValues(t, ac.bidx, 2) 275 276 a = New[testNew](ac) 277 a.a = ac.NewString("hello3") 278 a.b = 12 279 assert.EqualValues(t, a.a, "hello3") 280 assert.EqualValues(t, a.b, 12) 281 282 // 再次check内存信息 283 assert.EqualValues(t, len(ac.blocks), 3) 284 assert.EqualValues(t, ac.bidx, 2) 285 286 runtime.KeepAlive(ac) 287 } 288 289 type allocKeepTest1 struct { 290 ac *Allocator 291 b string 292 } 293 294 func TestKeepAlivePool(t *testing.T) { 295 ac := NewAlloctorFromPool(0) 296 a := New[allocKeepTest1](ac) 297 a.ac = NewAlloctorFromPool(0) 298 a.b = "123" 299 300 ac.KeepAlive(a.ac) // ! 301 runtime.GC() 302 303 e := []byte(fmt.Sprintf("nihaocai %d", 1)) 304 c := NewSlice[*allocKeepTest1](a.ac, 0, 8) 305 for i := 0; i < 1000000; i++ { 306 b := New[allocKeepTest1](a.ac) 307 b.b = a.ac.NewString(string(e)) // e 需要使用 NewString 来保留 308 c = Append[*allocKeepTest1](a.ac, c, b) 309 } 310 runtime.GC() 311 312 for i := 0; i < 1000000; i++ { 313 assert.EqualValues(t, c[i].b, "nihaocai 1") 314 } 315 316 runtime.KeepAlive(ac) 317 } 318 319 func TestNewString(t *testing.T) { 320 ac := NewAlloctorFromPool(0) 321 a := ac.NewString("") 322 b := ac.NewString("b") 323 324 runtime.GC() 325 326 assert.EqualValues(t, "", a) 327 assert.EqualValues(t, "b", b) 328 ac.KeepAlive(ac) 329 } 330 331 func TestSubAlloctor(t *testing.T) { 332 ac := NewAlloctorFromPool(0) 333 a := ac.NewString("123") 334 ac1 := NewAlloctorFromPool(0) 335 b := ac1.NewString("123") 336 ac.AddSubAlloctor(ac1) 337 338 runtime.GC() 339 340 assert.EqualValues(t, "123", a) 341 assert.EqualValues(t, "123", b) 342 343 ac.ReturnAlloctorToPool() 344 345 ac.KeepAlive(ac) 346 ac.KeepAlive(ac1) 347 }