- Timestamp:
- Nov 12, 2009 7:05:01 PM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp
r24529 r24621 248 248 249 249 AssertMsg(cbData > 0, ("Evicting 0 bytes not possible\n")); 250 #ifdef VBOX_WITH_2Q_CACHE 251 AssertMsg( !pGhostListDst 252 || (pGhostListDst == &pCache->LruRecentlyUsedOut), 253 ("Destination list must be NULL or the recently used but paged out list\n")); 254 #else 250 255 AssertMsg( !pGhostListDst 251 256 || (pGhostListDst == &pCache->LruRecentlyGhost) 252 257 || (pGhostListDst == &pCache->LruFrequentlyGhost), 253 258 ("Destination list must be NULL or one of the ghost lists\n")); 259 #endif 254 260 255 261 if (fReuseBuffer) … … 297 303 cbEvicted += pCurr->cbData; 298 304 305 pCache->cbCached -= pCurr->cbData; 306 299 307 if (pGhostListDst) 300 308 { 309 #ifdef VBOX_WITH_2Q_CACHE 310 /* We have to remove the last entries from the paged out list. */ 311 while (pGhostListDst->cbCached > pCache->cbRecentlyUsedOutMax) 312 { 313 PPDMACFILECACHEENTRY pFree = pGhostListDst->pTail; 314 pdmacFileCacheEntryRemoveFromList(pFree); 315 STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache); 316 RTAvlrFileOffsetRemove(pCurr->pEndpoint->DataCache.pTree, pFree->Core.Key); 317 STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache); 318 RTMemFree(pFree); 319 } 320 #endif 321 301 322 pdmacFileCacheEntryAddToList(pGhostListDst, pCurr); 302 323 } … … 309 330 310 331 pdmacFileCacheEntryRemoveFromList(pCurr); 311 pCache->cbCached -= pCurr->cbData;312 313 332 RTMemFree(pCurr); 314 333 } … … 322 341 return cbEvicted; 323 342 } 343 344 #ifdef VBOX_WITH_2Q_CACHE 345 static bool pdmacFileCacheReclaim(PPDMACFILECACHEGLOBAL pCache, size_t cbData, bool fReuseBuffer, uint8_t **ppbBuffer) 346 { 347 size_t cbRemoved = 0; 348 349 if ((pCache->cbCached + cbData) < pCache->cbMax) 350 return true; 351 else if ((pCache->LruRecentlyUsedIn.cbCached + cbData) > pCache->cbRecentlyUsedInMax) 352 { 353 /* Try to evict as many bytes as possible from A1in */ 354 cbRemoved = pdmacFileCacheEvictPagesFrom(pCache, cbData, &pCache->LruRecentlyUsedIn, 355 &pCache->LruRecentlyUsedOut, fReuseBuffer, ppbBuffer); 356 357 /* 358 * If it was not possible to remove enough entries 359 * try the frequently accessed cache. 360 */ 361 if (cbRemoved < cbData) 362 { 363 Assert(!fReuseBuffer || !*ppbBuffer); /* It is not possible that we got a buffer with the correct size but we didn't freed enough data. */ 364 365 cbRemoved += pdmacFileCacheEvictPagesFrom(pCache, cbData - cbRemoved, &pCache->LruFrequentlyUsed, 366 NULL, fReuseBuffer, ppbBuffer); 367 } 368 } 369 else 370 { 371 /* We have to remove entries from frequently access list. */ 372 cbRemoved = pdmacFileCacheEvictPagesFrom(pCache, cbData, &pCache->LruFrequentlyUsed, 373 NULL, fReuseBuffer, ppbBuffer); 374 } 375 376 LogFlowFunc((": removed %u bytes, requested %u\n", cbRemoved, cbData)); 377 return (cbRemoved >= cbData); 378 } 379 380 #else 324 381 325 382 static size_t pdmacFileCacheReplace(PPDMACFILECACHEGLOBAL pCache, size_t cbData, PPDMACFILELRULIST pEntryList, … … 436 493 AssertMsgFailed(("Invalid list type\n")); 437 494 } 495 #endif 438 496 439 497 /** … … 509 567 PPDMACFILECACHEGLOBAL pCache = pEntry->pCache; 510 568 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pEntry->pEndpoint; 569 PPDMACFILEENDPOINTCACHE pEndpointCache = &pEndpoint->DataCache; 511 570 512 571 /* Reference the entry now as we are clearing the I/O in progres flag … … 609 668 PPDMACFILECACHEGLOBAL pCache = &pClassFile->Cache; 610 669 670 rc = CFGMR3QueryU32Def(pCfgNode, "CacheSize", &pCache->cbMax, 5 * _1M); 671 AssertLogRelRCReturn(rc, rc); 672 673 pCache->cbCached = 0; 674 LogFlowFunc((": Maximum number of bytes cached %u\n", pCache->cbMax)); 675 611 676 /* Initialize members */ 677 #ifdef VBOX_WITH_2Q_CACHE 678 pCache->LruRecentlyUsedIn.pHead = NULL; 679 pCache->LruRecentlyUsedIn.pTail = NULL; 680 pCache->LruRecentlyUsedIn.cbCached = 0; 681 682 pCache->LruRecentlyUsedOut.pHead = NULL; 683 pCache->LruRecentlyUsedOut.pTail = NULL; 684 pCache->LruRecentlyUsedOut.cbCached = 0; 685 686 pCache->LruFrequentlyUsed.pHead = NULL; 687 pCache->LruFrequentlyUsed.pTail = NULL; 688 pCache->LruFrequentlyUsed.cbCached = 0; 689 690 pCache->cbRecentlyUsedInMax = (pCache->cbMax / 100) * 25; /* 25% of the buffer size */ 691 pCache->cbRecentlyUsedOutMax = (pCache->cbMax / 100) * 50; /* 50% of the buffer size */ 692 LogFlowFunc((": cbRecentlyUsedInMax=%u cbRecentlyUsedOutMax=%u\n", pCache->cbRecentlyUsedInMax, pCache->cbRecentlyUsedOutMax)); 693 #else 612 694 pCache->LruRecentlyUsed.pHead = NULL; 613 695 pCache->LruRecentlyUsed.pTail = NULL; … … 626 708 pCache->LruFrequentlyGhost.cbCached = 0; 627 709 628 rc = CFGMR3QueryU32Def(pCfgNode, "CacheSize", &pCache->cbMax, 5 * _1M);629 AssertLogRelRCReturn(rc, rc);630 631 pCache->cbCached = 0;632 710 pCache->uAdaptVal = 0; 633 LogFlowFunc((": Maximum number of bytes cached %u\n", pCache->cbMax)); 711 #endif 634 712 635 713 STAMR3Register(pClassFile->Core.pVM, &pCache->cbMax, … … 643 721 STAMUNIT_BYTES, 644 722 "Currently used cache"); 723 #ifdef VBOX_WITH_2Q_CACHE 724 STAMR3Register(pClassFile->Core.pVM, &pCache->LruRecentlyUsedIn.cbCached, 725 STAMTYPE_U32, STAMVISIBILITY_ALWAYS, 726 "/PDM/AsyncCompletion/File/cbCachedMruIn", 727 STAMUNIT_BYTES, 728 "Number of bytes cached in MRU list"); 729 STAMR3Register(pClassFile->Core.pVM, &pCache->LruRecentlyUsedOut.cbCached, 730 STAMTYPE_U32, STAMVISIBILITY_ALWAYS, 731 "/PDM/AsyncCompletion/File/cbCachedMruOut", 732 STAMUNIT_BYTES, 733 "Number of bytes cached in FRU list"); 734 STAMR3Register(pClassFile->Core.pVM, &pCache->LruFrequentlyUsed.cbCached, 735 STAMTYPE_U32, STAMVISIBILITY_ALWAYS, 736 "/PDM/AsyncCompletion/File/cbCachedFru", 737 STAMUNIT_BYTES, 738 "Number of bytes cached in FRU ghost list"); 739 #else 645 740 STAMR3Register(pClassFile->Core.pVM, &pCache->LruRecentlyUsed.cbCached, 646 741 STAMTYPE_U32, STAMVISIBILITY_ALWAYS, … … 662 757 "/PDM/AsyncCompletion/File/cbCachedFruGhost", 663 758 STAMUNIT_BYTES, "Number of bytes cached in Fru ghost list"); 759 #endif 664 760 665 761 #ifdef VBOX_WITH_STATISTICS … … 729 825 RTCritSectEnter(&pCache->CritSect); 730 826 827 #ifdef VBOX_WITH_2Q_CACHE 828 /* Cleanup deleting all cache entries waiting for in progress entries to finish. */ 829 pdmacFileCacheDestroyList(&pCache->LruRecentlyUsedIn); 830 pdmacFileCacheDestroyList(&pCache->LruRecentlyUsedOut); 831 pdmacFileCacheDestroyList(&pCache->LruFrequentlyUsed); 832 #else 731 833 /* Cleanup deleting all cache entries waiting for in progress entries to finish. */ 732 834 pdmacFileCacheDestroyList(&pCache->LruRecentlyUsed); … … 734 836 pdmacFileCacheDestroyList(&pCache->LruRecentlyGhost); 735 837 pdmacFileCacheDestroyList(&pCache->LruFrequentlyGhost); 838 #endif 736 839 737 840 RTCritSectLeave(&pCache->CritSect); … … 940 1043 * @param pSeg The segment to add. 941 1044 */ 942 static voidpdmacFileEpCacheEntryAddWaitingSegment(PPDMACFILECACHEENTRY pEntry, PPDMACFILETASKSEG pSeg)1045 DECLINLINE(void) pdmacFileEpCacheEntryAddWaitingSegment(PPDMACFILECACHEENTRY pEntry, PPDMACFILETASKSEG pSeg) 943 1046 { 944 1047 pSeg->pNext = NULL; … … 1082 1185 1083 1186 /* Ghost lists contain no data. */ 1187 #ifdef VBOX_WITH_2Q_CACHE 1188 if ( (pEntry->pList == &pCache->LruRecentlyUsedIn) 1189 || (pEntry->pList == &pCache->LruFrequentlyUsed)) 1190 { 1191 #else 1084 1192 if ( (pEntry->pList == &pCache->LruRecentlyUsed) 1085 1193 || (pEntry->pList == &pCache->LruFrequentlyUsed)) 1086 1194 { 1195 #endif 1087 1196 if(pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry, 1088 1197 PDMACFILECACHE_ENTRY_IS_DEPRECATED, … … 1152 1261 1153 1262 /* Move this entry to the top position */ 1263 #ifdef VBOX_WITH_2Q_CACHE 1264 if (pEntry->pList == &pCache->LruFrequentlyUsed) 1265 { 1266 RTCritSectEnter(&pCache->CritSect); 1267 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1268 RTCritSectLeave(&pCache->CritSect); 1269 } 1270 #else 1154 1271 RTCritSectEnter(&pCache->CritSect); 1155 1272 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1156 1273 RTCritSectLeave(&pCache->CritSect); 1274 #endif 1157 1275 } 1158 1276 else … … 1162 1280 LogFlow(("Fetching data for ghost entry %#p from file\n", pEntry)); 1163 1281 1282 #ifdef VBOX_WITH_2Q_CACHE 1283 RTCritSectEnter(&pCache->CritSect); 1284 pdmacFileCacheEntryRemoveFromList(pEntry); /* Remove it before we remove data, otherwise it may get freed when evicting data. */ 1285 pdmacFileCacheReclaim(pCache, pEntry->cbData, true, &pbBuffer); 1286 1287 /* Move the entry to Am and fetch it to the cache. */ 1288 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1289 RTCritSectLeave(&pCache->CritSect); 1290 #else 1164 1291 RTCritSectEnter(&pCache->CritSect); 1165 1292 pdmacFileCacheUpdate(pCache, pEntry); … … 1169 1296 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1170 1297 RTCritSectLeave(&pCache->CritSect); 1298 #endif 1171 1299 1172 1300 if (pbBuffer) … … 1250 1378 uint8_t *pbBuffer = NULL; 1251 1379 1380 #ifdef VBOX_WITH_2Q_CACHE 1381 RTCritSectEnter(&pCache->CritSect); 1382 bool fEnough = pdmacFileCacheReclaim(pCache, cbToReadAligned, true, &pbBuffer); 1383 RTCritSectLeave(&pCache->CritSect); 1384 1385 if (fEnough) 1386 { 1387 LogFlow(("Evicted enough bytes (%u requested). Creating new cache entry\n", cbToReadAligned)); 1388 #else 1252 1389 RTCritSectEnter(&pCache->CritSect); 1253 1390 size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToReadAligned, true, &pbBuffer); … … 1257 1394 { 1258 1395 LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToReadAligned)); 1396 #endif 1259 1397 PPDMACFILECACHEENTRY pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToReadAligned, pbBuffer); 1260 1398 AssertPtr(pEntryNew); 1261 1399 1262 1400 RTCritSectEnter(&pCache->CritSect); 1401 #ifdef VBOX_WITH_2Q_CACHE 1402 pdmacFileCacheEntryAddToList(&pCache->LruRecentlyUsedIn, pEntryNew); 1403 #else 1263 1404 pdmacFileCacheEntryAddToList(&pCache->LruRecentlyUsed, pEntryNew); 1405 #endif 1264 1406 pCache->cbCached += cbToReadAligned; 1265 1407 RTCritSectLeave(&pCache->CritSect); … … 1295 1437 * Pass the request directly to the I/O manager. 1296 1438 */ 1297 LogFlow(("Couldn't evict %u bytes from the cache (%u actually removed). Remaining request will be passed through\n", cbToRead, cbRemoved));1439 LogFlow(("Couldn't evict %u bytes from the cache. Remaining request will be passed through\n", cbToRead)); 1298 1440 1299 1441 while (cbToRead) … … 1390 1532 1391 1533 /* Ghost lists contain no data. */ 1534 #ifdef VBOX_WITH_2Q_CACHE 1535 if ( (pEntry->pList == &pCache->LruRecentlyUsedIn) 1536 || (pEntry->pList == &pCache->LruFrequentlyUsed)) 1537 #else 1392 1538 if ( (pEntry->pList == &pCache->LruRecentlyUsed) 1393 1539 || (pEntry->pList == &pCache->LruFrequentlyUsed)) 1540 #endif 1394 1541 { 1395 1542 /* Check if the buffer is deprecated. */ … … 1554 1701 1555 1702 /* Move this entry to the top position */ 1703 #ifdef VBOX_WITH_2Q_CACHE 1704 if (pEntry->pList == &pCache->LruFrequentlyUsed) 1705 { 1556 1706 RTCritSectEnter(&pCache->CritSect); 1557 1707 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1558 1708 RTCritSectLeave(&pCache->CritSect); 1559 1709 } /* Deprecated flag not set. */ 1710 #else 1711 RTCritSectEnter(&pCache->CritSect); 1712 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1713 RTCritSectLeave(&pCache->CritSect); 1714 #endif 1715 } 1560 1716 } 1561 1717 else /* Entry is on the ghost list */ … … 1563 1719 uint8_t *pbBuffer = NULL; 1564 1720 1721 #ifdef VBOX_WITH_2Q_CACHE 1722 RTCritSectEnter(&pCache->CritSect); 1723 pdmacFileCacheEntryRemoveFromList(pEntry); /* Remove it before we remove data, otherwise it may get freed when evicting data. */ 1724 pdmacFileCacheReclaim(pCache, pEntry->cbData, true, &pbBuffer); 1725 1726 /* Move the entry to Am and fetch it to the cache. */ 1727 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1728 RTCritSectLeave(&pCache->CritSect); 1729 #else 1565 1730 RTCritSectEnter(&pCache->CritSect); 1566 1731 pdmacFileCacheUpdate(pCache, pEntry); … … 1570 1735 pdmacFileCacheEntryAddToList(&pCache->LruFrequentlyUsed, pEntry); 1571 1736 RTCritSectLeave(&pCache->CritSect); 1737 #endif 1572 1738 1573 1739 if (pbBuffer) … … 1642 1808 uint8_t *pbBuffer = NULL; 1643 1809 1810 #ifdef VBOX_WITH_2Q_CACHE 1811 RTCritSectEnter(&pCache->CritSect); 1812 bool fEnough = pdmacFileCacheReclaim(pCache, cbToWrite, true, &pbBuffer); 1813 RTCritSectLeave(&pCache->CritSect); 1814 1815 if (fEnough) 1816 { 1817 LogFlow(("Evicted enough bytes (%u requested). Creating new cache entry\n", cbToWrite)); 1818 #else 1644 1819 RTCritSectEnter(&pCache->CritSect); 1645 1820 size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToWrite, true, &pbBuffer); … … 1648 1823 if (cbRemoved >= cbToWrite) 1649 1824 { 1825 LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToWrite)); 1826 1827 #endif 1650 1828 uint8_t *pbBuf; 1651 1829 PPDMACFILECACHEENTRY pEntryNew; 1652 1830 1653 LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToWrite));1654 1655 1831 pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToWrite, pbBuffer); 1656 1832 AssertPtr(pEntryNew); 1657 1833 1658 1834 RTCritSectEnter(&pCache->CritSect); 1835 #ifdef VBOX_WITH_2Q_CACHE 1836 pdmacFileCacheEntryAddToList(&pCache->LruRecentlyUsedIn, pEntryNew); 1837 #else 1659 1838 pdmacFileCacheEntryAddToList(&pCache->LruRecentlyUsed, pEntryNew); 1839 #endif 1660 1840 pCache->cbCached += cbToWrite; 1661 1841 RTCritSectLeave(&pCache->CritSect); … … 1689 1869 * Pass the request directly to the I/O manager. 1690 1870 */ 1691 LogFlow(("Couldn't evict %u bytes from the cache (%u actually removed). Remaining request will be passed through\n", cbToWrite, cbRemoved));1871 LogFlow(("Couldn't evict %u bytes from the cache. Remaining request will be passed through\n", cbToWrite)); 1692 1872 1693 1873 while (cbToWrite) -
trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
r24517 r24621 33 33 34 34 #include "PDMAsyncCompletionInternal.h" 35 36 /** Enable the 2Q cache alogrithm. */ 37 #define VBOX_WITH_2Q_CACHE 1 35 38 36 39 /** @todo: Revise the caching of tasks. We have currently four caches: … … 275 278 /** Critical section protecting the cache. */ 276 279 RTCRITSECT CritSect; 280 #ifdef VBOX_WITH_2Q_CACHE 281 uint32_t cbRecentlyUsedInMax; 282 uint32_t cbRecentlyUsedOutMax; 283 PDMACFILELRULIST LruRecentlyUsedIn; 284 PDMACFILELRULIST LruRecentlyUsedOut; 285 PDMACFILELRULIST LruFrequentlyUsed; 286 #else 277 287 /** Adaption parameter (p) */ 278 288 uint32_t uAdaptVal; … … 285 295 /** LRU list for evicted entries from T2 (B2) */ 286 296 PDMACFILELRULIST LruFrequentlyGhost; 297 #endif 287 298 #ifdef VBOX_WITH_STATISTICS 288 299 /** Hit counter. */
Note:
See TracChangeset
for help on using the changeset viewer.