VirtualBox

Changeset 46443 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jun 7, 2013 4:18:29 PM (12 years ago)
Author:
vboxsync
Message:

STAM: Registration optimizations.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/STAM.cpp

    r46439 r46443  
    5959#include <iprt/assert.h>
    6060#include <iprt/asm.h>
    61 #include <iprt/alloc.h>
     61#include <iprt/mem.h>
    6262#include <iprt/stream.h>
    6363#include <iprt/string.h>
     
    133133*   Internal Functions                                                         *
    134134*******************************************************************************/
     135#ifdef STAM_WITH_LOOKUP_TREE
     136static void                 stamR3LookupDestroyTree(PSTAMLOOKUP pRoot);
     137#endif
    135138static int                  stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    136139                                            STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
     
    272275
    273276    /*
    274      * Initialize the read/write lock.
     277     * Initialize the read/write lock and list.
    275278     */
    276279    int rc = RTSemRWCreate(&pUVM->stam.s.RWSem);
    277280    AssertRCReturn(rc, rc);
     281
     282    RTListInit(&pUVM->stam.s.List);
     283
     284#ifdef STAM_WITH_LOOKUP_TREE
     285    /*
     286     * Initialize the root node.
     287     */
     288    PSTAMLOOKUP pRoot = (PSTAMLOOKUP)RTMemAlloc(sizeof(STAMLOOKUP));
     289    if (!pRoot)
     290    {
     291        RTSemRWDestroy(pUVM->stam.s.RWSem);
     292        pUVM->stam.s.RWSem = NIL_RTSEMRW;
     293        return VERR_NO_MEMORY;
     294    }
     295    pRoot->pParent      = NULL;
     296    pRoot->papChildren   = NULL;
     297    pRoot->pDesc        = NULL;
     298    pRoot->cDescsInTree = 0;
     299    pRoot->cChildren    = 0;
     300    pRoot->iParent      = UINT16_MAX;
     301    pRoot->off          = 0;
     302    pRoot->cch          = 0;
     303    pRoot->szName[0]    = '\0';
     304
     305    pUVM->stam.s.pRoot = pRoot;
     306#endif
     307
    278308
    279309    /*
     
    309339     * Free used memory and the RWLock.
    310340     */
    311     PSTAMDESC pCur = pUVM->stam.s.pHead;
    312     while (pCur)
    313     {
    314         void *pvFree = pCur;
    315         pCur = pCur->pNext;
    316         RTMemFree(pvFree);
    317     }
    318     pUVM->stam.s.pHead = NULL;
     341    PSTAMDESC pCur, pNext;
     342    RTListForEachSafe(&pUVM->stam.s.List, pCur, pNext, STAMDESC, ListEntry)
     343    {
     344#ifdef STAM_WITH_LOOKUP_TREE
     345        pCur->pLookup->pDesc = NULL;
     346#endif
     347        RTMemFree(pCur);
     348    }
     349
     350#ifdef STAM_WITH_LOOKUP_TREE
     351    stamR3LookupDestroyTree(pUVM->stam.s.pRoot);
     352    pUVM->stam.s.pRoot = NULL;
     353#endif
    319354
    320355    Assert(pUVM->stam.s.RWSem != NIL_RTSEMRW);
     
    577612}
    578613#endif /* VBOX_STRICT */
     614
     615
     616#ifdef STAM_WITH_LOOKUP_TREE
     617
     618/**
     619 * Compares a lookup node with a name.
     620 *
     621 * @returns like strcmp and memcmp.
     622 * @param   pNode               The lookup node.
     623 * @param   pchName             The name, not necessarily terminated.
     624 * @param   cchName             The length of the name.
     625 */
     626DECL_FORCE_INLINE(int) stamR3LookupCmp(PSTAMLOOKUP pNode, const char *pchName, uint32_t cchName)
     627{
     628    uint32_t cchComp = RT_MIN(pNode->cch, cchName);
     629    int iDiff = memcmp(pNode->szName, pchName, cchComp);
     630    if (!iDiff && pNode->cch != cchName)
     631        iDiff = pNode->cch > cchName ? 2 : -2;
     632    return iDiff;
     633}
     634
     635
     636/**
     637 * Creates a new lookup child node.
     638 *
     639 * @returns Pointer to the newly created lookup node.
     640 * @param   pParent             The parent node.
     641 * @param   pchName             The name (not necessarily terminated).
     642 * @param   cchName             The length of the name.
     643 * @param   offName             The offset of the node in a path.
     644 * @param   iChild              Child index of a node that's before the one
     645 *                              we're inserting (returned by
     646 *                              stamR3LookupFindChild).
     647 */
     648static PSTAMLOOKUP stamR3LookupNewChild(PSTAMLOOKUP pParent, const char *pchName, uint32_t cchName, uint32_t offName,
     649                                        uint32_t iChild)
     650{
     651    Assert(cchName <= UINT8_MAX);
     652    Assert(offName <= UINT8_MAX);
     653    Assert(iChild  <  UINT16_MAX);
     654
     655    /*
     656     * Allocate a new entry.
     657     */
     658    PSTAMLOOKUP pNew = (PSTAMLOOKUP)RTMemAlloc(RT_OFFSETOF(STAMLOOKUP, szName[cchName + 1]));
     659    if (!pNew)
     660        return NULL;
     661    pNew->pParent       = pParent;
     662    pNew->papChildren    = NULL;
     663    pNew->pDesc         = NULL;
     664    pNew->cDescsInTree  = 0;
     665    pNew->cChildren     = 0;
     666    pNew->cch           = (uint16_t)cchName;
     667    pNew->off           = (uint16_t)offName;
     668    memcpy(pNew->szName, pchName, cchName);
     669    pNew->szName[cchName] = '\0';
     670
     671    /*
     672     * Reallocate the array?
     673     */
     674    if (RT_IS_POWER_OF_TWO(pParent->cChildren))
     675    {
     676        uint32_t cNew = pParent->cChildren ? (uint32_t)pParent->cChildren * 2 : 8;
     677        AssertReturnStmt(cNew <= 0x8000, RTMemFree(pNew), NULL);
     678        void *pvNew = RTMemRealloc(pParent->papChildren, cNew * sizeof(pParent->papChildren[0]));
     679        if (!pvNew)
     680        {
     681            RTMemFree(pNew);
     682            return NULL;
     683        }
     684        pParent->papChildren = (PSTAMLOOKUP *)pvNew;
     685    }
     686
     687    /*
     688     * Find the exact insertion point using iChild as a very good clue from
     689     * the find function.
     690     */
     691    if (!pParent->cChildren)
     692        iChild = 0;
     693    else
     694    {
     695        if (iChild >= pParent->cChildren)
     696            iChild = pParent->cChildren - 1;
     697        while (   iChild < pParent->cChildren
     698               && stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName) < 0)
     699            iChild++;
     700    }
     701
     702    /*
     703     * Insert it.
     704     */
     705    if (iChild < pParent->cChildren)
     706    {
     707        /* Do shift. */
     708        uint32_t i = pParent->cChildren;
     709        while (i > iChild)
     710        {
     711            PSTAMLOOKUP pNode = pParent->papChildren[i - 1];
     712            pParent->papChildren[i] = pNode;
     713            pNode->iParent = i;
     714            i--;
     715        }
     716    }
     717
     718    pNew->iParent = iChild;
     719    pParent->papChildren[iChild] = pNew;
     720    pParent->cChildren++;
     721
     722    return pNew;
     723}
     724
     725
     726/**
     727 * Looks up a child.
     728 *
     729 * @returns Pointer to child node if found, NULL if not.
     730 * @param   pParent             The parent node.
     731 * @param   pchName             The name (not necessarily terminated).
     732 * @param   cchName             The length of the name.
     733 * @param   piChild             Where to store a child index suitable for
     734 *                              passing to stamR3LookupNewChild when NULL is
     735 *                              returned.
     736 */
     737static PSTAMLOOKUP stamR3LookupFindChild(PSTAMLOOKUP pParent, const char *pchName, uint32_t cchName, uint32_t *piChild)
     738{
     739    uint32_t iChild = pParent->cChildren;
     740    if (iChild > 4)
     741    {
     742        uint32_t iFirst = 0;
     743        uint32_t iEnd   = iChild;
     744        iChild /= 2;
     745        for (;;)
     746        {
     747            int iDiff = stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName);
     748            if (!iDiff)
     749            {
     750                *piChild = iChild;
     751                return pParent->papChildren[iChild];
     752            }
     753
     754            /* Split. */
     755            if (iDiff < 0)
     756            {
     757                iFirst = iChild + 1;
     758                if (iFirst >= iEnd)
     759                {
     760                    *piChild = iChild;
     761                    break;
     762                }
     763            }
     764            else
     765            {
     766                if (iChild == iFirst)
     767                {
     768                    *piChild = iChild ? iChild - 1 : 0;
     769                    break;
     770                }
     771                iEnd = iChild;
     772            }
     773
     774            /* Calc next child. */
     775            iChild = (iEnd - iFirst) / 2 + iFirst;
     776        }
     777        return NULL;
     778    }
     779
     780    /*
     781     * Linear search.
     782     */
     783    while (iChild-- > 0)
     784    {
     785        int iDiff = stamR3LookupCmp(pParent->papChildren[iChild], pchName, cchName);
     786        if (iDiff <= 0)
     787        {
     788            *piChild = iChild;
     789            return !iDiff ? pParent->papChildren[iChild] : NULL;
     790        }
     791    }
     792    *piChild = 0;
     793    return NULL;
     794}
     795
     796
     797/**
     798 * Find the next sample description node.
     799 *
     800 * This is for use with insertion in the big list.
     801 *
     802 * @returns Pointer to the next sample description. NULL if not found (i.e.
     803 *          we're at the end of the list).
     804 * @param   pLookup             The current node.
     805 */
     806static PSTAMDESC stamR3LookupFindNextWithDesc(PSTAMLOOKUP pLookup)
     807{
     808    Assert(!pLookup->pDesc);
     809    PSTAMLOOKUP pCur = pLookup;
     810    uint32_t    iCur = 0;
     811    for (;;)
     812    {
     813        /*
     814         * Check all children.
     815         */
     816        uint32_t cChildren = pCur->cChildren;
     817        if (iCur < cChildren)
     818        {
     819            PSTAMLOOKUP *papChildren = pCur->papChildren;
     820            do
     821            {
     822                PSTAMLOOKUP pChild = pCur->papChildren[iCur];
     823                if (pChild->pDesc)
     824                    return pChild->pDesc;
     825
     826                if (pChild->cChildren > 0)
     827                {
     828                    /* One level down. */
     829                    iCur = 0;
     830                    pCur = pChild;
     831                    break;
     832                }
     833            } while (++iCur < cChildren);
     834        }
     835        else
     836        {
     837            /* One level up, resuming after the current. */
     838            iCur = pCur->iParent + 1;
     839            pCur = pCur->pParent;
     840            if (!pCur)
     841                return NULL;
     842        }
     843    }
     844}
     845
     846
     847/**
     848 * Increments the cDescInTree member of the given node an all ancestors.
     849 *
     850 * @param   pLookup             The lookup node.
     851 */
     852static void stamR3LookupIncUsage(PSTAMLOOKUP pLookup)
     853{
     854    Assert(pLookup->pDesc);
     855
     856    PSTAMLOOKUP pCur = pLookup;
     857    while (pCur != NULL)
     858    {
     859        pCur->cDescsInTree++;
     860        pCur = pCur->pParent;
     861    }
     862}
     863
     864
     865/**
     866 * Descrements the cDescInTree member of the given node an all ancestors.
     867 *
     868 * @param   pLookup             The lookup node.
     869 */
     870static void stamR3LookupDecUsage(PSTAMLOOKUP pLookup)
     871{
     872    Assert(!pLookup->pDesc);
     873
     874    PSTAMLOOKUP pCur = pLookup;
     875    while (pCur != NULL)
     876    {
     877        Assert(pCur->cDescsInTree > 0);
     878        pCur->cDescsInTree--;
     879        pCur = pCur->pParent;
     880    }
     881}
     882
     883
     884/**
     885 * Frees empty lookup nodes if it's worth it.
     886 *
     887 * @param   pLookup             The lookup node.
     888 */
     889static void stamR3LookupMaybeFree(PSTAMLOOKUP pLookup)
     890{
     891    Assert(!pLookup->pDesc);
     892
     893    /*
     894     * Free between two and three levels of nodes.  Freeing too much most
     895     * likely wasted effort since we're either going to repopluate the tree
     896     * or quit the whole thing.
     897     */
     898    if (pLookup->cDescsInTree > 0)
     899        return;
     900
     901    PSTAMLOOKUP pCur = pLookup->pParent;
     902    if (!pCur)
     903        return;
     904    if (pCur->cDescsInTree > 0)
     905        return;
     906    PSTAMLOOKUP pParent = pCur->pParent;
     907    if (pParent)
     908        return;
     909
     910    if (pParent->cDescsInTree == 0 && pParent->pParent)
     911    {
     912        pCur = pParent;
     913        pParent = pCur->pParent;
     914    }
     915
     916    /*
     917     * Remove pCur from pParent.
     918     */
     919    PSTAMLOOKUP *papChildren = pParent->papChildren;
     920    uint32_t     cChildren   = --pParent->cChildren;
     921    for (uint32_t i = pCur->iParent; i < cChildren; i++)
     922    {
     923        PSTAMLOOKUP pChild = papChildren[i + 1];
     924        pChild->iParent = i;
     925        papChildren[i] = pChild;
     926    }
     927    pCur->pParent = NULL;
     928
     929    /*
     930     * Destroy pCur.
     931     */
     932    stamR3LookupDestroyTree(pCur);
     933}
     934
     935
     936/**
     937 * Destroys a lookup tree.
     938 *
     939 * This is used by STAMR3Term as well as stamR3LookupMaybeFree.
     940 *
     941 * @param   pRoot               The root of the tree (must have no parent).
     942 */
     943static void stamR3LookupDestroyTree(PSTAMLOOKUP pRoot)
     944{
     945    Assert(pRoot); Assert(!pRoot->pParent);
     946    PSTAMLOOKUP pLookup = pRoot;
     947    for (;;)
     948    {
     949        uint32_t i = pLookup->cChildren;
     950        if (i > 0)
     951        {
     952            /*
     953             * Push child (with leaf optimization).
     954             */
     955            PSTAMLOOKUP pChild = pLookup->papChildren[--i];
     956            if (pChild->cChildren != 0)
     957                pLookup = pChild;
     958            else
     959            {
     960                /* free leaves. */
     961                for (;;)
     962                {
     963                    if (pChild->papChildren)
     964                    {
     965                        RTMemFree(pChild->papChildren);
     966                        pChild->papChildren = NULL;
     967                    }
     968                    RTMemFree(pChild);
     969
     970                    /* next */
     971                    if (i == 0)
     972                    {
     973                        pLookup->papChildren = 0;
     974                        break;
     975                    }
     976                    pChild = pLookup->papChildren[--i];
     977                    if (pChild->cChildren != 0)
     978                    {
     979                        pLookup->cChildren = i + 1;
     980                        pLookup = pChild;
     981                        break;
     982                    }
     983                }
     984            }
     985        }
     986        else
     987        {
     988            /*
     989             * Pop and free current.
     990             */
     991            Assert(!pLookup->pDesc);
     992
     993            PSTAMLOOKUP pParent = pLookup->pParent;
     994            RTMemFree(pLookup->papChildren);
     995            pLookup->papChildren = NULL;
     996            RTMemFree(pLookup);
     997
     998            pLookup = pParent;
     999            if (!pLookup)
     1000                break;
     1001            pLookup->cChildren--;
     1002        }
     1003    }
     1004}
     1005
     1006#endif /* STAM_WITH_LOOKUP_TREE */
     1007
    5791008
    5801009
     
    5981027                           STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
    5991028{
     1029    AssertReturn(pszName[0] == '/', VERR_INVALID_NAME);
     1030    AssertReturn(pszName[1] != '/' && pszName[1], VERR_INVALID_NAME);
     1031    uint32_t const cchName = (uint32_t)strlen(pszName);
     1032    AssertReturn(cchName < 256, VERR_OUT_OF_RANGE);
     1033    AssertReturn(pszName[cchName - 1] != '/', VERR_INVALID_NAME);
     1034    AssertReturn(memchr(pszName, '\\', cchName) == NULL, VERR_INVALID_NAME);
     1035
    6001036    STAM_LOCK_WR(pUVM);
    6011037
    6021038    /*
    603      * Check if exists.
    604      */
    605 #if 0
    606     PSTAMDESC   pPrev = pUVM->stam.s.pHint;
    607     PSTAMDESC   pCur  = pPrev ? pPrev->pNext : NULL;
    608     if (!pCur || strcmp(pCur->pszName, pszName) > 0)
    609     {
    610         pPrev = NULL;
    611         pCur  = pUVM->stam.s.pHead;
    612     }
     1039     * Look up the tree location, populating the lookup tree as we walk it.
     1040     */
     1041#ifdef STAM_WITH_LOOKUP_TREE
     1042    PSTAMLOOKUP pLookup = pUVM->stam.s.pRoot; Assert(pLookup);
     1043    uint32_t    offName = 1;
     1044    for (;;)
     1045    {
     1046        /* Get the next part of the path. */
     1047        const char *pszStart = &pszName[offName];
     1048        const char *pszEnd   = strchr(pszStart, '/');
     1049        uint32_t    cch      = pszEnd ? (uint32_t)(pszEnd - pszStart) : cchName - offName;
     1050        if (cch == 0)
     1051        {
     1052            STAM_UNLOCK_WR(pUVM);
     1053            AssertMsgFailed(("No double or trailing slashes are allowed: '%s'\n", pszName));
     1054            return VERR_INVALID_NAME;
     1055        }
     1056
     1057        /* Do the looking up. */
     1058        uint32_t    iChild = 0;
     1059        PSTAMLOOKUP pChild = stamR3LookupFindChild(pLookup, pszStart, cch, &iChild);
     1060        if (!pChild)
     1061        {
     1062            pChild = stamR3LookupNewChild(pLookup, pszStart, cch, offName, iChild);
     1063            if (!pChild)
     1064            {
     1065                STAM_UNLOCK_WR(pUVM);
     1066                return VERR_NO_MEMORY;
     1067            }
     1068        }
     1069
     1070        /* Advance. */
     1071        pLookup = pChild;
     1072        if (!pszEnd)
     1073            break;
     1074        offName += cch + 1;
     1075    }
     1076    if (pLookup->pDesc)
     1077    {
     1078        STAM_UNLOCK_WR(pUVM);
     1079        AssertMsgFailed(("Duplicate sample name: %s\n", pszName));
     1080        return VERR_ALREADY_EXISTS;
     1081    }
     1082
     1083    PSTAMDESC pCur = stamR3LookupFindNextWithDesc(pLookup);
     1084
    6131085#else
    614     PSTAMDESC   pPrev = NULL;
    615     PSTAMDESC   pCur  = pUVM->stam.s.pHead;
    616 #endif
    617     while (pCur)
     1086    PSTAMDESC pCur;
     1087    RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
    6181088    {
    6191089        int iDiff = strcmp(pCur->pszName, pszName);
     
    6281098            return VERR_ALREADY_EXISTS;
    6291099        }
    630 
    631         /* next */
    632         pPrev = pCur;
    633         pCur = pCur->pNext;
    634     }
    635     pUVM->stam.s.pHint = pPrev;
     1100    }
     1101#endif
    6361102
    6371103    /*
     
    6401106     * Problematic chars are: !"#$%&'()*+,-.
    6411107     */
     1108#ifdef VBOX_STRICT
    6421109    Assert(pszName[0] == '/');
    643     if (pPrev)
    644         Assert(stamR3SlashCompare(pPrev->pszName, pszName) < 0);
    645     if (pCur)
    646         Assert(stamR3SlashCompare(pCur->pszName, pszName) > 0);
    647 
    648 #ifdef VBOX_STRICT
     1110    PSTAMDESC pPrev = pCur
     1111                    ? RTListGetPrev(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
     1112                    : RTListGetLast(&pUVM->stam.s.List, STAMDESC, ListEntry);
     1113    Assert(!pPrev || strcmp(pszName, pPrev->pszName) > 0);
     1114    Assert(!pCur  || strcmp(pszName, pCur->pszName)  < 0);
     1115    Assert(!pPrev || stamR3SlashCompare(pPrev->pszName, pszName) < 0);
     1116    Assert(!pCur  || stamR3SlashCompare(pCur->pszName, pszName) > 0);
     1117
    6491118    /*
    6501119     * Check alignment requirements.
     
    7011170     */
    7021171    int rc;
    703     size_t cchName = strlen(pszName) + 1;
    704     size_t cchDesc = pszDesc ? strlen(pszDesc) + 1 : 0;
    705     PSTAMDESC pNew = (PSTAMDESC)RTMemAlloc(sizeof(*pNew) + cchName + cchDesc);
     1172    size_t cbDesc = pszDesc ? strlen(pszDesc) + 1 : 0;
     1173    PSTAMDESC pNew = (PSTAMDESC)RTMemAlloc(sizeof(*pNew) + cchName + 1 + cbDesc);
    7061174    if (pNew)
    7071175    {
    708         pNew->pszName       = (char *)memcpy((char *)(pNew + 1), pszName, cchName);
     1176        pNew->pszName       = (char *)memcpy((char *)(pNew + 1), pszName, cchName + 1);
    7091177        pNew->enmType       = enmType;
    7101178        pNew->enmVisibility = enmVisibility;
     
    7201188        pNew->pszDesc       = NULL;
    7211189        if (pszDesc)
    722             pNew->pszDesc   = (char *)memcpy((char *)(pNew + 1) + cchName,  pszDesc,  cchDesc);
    723 
    724         pNew->pNext         = pCur;
    725         if (pPrev)
    726             pPrev->pNext    = pNew;
     1190            pNew->pszDesc   = (char *)memcpy((char *)(pNew + 1) + cchName + 1, pszDesc, cbDesc);
     1191
     1192        if (pCur)
     1193            RTListNodeInsertBefore(&pCur->ListEntry, &pNew->ListEntry);
    7271194        else
    728             pUVM->stam.s.pHead = pNew;
     1195            RTListAppend(&pUVM->stam.s.List, &pNew->ListEntry);
     1196
     1197#ifdef STAM_WITH_LOOKUP_TREE
     1198        pNew->pLookup       = pLookup;
     1199        pLookup->pDesc      = pNew;
     1200        stamR3LookupIncUsage(pLookup);
     1201#endif
    7291202
    7301203        stamR3ResetOne(pNew, pUVM->pVM);
     
    7591232     */
    7601233    int         rc = VERR_INVALID_HANDLE;
    761     PSTAMDESC   pPrev = NULL;
    762     PSTAMDESC   pCur = pUVM->stam.s.pHead;
    763     while (pCur)
     1234    PSTAMDESC   pCur, pNext;
     1235    RTListForEachSafe(&pUVM->stam.s.List, pCur, pNext, STAMDESC, ListEntry)
    7641236    {
    7651237        if (pCur->u.pv == pvSample)
    7661238        {
    767             void *pvFree = pCur;
    768             pCur = pCur->pNext;
    769             if (pPrev)
    770                 pPrev->pNext = pCur;
    771             else
    772                 pUVM->stam.s.pHead = pCur;
    773 
    774             RTMemFree(pvFree);
     1239            RTListNodeRemove(&pCur->ListEntry);
     1240#ifdef STAM_WITH_LOOKUP_TREE
     1241            pCur->pLookup->pDesc = NULL; /** @todo free lookup nodes once it's working. */
     1242            stamR3LookupDecUsage(pCur->pLookup);
     1243            stamR3LookupMaybeFree(pCur->pLookup);
     1244#endif
     1245            RTMemFree(pCur);
    7751246            rc = VINF_SUCCESS;
    776             continue;
    777         }
    778 
    779         /* next */
    780         pPrev = pCur;
    781         pCur = pCur->pNext;
     1247        }
    7821248    }
    7831249
     
    16772143
    16782144        STAM_LOCK_RD(pUVM);
    1679         PSTAMDESC pCur = pUVM->stam.s.pHead;
    1680         while (pCur)
     2145        PSTAMDESC pCur;
     2146        RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
    16812147        {
    16822148            rc = pfnCallback(pCur, pvArg);
    16832149            if (rc)
    16842150                break;
    1685 
    1686             /* next */
    1687             pCur = pCur->pNext;
    16882151        }
    16892152        STAM_UNLOCK_RD(pUVM);
     
    17022165         * Note that it's doing exact matching. Organizing the samples in a tree would speed up thing
    17032166         * no end (at least for debug and profile builds). */
    1704         for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext)
     2167        PSTAMDESC pCur;
     2168        RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
     2169        {
    17052170            if (RTStrSimplePatternMatch(pszPat, pCur->pszName))
    17062171            {
     
    17092174                    break;
    17102175            }
     2176        }
    17112177        STAM_UNLOCK_RD(pUVM);
    17122178    }
     
    17342200        STAM_LOCK_RD(pUVM);
    17352201        unsigned iExpression = 0;
    1736         for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext)
     2202        PSTAMDESC pCur;
     2203        RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
     2204        {
    17372205            if (stamR3MultiMatch(papszExpressions, cExpressions, &iExpression, pCur->pszName))
    17382206            {
     
    17412209                    break;
    17422210            }
     2211        }
    17432212        STAM_UNLOCK_RD(pUVM);
    17442213
     
    19332402     */
    19342403    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
    1935     if (!pUVM->stam.s.pHead)
     2404    if (RTListIsEmpty(&pUVM->stam.s.List))
    19362405        return DBGCCmdHlpFail(pCmdHlp, pCmd, "No statistics present");
    19372406
     
    19762445     */
    19772446    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
    1978     if (!pUVM->stam.s.pHead)
     2447    if (RTListIsEmpty(&pUVM->stam.s.List))
    19792448        return DBGCCmdHlpFail(pCmdHlp, pCmd, "No statistics present");
    19802449
  • trunk/src/VBox/VMM/include/STAMInternal.h

    r46438 r46443  
    2424#include <VBox/vmm/gvmm.h>
    2525#include <VBox/vmm/gmm.h>
     26#include <iprt/list.h>
    2627#include <iprt/semaphore.h>
    2728
     
    3637 */
    3738
     39/** Enables the lookup tree.
     40 * This is an optimization for speeding up registration as well as query. */
     41#define STAM_WITH_LOOKUP_TREE
     42
     43
     44/** Pointer to sample descriptor. */
     45typedef struct STAMDESC    *PSTAMDESC;
     46/** Pointer to a sample lookup node. */
     47typedef struct STAMLOOKUP  *PSTAMLOOKUP;
     48
     49/**
     50 * Sample lookup node.
     51 */
     52typedef struct STAMLOOKUP
     53{
     54    /** The parent lookup record. This is NULL for the root node. */
     55    PSTAMLOOKUP         pParent;
     56    /** Array of children (using array for binary searching). */
     57    PSTAMLOOKUP        *papChildren;
     58    /** Pointer to the description node, if any. */
     59    PSTAMDESC           pDesc;
     60    /** Number of decentants with descriptors. (Use for freeing up sub-trees.) */
     61    uint32_t            cDescsInTree;
     62    /** The number of children. */
     63    uint16_t            cChildren;
     64    /** The index in the parent paChildren array. UINT16_MAX for the root node. */
     65    uint16_t            iParent;
     66    /** The path offset. */
     67    uint16_t            off;
     68    /** The size of the path component. */
     69    uint16_t            cch;
     70    /** The name (variable size). */
     71    char                szName[1];
     72} STAMLOOKUP;
     73
     74
    3875/**
    3976 * Sample descriptor.
     
    4178typedef struct STAMDESC
    4279{
    43     /** Pointer to the next sample. */
    44     struct STAMDESC    *pNext;
     80    /** Our entry in the big linear list. */
     81    RTLISTNODE          ListEntry;
     82    /** Pointer to our lookup node. */
     83    PSTAMLOOKUP         pLookup;
    4584    /** Sample name. */
    4685    const char         *pszName;
     
    88127    const char         *pszDesc;
    89128} STAMDESC;
    90 /** Pointer to sample descriptor. */
    91 typedef STAMDESC        *PSTAMDESC;
    92 /** Pointer to const sample descriptor. */
    93 typedef const STAMDESC  *PCSTAMDESC;
    94129
    95130
     
    99134typedef struct STAMUSERPERVM
    100135{
    101     /** Pointer to the first sample. */
    102     R3PTRTYPE(PSTAMDESC)    pHead;
    103     /** Lookup hint (pPrev value). */
    104     R3PTRTYPE(PSTAMDESC)    pHint;
    105     /** RW Lock for the list. */
     136    /** List of samples. */
     137    RTLISTANCHOR            List;
     138    /** Root of the lookup tree. */
     139    PSTAMLOOKUP             pRoot;
     140
     141    /** RW Lock for the list and tree. */
    106142    RTSEMRW                 RWSem;
    107     /** Alignment padding. */
    108     RTR3PTR                 Alignment;
    109143
    110144    /** The copy of the GVMM statistics. */
     
    118152    GMMSTATS                GMMStats;
    119153} STAMUSERPERVM;
     154#ifdef IN_RING3
    120155AssertCompileMemberAlignment(STAMUSERPERVM, GMMStats, 8);
     156#endif
    121157
    122158/** Pointer to the STAM data kept in the UVM. */
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