github.com/QuangTung97/bigcache@v0.1.0/segment_test.go (about) 1 package bigcache 2 3 import ( 4 "fmt" 5 "github.com/QuangTung97/bigcache/memhash" 6 "github.com/stretchr/testify/assert" 7 "math/rand" 8 "testing" 9 "unsafe" 10 ) 11 12 func TestEntryHeaderAlign(t *testing.T) { 13 assert.Equal(t, 20, entryHeaderSize) 14 assert.Equal(t, 4, entryHeaderAlign) 15 } 16 17 func newSegment() *segment { 18 s := &segment{} 19 initSegment(s, 1024) 20 return s 21 } 22 23 func newSegmentSize(bufSize int) *segment { 24 s := &segment{} 25 initSegment(s, bufSize) 26 return s 27 } 28 29 func (s *segment) getHeader(hash uint32) *entryHeader { 30 offset := s.kv[hash] 31 var headerData [entryHeaderSize]byte 32 s.rb.readAt(headerData[:], offset) 33 return (*entryHeader)(unsafe.Pointer(&headerData[0])) 34 } 35 36 func (s *segment) getSumTotalAccessTime() uint64 { 37 totalAccess := uint64(0) 38 for _, offset := range s.kv { 39 header := s.getHeaderAtOffset(offset) 40 totalAccess += uint64(header.accessTime) 41 } 42 return totalAccess 43 } 44 45 func (s *segment) getHeaderAtOffset(offset int) *entryHeader { 46 var headerData [entryHeaderSize]byte 47 s.rb.readAt(headerData[:], offset) 48 return (*entryHeader)(unsafe.Pointer(&headerData[0])) 49 } 50 51 func monoGetNow(start uint32) func() uint32 { 52 now := start 53 return func() uint32 { 54 now++ 55 return now 56 } 57 } 58 59 func TestNextNumberAlignToHeader(t *testing.T) { 60 result := nextNumberAlignToHeader(7) 61 assert.Equal(t, uint32(8), result) 62 63 result = nextNumberAlignToHeader(12) 64 assert.Equal(t, uint32(12), result) 65 } 66 67 func TestSegmentSizeAlignToCacheLine(t *testing.T) { 68 assert.Equal(t, 64*2, int(unsafe.Sizeof(segment{}))) 69 } 70 71 func TestSegment_Simple_Set_Get(t *testing.T) { 72 s := newSegment() 73 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 74 75 data := make([]byte, 10) 76 n, ok := s.get(40, []byte{1, 2, 3}, data) 77 assert.Equal(t, true, ok) 78 assert.Equal(t, 4, n) 79 assert.Equal(t, []byte{10, 11, 12, 13}, data[:n]) 80 81 assert.Equal(t, 0, s.rb.getBegin()) 82 assert.Equal(t, entryHeaderSize+8, s.rb.getEnd()) 83 assert.Equal(t, 1024-entryHeaderSize-8, s.rb.getAvailable()) 84 85 assert.Equal(t, uint64(1), s.getAccessCount()) 86 assert.Equal(t, uint64(1), s.getHitCount()) 87 } 88 89 func TestSegment_Simple_Set_With_Not_Enough_Space(t *testing.T) { 90 s := newSegment() 91 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13, 14, 15}) 92 93 data := make([]byte, 5) 94 n, ok := s.get(40, []byte{1, 2, 3}, data) 95 assert.Equal(t, true, ok) 96 assert.Equal(t, 6, n) 97 assert.Equal(t, []byte{10, 11, 12, 13, 14}, data) 98 } 99 100 func TestSegment_Set_Get_Not_Equal_Hash(t *testing.T) { 101 s := newSegment() 102 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 103 104 n, ok := s.get(50, []byte{1, 2, 3}, nil) 105 assert.Equal(t, false, ok) 106 assert.Equal(t, 0, n) 107 108 assert.Equal(t, uint64(1), s.getAccessCount()) 109 assert.Equal(t, uint64(0), s.getHitCount()) 110 } 111 112 func TestSegment_Set_Get_Key_Not_Equal_Length(t *testing.T) { 113 s := newSegment() 114 s.put(40, []byte{1, 2, 3, 4, 5, 6, 7, 8}, []byte{10, 11, 12, 13}) 115 116 assert.Equal(t, uint64(0), s.getAccessCount()) 117 118 n, ok := s.get(40, []byte{1, 2, 3}, nil) 119 assert.Equal(t, false, ok) 120 assert.Equal(t, 0, n) 121 122 assert.Equal(t, uint64(1), s.getAccessCount()) 123 assert.Equal(t, uint64(0), s.getHitCount()) 124 } 125 126 func TestSegment_Set_Get_Not_Equal_Key(t *testing.T) { 127 s := newSegment() 128 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 129 130 n, ok := s.get(40, []byte{1, 2, 4}, nil) 131 assert.Equal(t, false, ok) 132 assert.Equal(t, 0, n) 133 134 assert.Equal(t, uint64(1), s.getAccessCount()) 135 assert.Equal(t, uint64(0), s.getHitCount()) 136 } 137 138 func TestSegment_Get_Access_Time(t *testing.T) { 139 s := newSegment() 140 s.getNow = func() uint32 { return 120 } 141 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 142 header := s.getHeader(40) 143 assert.Equal(t, &entryHeader{ 144 hash: 40, 145 accessTime: 120, 146 keyLen: 3, 147 deleted: false, 148 valLen: 4, 149 valCap: 5, 150 }, header) 151 } 152 153 func TestSegment_Get_Update_Access_Time(t *testing.T) { 154 s := newSegment() 155 s.getNow = func() uint32 { return 120 } 156 157 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 158 159 s.getNow = func() uint32 { return 140 } 160 data := make([]byte, 4) 161 s.get(40, []byte{1, 2, 3}, data) 162 163 header := s.getHeader(40) 164 assert.Equal(t, &entryHeader{ 165 hash: 40, 166 accessTime: 140, 167 keyLen: 3, 168 deleted: false, 169 valLen: 4, 170 valCap: 5, 171 }, header) 172 } 173 174 func TestSegment_Put_With_Exist_Key_Same_Length(t *testing.T) { 175 s := newSegment() 176 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 177 prevAvail := s.rb.getAvailable() 178 s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23}) 179 180 assert.Equal(t, 1, len(s.kv)) 181 assert.Equal(t, uint64(1), s.getTotal()) 182 assert.Equal(t, entryHeaderSize+8, s.rb.getEnd()) 183 assert.Equal(t, prevAvail, s.rb.getAvailable()) 184 185 data := make([]byte, 100) 186 n, ok := s.get(40, []byte{1, 2, 3}, data) 187 assert.Equal(t, true, ok) 188 assert.Equal(t, []byte{20, 21, 22, 23}, data[:n]) 189 } 190 191 func TestSegment_Put_With_Exist_Key_Same_Length_Different_Length_Still_In_Cap(t *testing.T) { 192 s := newSegment() 193 s.getNow = func() uint32 { return 100 } 194 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 195 196 prevAvail := s.rb.getAvailable() 197 198 s.getNow = func() uint32 { return 110 } 199 s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23, 24}) 200 201 assert.Equal(t, 1, len(s.kv)) 202 assert.Equal(t, uint64(1), s.getTotal()) 203 assert.Equal(t, entryHeaderSize+8, s.rb.getEnd()) 204 assert.Equal(t, prevAvail, s.rb.getAvailable()) 205 206 header := s.getHeader(40) 207 assert.Equal(t, &entryHeader{ 208 hash: 40, 209 accessTime: 110, 210 keyLen: 3, 211 valLen: 5, 212 valCap: 5, 213 }, header) 214 215 data := make([]byte, 100) 216 n, ok := s.get(40, []byte{1, 2, 3}, data) 217 assert.Equal(t, true, ok) 218 assert.Equal(t, []byte{20, 21, 22, 23, 24}, data[:n]) 219 } 220 221 func TestSegment_Put_With_Exist_Key_Not_In_Cap(t *testing.T) { 222 s := newSegment() 223 224 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13}) 225 226 prevAvail := s.rb.getAvailable() 227 s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23, 24, 25}) 228 229 assert.Equal(t, 1, len(s.kv)) 230 assert.Equal(t, uint64(1), s.getTotal()) 231 assert.Equal(t, entryHeaderSize*2+8+12, s.rb.getEnd()) 232 assert.Equal(t, prevAvail-entryHeaderSize-12, s.rb.getAvailable()) 233 234 data := make([]byte, 100) 235 n, ok := s.get(40, []byte{1, 2, 3}, data) 236 assert.Equal(t, true, ok) 237 assert.Equal(t, []byte{20, 21, 22, 23, 24, 25}, data[:n]) 238 239 header := s.getHeaderAtOffset(0) 240 assert.Equal(t, true, header.deleted) 241 } 242 243 func TestSegment_Put_Same_Hash_Diff_Key(t *testing.T) { 244 s := newSegment() 245 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12}) 246 s.put(40, []byte{5, 6, 7, 8, 9}, []byte{20, 21, 22, 23}) 247 248 header := s.getHeaderAtOffset(0) 249 assert.Equal(t, true, header.deleted) 250 251 data := make([]byte, 100) 252 n, ok := s.get(40, []byte{1, 2, 3}, data) 253 assert.Equal(t, false, ok) 254 assert.Equal(t, 0, n) 255 256 data = make([]byte, 100) 257 n, ok = s.get(40, []byte{5, 6, 7, 8, 9}, data) 258 assert.Equal(t, true, ok) 259 assert.Equal(t, []byte{20, 21, 22, 23}, data[:n]) 260 } 261 262 func TestSegment_Put_Evacuate(t *testing.T) { 263 s := newSegmentSize(entryHeaderSize*3 + 8 + 12 + 8) 264 s.getNow = monoGetNow(0) 265 266 s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12}) 267 s.put(41, []byte{5, 6, 7}, []byte{20, 21, 22, 23, 24, 25}) 268 s.put(42, []byte{8, 9, 0}, []byte{30, 31}) 269 s.put(43, []byte{100, 101, 102}, []byte{40, 41, 42}) 270 271 assert.Equal(t, 3, len(s.kv)) 272 assert.Equal(t, uint64(3), s.getTotal()) 273 assert.Equal(t, entryHeaderSize+8, s.rb.getBegin()) 274 275 data := make([]byte, 100) 276 n, ok := s.get(40, []byte{1, 2, 3}, data) 277 assert.Equal(t, false, ok) 278 assert.Equal(t, 0, n) 279 280 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 281 } 282 283 func TestSegment_Put_Evacuate_Skip_Recent_Used(t *testing.T) { 284 const entrySize = entryHeaderSize + 8 285 s := newSegmentSize(entrySize * 5) 286 s.getNow = monoGetNow(0) 287 288 s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100}) 289 s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101}) 290 s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102}) 291 s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103}) 292 s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104}) 293 294 assert.Equal(t, 0, s.rb.getAvailable()) 295 assert.Equal(t, uint64(5), s.getTotal()) 296 297 data := make([]byte, 100) 298 299 s.get(40, []byte{1, 2, 0}, data) 300 s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105}) 301 302 assert.Equal(t, uint64(5), s.getTotal()) 303 304 data = make([]byte, 100) 305 n, ok := s.get(40, []byte{1, 2, 0}, data) 306 assert.Equal(t, true, ok) 307 assert.Equal(t, []byte{101, 102, 103, 100}, data[:n]) 308 309 _, ok = s.get(41, []byte{1, 2, 1}, data) 310 assert.Equal(t, false, ok) 311 312 _, ok = s.get(42, []byte{1, 2, 2}, data) 313 assert.Equal(t, true, ok) 314 315 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 316 } 317 318 func TestSegment_Put_Evacuate_Reach_Max_Evacuation(t *testing.T) { 319 const entrySize = entryHeaderSize + 8 320 s := newSegmentSize(entrySize * 12) 321 s.getNow = monoGetNow(0) 322 323 s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100}) 324 s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101}) 325 s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102}) 326 s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103}) 327 328 s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104}) 329 s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105}) 330 s.put(46, []byte{1, 2, 6}, []byte{101, 102, 103, 106}) 331 s.put(47, []byte{1, 2, 7}, []byte{101, 102, 103, 107}) 332 333 s.put(48, []byte{1, 2, 8}, []byte{101, 102, 103, 108}) 334 s.put(49, []byte{1, 2, 9}, []byte{101, 102, 103, 109}) 335 s.put(50, []byte{1, 2, 10}, []byte{101, 102, 103, 110}) 336 s.put(51, []byte{1, 2, 11}, []byte{101, 102, 103, 111}) 337 338 data := make([]byte, 100) 339 s.get(40, []byte{1, 2, 0}, data) 340 s.get(41, []byte{1, 2, 1}, data) 341 s.get(42, []byte{1, 2, 2}, data) 342 s.get(43, []byte{1, 2, 3}, data) 343 344 s.get(44, []byte{1, 2, 4}, data) 345 s.get(45, []byte{1, 2, 5}, data) 346 347 s.put(52, []byte{1, 2, 12}, []byte{101, 102, 103, 112}) 348 349 data = make([]byte, 100) 350 n, ok := s.get(45, []byte{1, 2, 5}, data) 351 assert.Equal(t, false, ok) 352 assert.Equal(t, []byte{}, data[:n]) 353 354 data = make([]byte, 100) 355 n, ok = s.get(46, []byte{1, 2, 6}, data) 356 assert.Equal(t, true, ok) 357 assert.Equal(t, []byte{101, 102, 103, 106}, data[:n]) 358 359 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 360 } 361 362 func TestSegment_Put_Existing_Check_Total_Access_Time(t *testing.T) { 363 s := newSegment() 364 s.getNow = monoGetNow(200) 365 366 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 367 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 0}) 368 369 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 370 } 371 372 func TestSegment_Put_Same_Hash_Diff_Key_Check_Total_Access_Time(t *testing.T) { 373 s := newSegment() 374 s.getNow = monoGetNow(200) 375 376 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 377 s.put(40, []byte{1, 2, 4}, []byte{101, 102, 103, 0}) 378 379 assert.Equal(t, uint64(1), s.getTotal()) 380 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 381 } 382 383 func TestSegment_Delete_Simple(t *testing.T) { 384 s := newSegment() 385 s.getNow = monoGetNow(200) 386 387 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 388 affected := s.delete(40, []byte{1, 2, 3}) 389 assert.Equal(t, true, affected) 390 391 assert.Equal(t, uint64(0), s.getTotal()) 392 393 data := make([]byte, 100) 394 n, ok := s.get(40, []byte{1, 2, 3}, data) 395 assert.Equal(t, false, ok) 396 assert.Equal(t, 0, n) 397 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 398 } 399 400 func TestSegment_Delete_Different_Hash(t *testing.T) { 401 s := newSegment() 402 s.getNow = monoGetNow(200) 403 404 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 405 s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105}) 406 407 affected := s.delete(42, []byte{1, 2, 3}) 408 assert.Equal(t, false, affected) 409 410 assert.Equal(t, uint64(2), s.getTotal()) 411 412 data := make([]byte, 100) 413 n, ok := s.get(40, []byte{1, 2, 3}, data) 414 assert.Equal(t, true, ok) 415 assert.Equal(t, []byte{101, 102, 103, 104}, data[:n]) 416 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 417 } 418 419 func TestSegment_Delete_Same_Hash_Diff_Key(t *testing.T) { 420 s := newSegment() 421 s.getNow = monoGetNow(200) 422 423 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 424 s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105}) 425 426 affected := s.delete(40, []byte{1, 2, 5}) 427 assert.Equal(t, false, affected) 428 429 assert.Equal(t, uint64(2), s.getTotal()) 430 431 data := make([]byte, 100) 432 n, ok := s.get(40, []byte{1, 2, 3}, data) 433 assert.Equal(t, true, ok) 434 assert.Equal(t, []byte{101, 102, 103, 104}, data[:n]) 435 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 436 } 437 438 func TestSegment_Delete_Already_Deleted(t *testing.T) { 439 s := newSegment() 440 s.getNow = monoGetNow(200) 441 442 s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104}) 443 s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105}) 444 445 affected := s.delete(40, []byte{1, 2, 3}) 446 assert.Equal(t, true, affected) 447 448 assert.Equal(t, uint64(1), s.getTotal()) 449 450 affected = s.delete(40, []byte{1, 2, 3}) 451 assert.Equal(t, false, affected) 452 453 assert.Equal(t, uint64(1), s.getTotal()) 454 455 data := make([]byte, 100) 456 n, ok := s.get(40, []byte{1, 2, 3}, data) 457 assert.Equal(t, false, ok) 458 assert.Equal(t, 0, n) 459 } 460 461 func TestSegment_Put_Evacuate_After_Deleted(t *testing.T) { 462 const entrySize = entryHeaderSize + 8 463 s := newSegmentSize(entrySize * 5) 464 s.getNow = monoGetNow(0) 465 466 s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100}) 467 s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101}) 468 s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102}) 469 s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103}) 470 s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104}) 471 472 data := make([]byte, 100) 473 s.get(40, []byte{1, 2, 0}, data) 474 s.delete(40, []byte{1, 2, 0}) 475 476 assert.Equal(t, uint64(4), s.getTotal()) 477 assert.Equal(t, 4, len(s.kv)) 478 479 s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105}) 480 481 assert.Equal(t, uint64(5), s.getTotal()) 482 assert.Equal(t, 5, len(s.kv)) 483 484 data = make([]byte, 100) 485 n, ok := s.get(41, []byte{1, 2, 1}, data) 486 assert.Equal(t, true, ok) 487 assert.Equal(t, []byte{101, 102, 103, 101}, data[:n]) 488 } 489 490 func TestSegment_Put_Evacuate_Need_Reset_ConsecutiveEvacuation(t *testing.T) { 491 const entrySize = entryHeaderSize + 8 492 s := newSegmentSize(entrySize * 12) 493 s.maxConsecutiveEvacuation = 2 494 s.getNow = monoGetNow(0) 495 496 s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100}) 497 s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101}) 498 s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102}) 499 s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103}) 500 501 s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104}) 502 s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105}) 503 s.put(46, []byte{1, 2, 6}, []byte{101, 102, 103, 106}) 504 s.put(47, []byte{1, 2, 7}, []byte{101, 102, 103, 107}) 505 506 s.put(48, []byte{1, 2, 8}, []byte{101, 102, 103, 108}) 507 s.put(49, []byte{1, 2, 9}, []byte{101, 102, 103, 109}) 508 s.put(50, []byte{1, 2, 10}, []byte{101, 102, 103, 110}) 509 s.put(51, []byte{1, 2, 11}, []byte{101, 102, 103, 111}) 510 511 data := make([]byte, 100) 512 s.get(40, []byte{1, 2, 0}, data) 513 s.get(41, []byte{1, 2, 1}, data) 514 s.get(42, []byte{1, 2, 2}, data) 515 s.get(43, []byte{1, 2, 3}, data) 516 517 s.get(44, []byte{1, 2, 4}, data) 518 519 s.put(60, []byte{5, 5, 5}, []byte{10, 10, 10, 10, 10, 10}) 520 521 _, ok := s.get(40, []byte{1, 2, 0}, data) 522 assert.Equal(t, true, ok) 523 _, ok = s.get(41, []byte{1, 2, 1}, data) 524 assert.Equal(t, true, ok) 525 _, ok = s.get(42, []byte{1, 2, 2}, data) 526 assert.Equal(t, false, ok) 527 _, ok = s.get(43, []byte{1, 2, 3}, data) 528 assert.Equal(t, true, ok) 529 _, ok = s.get(44, []byte{1, 2, 4}, data) 530 assert.Equal(t, true, ok) 531 _, ok = s.get(45, []byte{1, 2, 5}, data) 532 assert.Equal(t, false, ok) 533 534 assert.Equal(t, 11, len(s.kv)) 535 assert.Equal(t, uint64(11), s.getTotal()) 536 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 537 } 538 539 func fillRandom(data []byte) { 540 _, err := rand.Read(data) 541 if err != nil { 542 panic(err) 543 } 544 } 545 546 func appendKeyValue(key []byte, val []byte) []byte { 547 data := make([]byte, len(key)+len(val)-1) 548 copy(data, key) 549 copy(data[len(key):], val[1:]) 550 return data 551 } 552 553 func TestAppendKeyValue(t *testing.T) { 554 data := appendKeyValue([]byte{1, 2, 3}, []byte{4, 5, 6, 7}) 555 assert.Equal(t, []byte{1, 2, 3, 5, 6, 7}, data) 556 } 557 558 func TestSegment_Stress_Testing(t *testing.T) { 559 s := newSegmentSize(123456) 560 s.getNow = monoGetNow(0) 561 562 type keyUsed struct { 563 hash uint64 564 key []byte 565 } 566 567 const keyCount = 10000 568 const touchCount = 5 569 570 keyUsedList := make([]keyUsed, 0, keyCount) 571 572 placeholder := make([]byte, 1000) 573 574 for i := 0; i < keyCount; i++ { 575 keyLen := 2 + rand.Intn(10) 576 key := make([]byte, keyLen) 577 fillRandom(key) 578 hash := memhash.Hash(key) & 0xfff 579 keyUsedList = append(keyUsedList, keyUsed{ 580 key: key, 581 hash: hash, 582 }) 583 } 584 585 for i := 0; i < keyCount*3; i++ { 586 valueLen := 1 + rand.Intn(50) 587 value := make([]byte, valueLen) 588 fillRandom(value) 589 590 for k := 0; k < touchCount; k++ { 591 index := rand.Intn(keyCount) 592 e := keyUsedList[index] 593 s.get(uint32(e.hash), e.key, placeholder) 594 } 595 596 index := rand.Intn(keyCount) 597 e := keyUsedList[index] 598 599 h := memhash.Hash(appendKeyValue(e.key, value)) 600 value[0] = uint8(h) 601 602 putOrDelete := rand.Intn(3) 603 if putOrDelete < 2 { 604 s.put(uint32(e.hash), e.key, value) 605 } else { 606 s.delete(uint32(e.hash), e.key) 607 } 608 } 609 610 for _, e := range keyUsedList { 611 data := make([]byte, 100) 612 n, ok := s.get(uint32(e.hash), e.key, data) 613 if ok { 614 value := data[:n] 615 h := memhash.Hash(appendKeyValue(e.key, value)) 616 assert.Equal(t, uint8(h), value[0]) 617 } 618 } 619 620 assert.Equal(t, uint64((touchCount*3+1)*keyCount), s.getAccessCount()) 621 assert.Equal(t, len(s.kv), int(s.getTotal())) 622 assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime()) 623 624 fmt.Println(s.getHitCount()) 625 fmt.Println(s.getAccessCount()) 626 fmt.Println("TOTAL:", s.getTotal()) 627 fmt.Println("LEN:", len(s.kv)) 628 } 629 630 func BenchmarkSegmentPut(b *testing.B) { 631 b.StopTimer() 632 633 key := make([]byte, 32) 634 value := make([]byte, 200) 635 data := make([]byte, 500) 636 637 num := (*uint64)(unsafe.Pointer(&key[0])) 638 639 fillRandom(key) 640 fillRandom(value) 641 642 tmp := make([]byte, len(key)) 643 copy(tmp, key) 644 645 s := newSegmentSize(2000000) 646 647 const actionCount = 10000 648 649 b.StartTimer() 650 hitCount := 0 651 for n := 0; n < b.N; n++ { 652 for i := 0; i < actionCount; i++ { 653 *num++ 654 hash := memhash.Hash(key) 655 s.put(uint32(hash), key, value) 656 } 657 658 copy(key, tmp) 659 660 for i := 0; i < actionCount; i++ { 661 *num++ 662 hash := memhash.Hash(key) 663 _, ok := s.get(uint32(hash), key, data) 664 if ok { 665 hitCount++ 666 } 667 } 668 } 669 fmt.Println(hitCount, b.N) 670 }