VirtualBox

Changeset 24278 in vbox


Ignore:
Timestamp:
Nov 2, 2009 8:26:07 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
54251
Message:

AsyncCompletion: Cleanup in the cache and more statistics (more to come)

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

Legend:

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

    r24059 r24278  
    4242#include <iprt/string.h>
    4343#include <iprt/thread.h>
     44#include <iprt/path.h>
    4445
    4546#include "PDMAsyncCompletionFileInternal.h"
     
    693694    }
    694695
     696#ifdef VBOX_WITH_STATISTICS
     697    if (RT_SUCCESS(rc))
     698    {
     699        STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatRead,
     700                       STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS,
     701                       STAMUNIT_TICKS_PER_CALL, "Time taken to read from the endpoint",
     702                       "/PDM/AsyncCompletion/File/%s/Read", RTPathFilename(pEpFile->Core.pszUri));
     703
     704        STAMR3RegisterF(pEpClassFile->Core.pVM, &pEpFile->StatWrite,
     705                       STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS,
     706                       STAMUNIT_TICKS_PER_CALL, "Time taken to write to the endpoint",
     707                       "/PDM/AsyncCompletion/File/%s/Write", RTPathFilename(pEpFile->Core.pszUri));
     708    }
     709#endif
     710
    695711    return rc;
    696712}
     
    728744    RTFileClose(pEpFile->File);
    729745
     746#ifdef VBOX_WITH_STATISTICS
     747    STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatRead);
     748    STAMR3Deregister(pEpClassFile->Core.pVM, &pEpFile->StatWrite);
     749#endif
     750
    730751    return VINF_SUCCESS;
    731752}
     
    736757                           size_t cbRead)
    737758{
     759    int rc = VINF_SUCCESS;
    738760    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;
    739761
     762    STAM_PROFILE_ADV_START(&pEpFile->StatRead, Read);
     763
    740764    if (pEpFile->fCaching)
    741         return pdmacFileEpCacheRead(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,
    742                                     off, paSegments, cSegments, cbRead);
     765        rc = pdmacFileEpCacheRead(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,
     766                                  off, paSegments, cSegments, cbRead);
    743767    else
    744         return pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbRead,
    745                                        PDMACTASKFILETRANSFER_READ);
     768        rc = pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbRead,
     769                                     PDMACTASKFILETRANSFER_READ);
     770
     771    STAM_PROFILE_ADV_STOP(&pEpFile->StatRead, Read);
     772
     773    return rc;
    746774}
    747775
     
    751779                            size_t cbWrite)
    752780{
     781    int rc = VINF_SUCCESS;
    753782    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;
    754783
     
    756785        return VERR_NOT_SUPPORTED;
    757786
     787    STAM_PROFILE_ADV_START(&pEpFile->StatWrite, Write);
     788
    758789    if (pEpFile->fCaching)
    759         return pdmacFileEpCacheWrite(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,
    760                                      off, paSegments, cSegments, cbWrite);
     790        rc = pdmacFileEpCacheWrite(pEpFile, (PPDMASYNCCOMPLETIONTASKFILE)pTask,
     791                                   off, paSegments, cSegments, cbWrite);
    761792    else
    762         return pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbWrite,
    763                                        PDMACTASKFILETRANSFER_WRITE);
     793        rc = pdmacFileEpTaskInitiate(pTask, pEndpoint, off, paSegments, cSegments, cbWrite,
     794                                     PDMACTASKFILETRANSFER_WRITE);
     795
     796    STAM_PROFILE_ADV_STOP(&pEpFile->StatWrite, Write);
     797
     798    return rc;
    764799}
    765800
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp

    r24202 r24278  
    4747#include <iprt/types.h>
    4848#include <iprt/mem.h>
     49#include <iprt/path.h>
    4950#include <VBox/log.h>
    5051#include <VBox/stam.h>
     
    714715    }
    715716
     717#ifdef VBOX_WITH_STATISTICS
     718    if (RT_SUCCESS(rc))
     719    {
     720        STAMR3RegisterF(pClassFile->Core.pVM, &pEndpointCache->StatWriteDeferred,
     721                       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS,
     722                       STAMUNIT_COUNT, "Number of deferred writes",
     723                       "/PDM/AsyncCompletion/File/%s/Cache/DeferredWrites", RTPathFilename(pEndpoint->Core.pszUri));
     724    }
     725#endif
     726
    716727    return rc;
    717728}
     
    768779
    769780    RTSemRWDestroy(pEndpointCache->SemRWEntries);
     781
     782#ifdef VBOX_WITH_STATISTICS
     783    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;
     784
     785    STAMR3Deregister(pEpClassFile->Core.pVM, &pEndpointCache->StatWriteDeferred);
     786#endif
    770787}
    771788
     
    884901        pEntry->pWaitingTail = pSeg;
    885902    }
     903}
     904
     905/**
     906 * Checks that a set of flags is set/clear acquiring the R/W semaphore
     907 * in exclusive mode.
     908 *
     909 * @returns true if the flag in fSet is set and the one in fClear is clear.
     910 *          false othwerise.
     911 *          The R/W semaphore is only held if true is returned.
     912 *
     913 * @param   pEndpointCache   The endpoint cache instance data.
     914 * @param   pEntry           The entry to check the flags for.
     915 * @param   fSet             The flag which is tested to be set.
     916 * @param   fClear           The flag which is tested to be clear.
     917 */
     918DECLINLINE(bool) pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(PPDMACFILEENDPOINTCACHE pEndpointCache,
     919                                                                PPDMACFILECACHEENTRY pEntry,
     920                                                                uint32_t fSet, uint32_t fClear)
     921{
     922    bool fPassed = ((pEntry->fFlags & fSet) && !(pEntry->fFlags & fClear));
     923
     924    if (fPassed)
     925    {
     926        /* Acquire the lock and check again becuase the completion callback might have raced us. */
     927        RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT);
     928
     929        fPassed = ((pEntry->fFlags & fSet) && !(pEntry->fFlags & fClear));
     930
     931        /* Drop the lock if we didn't passed the test. */
     932        if (!fPassed)
     933            RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
     934    }
     935
     936    return fPassed;
    886937}
    887938
     
    9791030                LogFlow(("Fetching data for ghost entry %#p from file\n", pEntry));
    9801031
    981                 if (   (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS)
    982                     && !(pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY))
     1032                if (pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry,
     1033                                                                   PDMACFILECACHE_ENTRY_IO_IN_PROGRESS,
     1034                                                                   PDMACFILECACHE_ENTRY_IS_DIRTY))
    9831035                {
    984                     RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT);
    985                     /* Check again. The completion callback might have raced us. */
    986 
    987                     if (   (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS)
    988                         && !(pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY))
     1036                    /* Entry didn't completed yet. Append to the list */
     1037                    while (cbToRead)
    9891038                    {
    990                         /* Entry didn't completed yet. Append to the list */
    991                         while (cbToRead)
    992                         {
    993                             PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
    994 
    995                             pSeg->pTask      = pTask;
    996                             pSeg->uBufOffset = OffDiff;
    997                             pSeg->cbTransfer = RT_MIN(cbToRead, cbSegLeft);
    998                             pSeg->pvBuf      = pbSegBuf;
    999                             pSeg->fWrite     = false;
    1000 
    1001                             ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
    1002 
    1003                             pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
    1004 
    1005                             off      += pSeg->cbTransfer;
    1006                             cbToRead -= pSeg->cbTransfer;
    1007                             OffDiff  += pSeg->cbTransfer;
    1008                         }
    1009                         RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
     1039                        PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
     1040
     1041                        pSeg->pTask      = pTask;
     1042                        pSeg->uBufOffset = OffDiff;
     1043                        pSeg->cbTransfer = RT_MIN(cbToRead, cbSegLeft);
     1044                        pSeg->pvBuf      = pbSegBuf;
     1045                        pSeg->fWrite     = false;
     1046
     1047                        ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
     1048
     1049                        pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
     1050
     1051                        off      += pSeg->cbTransfer;
     1052                        cbToRead -= pSeg->cbTransfer;
     1053                        OffDiff  += pSeg->cbTransfer;
    10101054                    }
    1011                     else
    1012                     {
    1013                         RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    1014 
    1015                         /* Read as much as we can from the entry. */
    1016                         while (cbToRead)
    1017                         {
    1018                             size_t cbCopy = RT_MIN(cbSegLeft, cbToRead);
    1019 
    1020                             memcpy(pbSegBuf, pEntry->pbData + OffDiff, cbCopy);
    1021 
    1022                             ADVANCE_SEGMENT_BUFFER(cbCopy);
    1023 
    1024                             cbToRead -= cbCopy;
    1025                             off      += cbCopy;
    1026                             OffDiff  += cbCopy;
    1027                             ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy);
    1028                         }
    1029                     }
     1055                    RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    10301056                }
    10311057                else
     
    12771303                || (pEntry->pList == &pCache->LruFrequentlyUsed))
    12781304            {
    1279                 if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY)
     1305
     1306                /* If the entry is dirty it must be also in progress now and we have to defer updating it again. */
     1307                if(pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry,
     1308                                                                  PDMACFILECACHE_ENTRY_IS_DIRTY,
     1309                                                                  0))
    12801310                {
    1281                     RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT);
    1282                     /* Check again. The completion callback might have raced us. */
    1283 
    1284                     if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IS_DIRTY)
     1311                    AssertMsg(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS,
     1312                                ("Entry is dirty but not in progress\n"));
     1313
     1314                    /* The data isn't written to the file yet */
     1315                    while (cbToWrite)
    12851316                    {
    1286                         AssertMsg(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS,
    1287                                   ("Entry is dirty but not in progress\n"));
    1288 
    1289                         /* The data isn't written to the file yet */
    1290                         while (cbToWrite)
    1291                         {
    1292                             PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
    1293 
    1294                             pSeg->pTask      = pTask;
    1295                             pSeg->uBufOffset = OffDiff;
    1296                             pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft);
    1297                             pSeg->pvBuf      = pbSegBuf;
    1298                             pSeg->fWrite     = true;
    1299 
    1300                             ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
    1301 
    1302                             pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
    1303 
    1304                             off       += pSeg->cbTransfer;
    1305                             OffDiff   += pSeg->cbTransfer;
    1306                             cbToWrite -= pSeg->cbTransfer;
    1307                         }
    1308                         RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
     1317                        PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
     1318
     1319                        pSeg->pTask      = pTask;
     1320                        pSeg->uBufOffset = OffDiff;
     1321                        pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft);
     1322                        pSeg->pvBuf      = pbSegBuf;
     1323                        pSeg->fWrite     = true;
     1324
     1325                        ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
     1326
     1327                        pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
     1328
     1329                        off       += pSeg->cbTransfer;
     1330                        OffDiff   += pSeg->cbTransfer;
     1331                        cbToWrite -= pSeg->cbTransfer;
    13091332                    }
    1310                     else
    1311                     {
    1312                         RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    1313 
    1314                         AssertMsg(!(pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS),
    1315                                   ("Entry is not dirty but in progress\n"));
    1316 
    1317                         /* Write as much as we can into the entry and update the file. */
    1318                         while (cbToWrite)
    1319                         {
    1320                             size_t cbCopy = RT_MIN(cbSegLeft, cbToWrite);
    1321 
    1322                             memcpy(pEntry->pbData + OffDiff, pbSegBuf, cbCopy);
    1323 
    1324                             ADVANCE_SEGMENT_BUFFER(cbCopy);
    1325 
    1326                             cbToWrite-= cbCopy;
    1327                             off      += cbCopy;
    1328                             OffDiff  += cbCopy;
    1329                             ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy);
    1330                         }
    1331 
    1332                         pEntry->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY;
    1333                         pdmacFileCacheWriteToEndpoint(pEntry);
    1334                     }
     1333                    STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred);
     1334                    RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    13351335                }
    13361336                else
     
    13401340                     * We have to defer processing in that case.
    13411341                     */
    1342                     if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS)
     1342                    if(pdmacFileEpCacheEntryFlagIsSetClearAcquireLock(pEndpointCache, pEntry,
     1343                                                                      PDMACFILECACHE_ENTRY_IO_IN_PROGRESS,
     1344                                                                      0))
    13431345                    {
    1344                         RTSemRWRequestWrite(pEndpointCache->SemRWEntries, RT_INDEFINITE_WAIT);
    1345 
    1346                         /* Check again. The completion callback might have raced us. */
    1347                         if (pEntry->fFlags & PDMACFILECACHE_ENTRY_IO_IN_PROGRESS)
     1346                        while (cbToWrite)
    13481347                        {
    1349 
    1350                             while (cbToWrite)
    1351                             {
    1352                                 PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
    1353 
    1354                                 pSeg->pTask      = pTask;
    1355                                 pSeg->uBufOffset = OffDiff;
    1356                                 pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft);
    1357                                 pSeg->pvBuf      = pbSegBuf;
    1358                                 pSeg->fWrite     = true;
    1359 
    1360                                 ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
    1361 
    1362                                 pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
    1363 
    1364                                 off       += pSeg->cbTransfer;
    1365                                 OffDiff   += pSeg->cbTransfer;
    1366                                 cbToWrite -= pSeg->cbTransfer;
    1367                             }
    1368 
    1369                             RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
     1348                            PPDMACFILETASKSEG pSeg = (PPDMACFILETASKSEG)RTMemAllocZ(sizeof(PDMACFILETASKSEG));
     1349
     1350                            pSeg->pTask      = pTask;
     1351                            pSeg->uBufOffset = OffDiff;
     1352                            pSeg->cbTransfer = RT_MIN(cbToWrite, cbSegLeft);
     1353                            pSeg->pvBuf      = pbSegBuf;
     1354                            pSeg->fWrite     = true;
     1355
     1356                            ADVANCE_SEGMENT_BUFFER(pSeg->cbTransfer);
     1357
     1358                            pdmacFileEpCacheEntryAddWaitingSegment(pEntry, pSeg);
     1359
     1360                            off       += pSeg->cbTransfer;
     1361                            OffDiff   += pSeg->cbTransfer;
     1362                            cbToWrite -= pSeg->cbTransfer;
    13701363                        }
    1371                         else
    1372                         {
    1373                             RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    1374 
    1375                             /* Write as much as we can into the entry and update the file. */
    1376                             while (cbToWrite)
    1377                             {
    1378                                 size_t cbCopy = RT_MIN(cbSegLeft, cbToWrite);
    1379 
    1380                                 memcpy(pEntry->pbData + OffDiff, pbSegBuf, cbCopy);
    1381 
    1382                                 ADVANCE_SEGMENT_BUFFER(cbCopy);
    1383 
    1384                                 cbToWrite-= cbCopy;
    1385                                 off      += cbCopy;
    1386                                 OffDiff  += cbCopy;
    1387                                 ASMAtomicSubS32(&pTask->cbTransferLeft, cbCopy);
    1388                             }
    1389 
    1390                             pEntry->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY;
    1391                             pdmacFileCacheWriteToEndpoint(pEntry);
    1392                         }
     1364                        STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred);
     1365                        RTSemRWReleaseWrite(pEndpointCache->SemRWEntries);
    13931366                    }
    13941367                    else
     
    14551428                }
    14561429
     1430                STAM_COUNTER_INC(&pEndpointCache->StatWriteDeferred);
    14571431                pdmacFileCacheReadFromEndpoint(pEntry);
    14581432            }
     
    15261500                }
    15271501
     1502                pEntryNew->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY;
    15281503                pdmacFileCacheWriteToEndpoint(pEntryNew);
    15291504                pdmacFileEpCacheEntryRelease(pEntryNew); /* it is protected by the I/O in progress flag now. */
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r23975 r24278  
    308308    /** Pointer to the gobal cache data */
    309309    PPDMACFILECACHEGLOBAL pCache;
     310
     311#ifdef VBOX_WITH_STATISTICS
     312    /** Number of times a write was deferred because the cache entry was still in progress */
     313    STAMCOUNTER           StatWriteDeferred;
     314#endif
    310315} PDMACFILEENDPOINTCACHE, *PPDMACFILEENDPOINTCACHE;
    311316
     
    423428    /** Blocking event type */
    424429    PDMACEPFILEBLOCKINGEVENT               enmBlockingEvent;
     430
     431#ifdef VBOX_WITH_STATISTICS
     432    /** Time spend in a read. */
     433    STAMPROFILEADV                         StatRead;
     434    /** Time spend in a write. */
     435    STAMPROFILEADV                         StatWrite;
     436#endif
     437
    425438    /** Additional data needed for the event types. */
    426439    union
Note: See TracChangeset for help on using the changeset viewer.

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