VirtualBox

Changeset 97926 in vbox for trunk


Ignore:
Timestamp:
Dec 30, 2022 11:40:02 PM (2 years ago)
Author:
vboxsync
Message:

Add/VBoxGuestR0LibPhysHeap.cpp: Restrict the number of free list entries we consider during allocation to prevent pointless search for a perfect match in a busy and fragmented heap.

Location:
trunk/src/VBox/Additions/common/VBoxGuest/lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibPhysHeap.cpp

    r97925 r97926  
    8181
    8282/* Heap block signature */
    83 #define VBGL_PH_BLOCKSIGNATURE (0xADDBBBBB)
    84 
     83#define VBGL_PH_BLOCKSIGNATURE  UINT32_C(0xADDBBBBB)
    8584
    8685/* Heap chunk signature */
    87 #define VBGL_PH_CHUNKSIGNATURE (0xADDCCCCC)
     86#define VBGL_PH_CHUNKSIGNATURE  UINT32_C(0xADDCCCCC)
    8887/* Heap chunk allocation unit */
    89 #define VBGL_PH_CHUNKSIZE (0x10000)
    90 
    91 /* Heap block bit flags */
    92 #define VBGL_PH_BF_ALLOCATED (0x1)
     88#define VBGL_PH_CHUNKSIZE       (0x10000)
     89
     90/** Max number of free nodes to search before just using the best fit.
     91 *
     92 * This is used to limit the free list walking during allocation and just get
     93 * on with the job.  A low number should reduce the cache trashing at the
     94 * possible cost of heap fragmentation.
     95 *
     96 * Picked 16 after comparing the tstVbglR0PhysHeap-1 results w/ uRandSeed=42 for
     97 * different max values.
     98 */
     99#define VBGL_PH_MAX_FREE_SEARCH         16
    93100
    94101/** Threshold at which to split out a tail free block when allocating.
     
    438445DECLR0VBGL(void *) VbglR0PhysHeapAlloc(uint32_t cbSize)
    439446{
    440     VBGLPHYSHEAPBLOCK *pBlock, *pIter;
    441     int rc;
     447    VBGLPHYSHEAPBLOCK *pBlock;
     448    VBGLPHYSHEAPBLOCK *pIter;
     449    int32_t            cLeft;
     450    int                rc;
    442451
    443452    /*
     
    457466     * there to be many blocks in the heap.
    458467     */
    459     /** @todo r=bird: Don't walk these lists for ever, use the block count
    460      *        statistics to limit the walking to the first X or something. */
     468    cLeft  = VBGL_PH_MAX_FREE_SEARCH;
    461469    pBlock = NULL;
    462470    if (cbSize <= PAGE_SIZE / 4 * 3)
     
    465473           so HGCM processing in VMMDev can use page locks instead of several reads and writes. */
    466474        VBGLPHYSHEAPBLOCK *pFallback = NULL;
    467         for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
     475        for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext, cLeft--)
    468476        {
    469477            AssertBreak(pIter->u32Signature == VBGL_PH_BLOCKSIGNATURE);
     
    487495                            pBlock = pIter;
    488496                }
     497
     498                if (cLeft > 0)
     499                { /* likely */ }
     500                else
     501                    break;
    489502            }
    490503        }
     
    496509    {
    497510        /* Large than 3/4 page:  Find closest free list match. */
    498         for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
     511        for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext, cLeft--)
    499512        {
    500513            AssertBreak(pIter->u32Signature == VBGL_PH_BLOCKSIGNATURE);
     
    511524                if (!pBlock || pIter->cbDataSize < pBlock->cbDataSize)
    512525                    pBlock = pIter;
     526
     527                if (cLeft > 0)
     528                { /* likely */ }
     529                else
     530                    break;
    513531            }
    514532        }
     
    556574        dumpheap("post alloc");
    557575
     576        /*
     577         * Return success.
     578         */
    558579        rc = RTSemFastMutexRelease(g_vbgldata.mutexHeap);
    559580
     
    562583    }
    563584
     585    /*
     586     * Return failure.
     587     */
    564588    rc = RTSemFastMutexRelease(g_vbgldata.mutexHeap);
    565589    AssertRC(rc);
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/testcase/tstVbglR0PhysHeap-1.cpp

    r97923 r97926  
    159159        return rc;
    160160    RTTestBanner(hTest);
     161
     162    /*
     163     * Arguments are taken to be random seeding.
     164     */
     165    uint64_t uRandSeed = RTTimeNanoTS();
     166    for (int i = 1; i < argc; i++)
     167    {
     168        rc = RTStrToUInt64Full(argv[i], 0, &uRandSeed);
     169        if (rc != VINF_SUCCESS)
     170        {
     171            RTTestIFailed("Invalid parameter: %Rrc: %s\n", rc, argv[i]);
     172            return RTTestSummaryAndDestroy(hTest);
     173        }
     174    }
    161175
    162176    /*
     
    276290    if (RT_FAILURE(rc))
    277291        return RTTestSummaryAndDestroy(hTest);
    278 #if 0
    279     RTRandAdvSeed(hRand, 42);
    280 #else
    281     RTRandAdvSeed(hRand, RTTimeNanoTS());
    282 #endif
     292    RTRandAdvSeed(hRand, uRandSeed);
     293    RTTestValue(hTest, "RandSeed", uRandSeed, RTTESTUNIT_NONE);
    283294
    284295    static TSTHISTORYENTRY s_aHistory[3072];
     
    364375        {
    365376            /* free all */
     377            RTTestIPrintf(RTTESTLVL_ALWAYS, "Free-all-pre:  cFreeBlocks=%u cAllocedBlocks=%u in %u chunk(s)\n",
     378                          g_vbgldata.acBlocks[0], g_vbgldata.acBlocks[1], g_cChunks);
    366379            for (i = 0; i < RT_ELEMENTS(s_aHistory); i++)
    367380            {
     
    369382                s_aHistory[i].pv = NULL;
    370383            }
    371             RTTestIPrintf(RTTESTLVL_ALWAYS, "after free-all: cFreeBlocks=%u in %u chunk(s)\n", g_vbgldata.acBlocks[0], g_cChunks);
     384            RTTestIPrintf(RTTESTLVL_ALWAYS, "Free-all-post: cFreeBlocks=%u in %u chunk(s)\n", g_vbgldata.acBlocks[0], g_cChunks);
    372385            RTTESTI_CHECK_MSG(g_cChunks == 1, ("g_cChunks=%d\n", g_cChunks));
    373386            RTTESTI_CHECK_MSG(g_vbgldata.acBlocks[1] == 0, ("g_vbgldata.acBlocks[1]=%d\n", g_vbgldata.acBlocks[0]));
    374 #if 0
    375             for (VBGLPHYSHEAPCHUNK *pCurChunk = g_vbgldata.pChunkHead; pCurChunk; pCurChunk = pCurChunk->pNext)
    376             {
    377                 RTTestIPrintf(RTTESTLVL_ALWAYS, "pCurChunk=%p: cAllocatedBlocks=%d\n", pCurChunk, pCurChunk->cAllocatedBlocks);
    378                 uintptr_t const          uEnd        = (uintptr_t)pCurChunk + pCurChunk->cbSize;
    379                 const VBGLPHYSHEAPBLOCK *pCurBlock   = (const VBGLPHYSHEAPBLOCK *)(pCurChunk + 1);
    380                 unsigned                 iCurBlock   = 0;
    381                 while ((uintptr_t)pCurBlock < uEnd)
    382                 {
    383                     RTTestIPrintf(RTTESTLVL_ALWAYS, "  #%2u/%p: cb=%#x %s byte0=%02x\n",
    384                                   iCurBlock, pCurBlock, pCurBlock->cbDataSize, pCurBlock->fu32Flags ? "alloc" : "free",
    385                                   *(uint8_t const *)(pCurBlock + 1));
    386                     pCurBlock = (const VBGLPHYSHEAPBLOCK *)((uintptr_t)(pCurBlock + 1) + pCurBlock->cbDataSize);
    387                     iCurBlock++;
    388                 }
    389             }
    390 #endif
    391387
    392388            //size_t cbAfterRand = VbglR0PhysHeapGetFreeSize();
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette