VirtualBox

Changeset 24517 in vbox


Ignore:
Timestamp:
Nov 9, 2009 4:03:09 PM (15 years ago)
Author:
vboxsync
Message:

AsyncCompletion: Reuse evicted buffers if possible to avoid too much free/allocation calls

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp

    r24415 r24517  
    232232 * @param    pGhostListSrc    The ghost list removed entries should be moved to
    233233 *                            NULL if the entry should be freed.
     234 * @param    fReuseBuffer     Flag whether a buffer should be reused if it has the same size
     235 * @param    ppbBuf           Where to store the address of the buffer if an entry with the
     236 *                            same size was found and fReuseBuffer is true.
    234237 *
    235238 * @notes This function may return fewer bytes than requested because entries
     
    237240 */
    238241static size_t pdmacFileCacheEvictPagesFrom(PPDMACFILECACHEGLOBAL pCache, size_t cbData,
    239                                            PPDMACFILELRULIST pListSrc, PPDMACFILELRULIST pGhostListDst)
     242                                           PPDMACFILELRULIST pListSrc, PPDMACFILELRULIST pGhostListDst,
     243                                           bool fReuseBuffer, uint8_t **ppbBuffer)
    240244{
    241245    size_t cbEvicted = 0;
     
    248252              || (pGhostListDst == &pCache->LruFrequentlyGhost),
    249253              ("Destination list must be NULL or one of the ghost lists\n"));
     254
     255    if (fReuseBuffer)
     256    {
     257        AssertPtr(ppbBuffer);
     258        *ppbBuffer = NULL;
     259    }
    250260
    251261    /* Start deleting from the tail. */
     
    276286                LogFlow(("Evicting entry %#p (%u bytes)\n", pCurr, pCurr->cbData));
    277287
    278                 if (pCurr->pbData)
     288                if (fReuseBuffer && (pCurr->cbData == cbData))
    279289                {
     290                    STAM_COUNTER_INC(&pCache->StatBuffersReused);
     291                    *ppbBuffer = pCurr->pbData;
     292                }
     293                else if (pCurr->pbData)
    280294                    RTMemPageFree(pCurr->pbData);
    281                     pCurr->pbData = NULL;
    282                 }
    283 
     295
     296                pCurr->pbData = NULL;
    284297                cbEvicted += pCurr->cbData;
    285298
     
    310323}
    311324
    312 static size_t pdmacFileCacheReplace(PPDMACFILECACHEGLOBAL pCache, size_t cbData, PPDMACFILELRULIST pEntryList)
     325static size_t pdmacFileCacheReplace(PPDMACFILECACHEGLOBAL pCache, size_t cbData, PPDMACFILELRULIST pEntryList,
     326                                    bool fReuseBuffer, uint8_t **ppbBuffer)
    313327{
    314328    PDMACFILECACHE_IS_CRITSECT_OWNER(pCache);
     
    322336        return pdmacFileCacheEvictPagesFrom(pCache, cbData,
    323337                                            &pCache->LruRecentlyUsed,
    324                                             &pCache->LruRecentlyGhost);
     338                                            &pCache->LruRecentlyGhost,
     339                                            fReuseBuffer, ppbBuffer);
    325340    }
    326341    else
     
    329344        return pdmacFileCacheEvictPagesFrom(pCache, cbData,
    330345                                            &pCache->LruFrequentlyUsed,
    331                                             &pCache->LruFrequentlyGhost);
     346                                            &pCache->LruFrequentlyGhost,
     347                                            fReuseBuffer, ppbBuffer);
    332348    }
    333349}
     
    340356 * @param    cbData    Number of bytes to evict.
    341357 */
    342 static size_t pdmacFileCacheEvict(PPDMACFILECACHEGLOBAL pCache, size_t cbData)
     358static size_t pdmacFileCacheEvict(PPDMACFILECACHEGLOBAL pCache, size_t cbData, bool fReuseBuffer, uint8_t **ppbBuffer)
    343359{
    344360    size_t cbRemoved = ~0;
     
    353369            cbRemoved = pdmacFileCacheEvictPagesFrom(pCache, cbData,
    354370                                                     &pCache->LruRecentlyGhost,
    355                                                      NULL);
     371                                                     NULL,
     372                                                     fReuseBuffer, ppbBuffer);
    356373        }
    357374        else
     
    359376            cbRemoved = pdmacFileCacheEvictPagesFrom(pCache, cbData,
    360377                                                     &pCache->LruRecentlyUsed,
    361                                                      NULL);
     378                                                     NULL,
     379                                                     fReuseBuffer, ppbBuffer);
    362380        }
    363381    }
     
    372390                cbRemoved = pdmacFileCacheEvictPagesFrom(pCache, cbData,
    373391                                                         &pCache->LruFrequentlyGhost,
    374                                                          NULL);
     392                                                         NULL,
     393                                                         fReuseBuffer, ppbBuffer);
    375394
    376395            if (cbRemoved >= cbData)
    377                 cbRemoved = pdmacFileCacheReplace(pCache, cbData, NULL);
     396                cbRemoved = pdmacFileCacheReplace(pCache, cbData, NULL, fReuseBuffer, ppbBuffer);
    378397        }
    379398    }
     
    677696                   "/PDM/AsyncCompletion/File/CacheTreeRemove",
    678697                   STAMUNIT_TICKS_PER_CALL, "Time taken to remove an entry an the tree");
     698    STAMR3Register(pClassFile->Core.pVM, &pCache->StatBuffersReused,
     699                   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS,
     700                   "/PDM/AsyncCompletion/File/CacheBuffersReused",
     701                   STAMUNIT_COUNT, "Number of times a buffer could be reused");
    679702#endif
    680703
     
    866889 * @param   off       Start offset.
    867890 * @param   cbData    Size of the cache entry.
     891 * @param   pbBuffer  Pointer to the buffer to use.
     892 *                    NULL if a new buffer should be allocated.
     893 *                    The buffer needs to have the same size of the entry.
    868894 */
    869895static PPDMACFILECACHEENTRY pdmacFileCacheEntryAlloc(PPDMACFILECACHEGLOBAL pCache,
    870896                                                     PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
    871                                                      RTFOFF off, size_t cbData)
     897                                                     RTFOFF off, size_t cbData, uint8_t *pbBuffer)
    872898{
    873899    PPDMACFILECACHEENTRY pEntryNew = (PPDMACFILECACHEENTRY)RTMemAllocZ(sizeof(PDMACFILECACHEENTRY));
     
    887913    pEntryNew->pWaitingTail  = NULL;
    888914    pEntryNew->pbDataReplace = NULL;
    889     pEntryNew->pbData        = (uint8_t *)RTMemPageAlloc(cbData);
     915    if (pbBuffer)
     916        pEntryNew->pbData    = pbBuffer;
     917    else
     918        pEntryNew->pbData    = (uint8_t *)RTMemPageAlloc(cbData);
    890919
    891920    if (RT_UNLIKELY(!pEntryNew->pbData))
     
    11241153            else
    11251154            {
     1155                uint8_t *pbBuffer = NULL;
     1156
    11261157                LogFlow(("Fetching data for ghost entry %#p from file\n", pEntry));
    11271158
    11281159                RTCritSectEnter(&pCache->CritSect);
    11291160                pdmacFileCacheUpdate(pCache, pEntry);
    1130                 pdmacFileCacheReplace(pCache, pEntry->cbData, pEntry->pList);
     1161                pdmacFileCacheReplace(pCache, pEntry->cbData, pEntry->pList, true, &pbBuffer);
    11311162
    11321163                /* Move the entry to T2 and fetch it to the cache. */
     
    11341165                RTCritSectLeave(&pCache->CritSect);
    11351166
    1136                 pEntry->pbData  = (uint8_t *)RTMemPageAlloc(pEntry->cbData);
     1167                if (pbBuffer)
     1168                    pEntry->pbData = pbBuffer;
     1169                else
     1170                    pEntry->pbData = (uint8_t *)RTMemPageAlloc(pEntry->cbData);
    11371171                AssertPtr(pEntry->pbData);
    11381172
     
    12061240                STAM_COUNTER_INC(&pCache->cPartialHits);
    12071241
     1242            uint8_t *pbBuffer = NULL;
     1243
    12081244            RTCritSectEnter(&pCache->CritSect);
    1209             size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToReadAligned);
     1245            size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToReadAligned, true, &pbBuffer);
    12101246            RTCritSectLeave(&pCache->CritSect);
    12111247
     
    12131249            {
    12141250                LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToReadAligned));
    1215                 PPDMACFILECACHEENTRY pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToReadAligned);
     1251                PPDMACFILECACHEENTRY pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToReadAligned, pbBuffer);
    12161252                AssertPtr(pEntryNew);
    12171253
     
    15171553            else
    15181554            {
     1555                uint8_t *pbBuffer = NULL;
     1556
    15191557                RTCritSectEnter(&pCache->CritSect);
    15201558                pdmacFileCacheUpdate(pCache, pEntry);
    1521                 pdmacFileCacheReplace(pCache, pEntry->cbData, pEntry->pList);
     1559                pdmacFileCacheReplace(pCache, pEntry->cbData, pEntry->pList, true, &pbBuffer);
    15221560
    15231561                /* Move the entry to T2 and fetch it to the cache. */
     
    15251563                RTCritSectLeave(&pCache->CritSect);
    15261564
    1527                 pEntry->pbData  = (uint8_t *)RTMemPageAlloc(pEntry->cbData);
     1565                if (pbBuffer)
     1566                    pEntry->pbData = pbBuffer;
     1567                else
     1568                    pEntry->pbData = (uint8_t *)RTMemPageAlloc(pEntry->cbData);
    15281569                AssertPtr(pEntry->pbData);
    15291570
     
    15861627            STAM_COUNTER_ADD(&pCache->StatWritten, cbToWrite);
    15871628
     1629            uint8_t *pbBuffer = NULL;
     1630
    15881631            RTCritSectEnter(&pCache->CritSect);
    1589             size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToWrite);
     1632            size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToWrite, true, &pbBuffer);
    15901633            RTCritSectLeave(&pCache->CritSect);
    15911634
     
    15971640                LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToWrite));
    15981641
    1599                 pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToWrite);
     1642                pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToWrite, pbBuffer);
    16001643                AssertPtr(pEntryNew);
    16011644
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r24442 r24517  
    249249#define PDMACFILECACHE_ENTRY_IS_DEPRECATED  RT_BIT(3)
    250250/** Entry is not evictable. */
    251 #define PDMACFILECACHE_NOT_EVICTABLE  (PDMACFILECACHE_ENTRY_LOCKED | PDMACFILECACHE_IO_IN_PROGRESS)
     251#define PDMACFILECACHE_NOT_EVICTABLE  (PDMACFILECACHE_ENTRY_LOCKED | PDMACFILECACHE_IO_IN_PROGRESS | PDMACFILECACHE_ENTRY_IS_DEPRECATED)
    252252
    253253/**
     
    302302    /** Time spend to remove an entry in the AVL tree. */
    303303    STAMPROFILEADV   StatTreeRemove;
     304    /** Number of times a buffer could be reused. */
     305    STAMCOUNTER      StatBuffersReused;
    304306#endif
    305307} PDMACFILECACHEGLOBAL;
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