Changeset 46202 in vbox for trunk/src/VBox/Runtime/common/string/strcache.cpp
- Timestamp:
- May 21, 2013 11:02:26 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/string/strcache.cpp
r46201 r46202 66 66 * Using a 1KB as a reasonable limit here. 67 67 */ 68 #define RTSTRCACHE_HEAP_THRESHOLD_BIT 10 68 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 69 # define RTSTRCACHE_HEAP_THRESHOLD_BIT 10 70 #else 71 # define RTSTRCACHE_HEAP_THRESHOLD_BIT 9 72 #endif 69 73 /** The RTSTRCACHE_HEAP_THRESHOLD_BIT as a byte limit. */ 70 74 #define RTSTRCACHE_HEAP_THRESHOLD RT_BIT_32(RTSTRCACHE_HEAP_THRESHOLD_BIT) 71 75 76 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 72 77 /** 73 78 * The RTSTRCACHEENTRY size threshold at which we start using the merge free 74 79 * list for allocations, expressed as a power of two. 75 80 */ 76 #define RTSTRCACHE_MERGED_THRESHOLD_BIT 6 77 81 # define RTSTRCACHE_MERGED_THRESHOLD_BIT 6 78 82 79 83 /** The number of bytes (power of two) that the merged allocation lists should 80 84 * be grown by. Must be much greater than RTSTRCACHE_MERGED_THRESHOLD. */ 81 85 #define RTSTRCACHE_MERGED_GROW_SIZE _32K 86 #endif 87 82 88 /** The number of bytes (power of two) that the fixed allocation lists should 83 89 * be grown by. */ 84 90 #define RTSTRCACHE_FIXED_GROW_SIZE _32K 91 92 /** The number of fixed sized lists. */ 93 #define RTSTRCACHE_NUM_OF_FIXED_SIZES 10 94 85 95 86 96 /** Validates a string cache handle, translating RTSTRCACHE_DEFAULT when found, … … 173 183 typedef RTSTRCACHEFREE *PRTSTRCACHEFREE; 174 184 185 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 175 186 176 187 /** … … 202 213 * header. Must be something that's invalid UTF-8 for both little and big 203 214 * endian system. */ 204 # define RTSTRCACHEFREEMERGE_MAINUINT32_C(0xfffffff1)215 # define RTSTRCACHEFREEMERGE_MAIN UINT32_C(0xfffffff1) 205 216 /** RTSTRCACHEFREEMERGE::uMarker value indicating that it's part of a larger 206 217 * chunk of free memory. Must be something that's invalid UTF-8 for both little 207 218 * and big endian system. */ 208 #define RTSTRCACHEFREEMERGE_PART UINT32_C(0xfffffff2) 209 219 # define RTSTRCACHEFREEMERGE_PART UINT32_C(0xfffffff2) 220 221 #endif /* RTSTRCACHE_WITH_MERGED_ALLOCATOR */ 210 222 211 223 /** … … 242 254 /** Pointer to the hash table. */ 243 255 PRTSTRCACHEENTRY *papHashTab; 244 /** Free list for allocations of size: 64+, 16, and 32. */ 245 PRTSTRCACHEFREE apFreeLists[2]; 256 /** Free list for allocations of the sizes defined by g_acbFixedLists. */ 257 PRTSTRCACHEFREE apFreeLists[RTSTRCACHE_NUM_OF_FIXED_SIZES]; 258 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 246 259 /** Free lists based on */ 247 260 RTLISTANCHOR aMergedFreeLists[RTSTRCACHE_HEAP_THRESHOLD_BIT - RTSTRCACHE_MERGED_THRESHOLD_BIT + 1]; 261 #endif 248 262 /** List of allocated memory chunks. */ 249 263 PRTSTRCACHECHUNK pChunkList; … … 261 275 * Global Variables * 262 276 *******************************************************************************/ 277 /** The entry sizes of the fixed lists (RTSTRCACHEINT::apFreeLists). */ 278 static const uint32_t g_acbFixedLists[RTSTRCACHE_NUM_OF_FIXED_SIZES] = 279 { 280 16, 32, 64, 128, 192, 256, 320, 384, 448, 512 281 }; 282 263 283 /** Init once for the default string cache. */ 264 284 static RTONCE g_rtStrCacheOnce = RTONCE_INITIALIZER; … … 289 309 { 290 310 RTListInit(&pThis->BigEntryList); 311 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 291 312 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aMergedFreeLists); i++) 292 313 RTListInit(&pThis->aMergedFreeLists[i]); 314 #endif 293 315 pThis->cRefs = 1; 294 316 pThis->u32Magic = RTSTRCACHE_MAGIC; … … 348 370 349 371 372 373 /** 374 * Selects the fixed free list index for a given minimum entry size. 375 * 376 * @returns Free list index. 377 * @param cbMin Minimum entry size. 378 */ 379 DECLINLINE(uint32_t) rtStrCacheSelectFixedList(uint32_t cbMin) 380 { 381 Assert(cbMin <= g_acbFixedLists[RT_ELEMENTS(g_acbFixedLists) - 1]); 382 unsigned i = 0; 383 while (cbMin > g_acbFixedLists[i]) 384 i++; 385 return i; 386 } 387 388 350 389 #ifdef RT_STRICT 351 390 # define RTSTRCACHE_CHECK(a_pThis) do { rtStrCacheCheck(pThis); } while (0) … … 355 394 static void rtStrCacheCheck(PRTSTRCACHEINT pThis) 356 395 { 396 # ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 357 397 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aMergedFreeLists); i++) 358 398 { … … 365 405 } 366 406 } 407 # endif 367 408 } 368 409 #else 369 410 # define RTSTRCACHE_CHECK(a_pThis) do { } while (0) 370 411 #endif 371 372 373 /**374 * Link/Relink into the free right list.375 *376 * @param pThis The string cache instance.377 * @param pFree The free string entry.378 */379 static void rtStrCacheRelinkMerged(PRTSTRCACHEINT pThis, PRTSTRCACHEFREEMERGE pFree)380 {381 Assert(pFree->uMarker == RTSTRCACHEFREEMERGE_MAIN);382 Assert(pFree->cbFree > 0);383 Assert(RT_ALIGN_32(pFree->cbFree, sizeof(*pFree)) == pFree->cbFree);384 385 if (!RTListIsEmpty(&pFree->ListEntry))386 RTListNodeRemove(&pFree->ListEntry);387 388 uint32_t iList = (ASMBitLastSetU32(pFree->cbFree) - 1) - RTSTRCACHE_MERGED_THRESHOLD_BIT;389 if (iList >= RT_ELEMENTS(pThis->aMergedFreeLists))390 iList = RT_ELEMENTS(pThis->aMergedFreeLists) - 1;391 392 RTListPrepend(&pThis->aMergedFreeLists[iList], &pFree->ListEntry);393 }394 412 395 413 … … 464 482 } 465 483 466 467 /** 468 * Allocate a cache entry from the heap. 469 * 470 * @returns Pointer to the cache entry on success, NULL on allocation error.484 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 485 486 /** 487 * Link/Relink into the free right list. 488 * 471 489 * @param pThis The string cache instance. 472 * @param uHash The full hash of the string. 473 * @param pchString The string. 474 * @param cchString The string length. 475 */ 476 static PRTSTRCACHEENTRY rtStrCacheAllocHeapEntry(PRTSTRCACHEINT pThis, uint32_t uHash, 477 const char *pchString, uint32_t cchString) 478 { 479 /* 480 * Allocate a heap block for storing the string. We do some size aligning 481 * here to encourage the heap to give us optimal alignment. 482 */ 483 size_t cbEntry = RT_UOFFSETOF(RTSTRCACHEBIGENTRY, Core.szString[cchString + 1]); 484 PRTSTRCACHEBIGENTRY pBigEntry = (PRTSTRCACHEBIGENTRY)RTMemAlloc(RT_ALIGN_Z(cbEntry, 64)); 485 if (!pBigEntry) 486 return NULL; 487 488 /* 489 * Initialize the block. 490 */ 491 RTListAppend(&pThis->BigEntryList, &pBigEntry->ListEntry); 492 pBigEntry->cchString = cchString; 493 pBigEntry->uHash = uHash; 494 pBigEntry->Core.cRefs = 1; 495 pBigEntry->Core.uHash = (uint16_t)uHash; 496 pBigEntry->Core.cchString = RTSTRCACHEENTRY_BIG_LEN; 497 memcpy(pBigEntry->Core.szString, pchString, cchString); 498 pBigEntry->Core.szString[cchString] = '\0'; 499 500 return &pBigEntry->Core; 490 * @param pFree The free string entry. 491 */ 492 static void rtStrCacheRelinkMerged(PRTSTRCACHEINT pThis, PRTSTRCACHEFREEMERGE pFree) 493 { 494 Assert(pFree->uMarker == RTSTRCACHEFREEMERGE_MAIN); 495 Assert(pFree->cbFree > 0); 496 Assert(RT_ALIGN_32(pFree->cbFree, sizeof(*pFree)) == pFree->cbFree); 497 498 if (!RTListIsEmpty(&pFree->ListEntry)) 499 RTListNodeRemove(&pFree->ListEntry); 500 501 uint32_t iList = (ASMBitLastSetU32(pFree->cbFree) - 1) - RTSTRCACHE_MERGED_THRESHOLD_BIT; 502 if (iList >= RT_ELEMENTS(pThis->aMergedFreeLists)) 503 iList = RT_ELEMENTS(pThis->aMergedFreeLists) - 1; 504 505 RTListPrepend(&pThis->aMergedFreeLists[iList], &pFree->ListEntry); 501 506 } 502 507 … … 615 620 } 616 621 622 #endif /* RTSTRCACHE_WITH_MERGED_ALLOCATOR */ 623 624 /** 625 * Allocate a cache entry from the heap. 626 * 627 * @returns Pointer to the cache entry on success, NULL on allocation error. 628 * @param pThis The string cache instance. 629 * @param uHash The full hash of the string. 630 * @param pchString The string. 631 * @param cchString The string length. 632 */ 633 static PRTSTRCACHEENTRY rtStrCacheAllocHeapEntry(PRTSTRCACHEINT pThis, uint32_t uHash, 634 const char *pchString, uint32_t cchString) 635 { 636 /* 637 * Allocate a heap block for storing the string. We do some size aligning 638 * here to encourage the heap to give us optimal alignment. 639 */ 640 size_t cbEntry = RT_UOFFSETOF(RTSTRCACHEBIGENTRY, Core.szString[cchString + 1]); 641 PRTSTRCACHEBIGENTRY pBigEntry = (PRTSTRCACHEBIGENTRY)RTMemAlloc(RT_ALIGN_Z(cbEntry, 64)); 642 if (!pBigEntry) 643 return NULL; 644 645 /* 646 * Initialize the block. 647 */ 648 RTListAppend(&pThis->BigEntryList, &pBigEntry->ListEntry); 649 pBigEntry->cchString = cchString; 650 pBigEntry->uHash = uHash; 651 pBigEntry->Core.cRefs = 1; 652 pBigEntry->Core.uHash = (uint16_t)uHash; 653 pBigEntry->Core.cchString = RTSTRCACHEENTRY_BIG_LEN; 654 memcpy(pBigEntry->Core.szString, pchString, cchString); 655 pBigEntry->Core.szString[cchString] = '\0'; 656 657 return &pBigEntry->Core; 658 } 659 617 660 618 661 /** … … 644 687 645 688 PRTSTRCACHEFREE pPrev = NULL; 646 size_t const cbEntry = 1 << (iFreeList + 4);647 uint32_t cLeft = PAGE_SIZE / cbEntry - 1;689 uint32_t const cbEntry = g_acbFixedLists[iFreeList]; 690 uint32_t cLeft = RTSTRCACHE_FIXED_GROW_SIZE / cbEntry - 1; 648 691 pFree = (PRTSTRCACHEFREE)((uintptr_t)pChunk + cbEntry); 649 692 650 693 Assert(sizeof(*pChunk) <= cbEntry); 651 694 Assert(sizeof(*pFree) <= cbEntry); 652 Assert(cbEntry < PAGE_SIZE / 16);695 Assert(cbEntry < RTSTRCACHE_FIXED_GROW_SIZE / 16); 653 696 654 697 while (cLeft-- > 0) … … 762 805 uint32_t const uHashLen = RT_MAKE_U32(uHash, cchString); 763 806 AssertReturn(cchString < _1G, NULL); 764 807 uint32_t const cchString32 = (uint32_t)cchString; 765 808 766 809 RTCritSectEnter(&pThis->CritSect); … … 768 811 769 812 uint32_t iFreeHashTabEntry; 770 PRTSTRCACHEENTRY pEntry = rtStrCacheLookUp(pThis, uHashLen, cchString , pchString, &iFreeHashTabEntry);813 PRTSTRCACHEENTRY pEntry = rtStrCacheLookUp(pThis, uHashLen, cchString32, pchString, &iFreeHashTabEntry); 771 814 if (pEntry) 772 815 { … … 779 822 * Allocate a new entry. 780 823 */ 781 uint32_t cbEntry = cchString + 1U + RT_UOFFSETOF(RTSTRCACHEENTRY, szString); 782 if (cbEntry >= RTSTRCACHE_MERGED_THRESHOLD_BIT) 783 { 784 if (cbEntry <= RTSTRCACHE_HEAP_THRESHOLD) 785 pEntry = rtStrCacheAllocMergedEntry(pThis, uHash, pchString, cchString, cbEntry); 786 else 787 pEntry = rtStrCacheAllocHeapEntry(pThis, uHash, pchString, cchString); 788 } 824 uint32_t cbEntry = cchString32 + 1U + RT_UOFFSETOF(RTSTRCACHEENTRY, szString); 825 if (cbEntry >= RTSTRCACHE_HEAP_THRESHOLD) 826 pEntry = rtStrCacheAllocHeapEntry(pThis, uHash, pchString, cchString32); 827 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 828 else if (cbEntry >= RTSTRCACHE_MERGED_THRESHOLD_BIT) 829 pEntry = rtStrCacheAllocMergedEntry(pThis, uHash, pchString, cchString32, cbEntry); 830 #endif 789 831 else 790 pEntry = rtStrCacheAllocFixedEntry(pThis, uHash, pchString, cchString, cbEntry > 16); 832 pEntry = rtStrCacheAllocFixedEntry(pThis, uHash, pchString, cchString32, 833 rtStrCacheSelectFixedList(cbEntry)); 791 834 if (!pEntry) 792 835 { … … 941 984 { 942 985 uint32_t const cbMin = pStr->cchString + 1U + RT_UOFFSETOF(RTSTRCACHEENTRY, szString); 943 if (cbMin <= 32) 986 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 987 if (cbMin <= RTSTRCACHE_MAX_FIXED) 988 #endif 944 989 { 945 990 /* 946 991 * No merging, just add it to the list. 947 992 */ 948 uint32_t const iFreeList = cbMin > 16;993 uint32_t const iFreeList = rtStrCacheSelectFixedList(cbMin); 949 994 ASMCompilerBarrier(); 950 995 PRTSTRCACHEFREE pFreeStr = (PRTSTRCACHEFREE)pStr; … … 954 999 pThis->apFreeLists[iFreeList] = pFreeStr; 955 1000 } 1001 #ifdef RTSTRCACHE_WITH_MERGED_ALLOCATOR 956 1002 else 957 1003 { … … 1032 1078 rtStrCacheRelinkMerged(pThis, pMain); 1033 1079 } 1080 #endif /* RTSTRCACHE_WITH_MERGED_ALLOCATOR */ 1034 1081 RTSTRCACHE_CHECK(pThis); 1035 1082 RTCritSectLeave(&pThis->CritSect);
Note:
See TracChangeset
for help on using the changeset viewer.