Changeset 46447 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jun 7, 2013 7:09:25 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/STAM.cpp
r46443 r46447 748 748 if (!iDiff) 749 749 { 750 *piChild = iChild; 750 if (piChild) 751 *piChild = iChild; 751 752 return pParent->papChildren[iChild]; 752 753 } … … 758 759 if (iFirst >= iEnd) 759 760 { 760 *piChild = iChild; 761 if (piChild) 762 *piChild = iChild; 761 763 break; 762 764 } … … 766 768 if (iChild == iFirst) 767 769 { 768 *piChild = iChild ? iChild - 1 : 0; 770 if (piChild) 771 *piChild = iChild ? iChild - 1 : 0; 769 772 break; 770 773 } … … 786 789 if (iDiff <= 0) 787 790 { 788 *piChild = iChild; 791 if (piChild) 792 *piChild = iChild; 789 793 return !iDiff ? pParent->papChildren[iChild] : NULL; 790 794 } 791 795 } 792 *piChild = 0; 796 if (piChild) 797 *piChild = 0; 793 798 return NULL; 794 799 } … … 796 801 797 802 /** 798 * Find the next sample descript ionnode.799 * 800 * This is for use with insertion in the big list .801 * 802 * @returns Pointer to the next sample descript ion. NULL if not found (i.e.803 * Find the next sample descriptor node. 804 * 805 * This is for use with insertion in the big list and pattern range lookups. 806 * 807 * @returns Pointer to the next sample descriptor. NULL if not found (i.e. 803 808 * we're at the end of the list). 804 809 * @param pLookup The current node. … … 835 840 else 836 841 { 837 /* One level up, resuming after the current. */ 842 /* 843 * One level up, resuming after the current. 844 */ 838 845 iCur = pCur->iParent + 1; 839 846 pCur = pCur->pParent; … … 842 849 } 843 850 } 851 } 852 853 854 /** 855 * Look up a sample descriptor by name. 856 * 857 * @returns Pointer to a sample descriptor. 858 * @param pRoot The root node. 859 * @param pszName The name to lookup. 860 */ 861 static PSTAMDESC stamR3LookupFindDesc(PSTAMLOOKUP pRoot, const char *pszName) 862 { 863 Assert(!pRoot->pParent); 864 while (*pszName++ == '/') 865 { 866 const char *pszEnd = strchr(pszName, '/'); 867 uint32_t cch = pszEnd ? pszEnd - pszName : strlen(pszName); 868 PSTAMLOOKUP pChild = stamR3LookupFindChild(pRoot, pszName, cch, NULL); 869 if (!pChild) 870 break; 871 if (!pszEnd) 872 return pChild->pDesc; 873 pszName = pszEnd; 874 pRoot = pChild; 875 } 876 877 return NULL; 878 } 879 880 881 /** 882 * Finds the first sample descriptor for a given lookup range. 883 * 884 * This is for pattern range lookups. 885 * 886 * @returns Pointer to the first descriptor. 887 * @param pFirst The first node in the range. 888 * @param pLast The last node in the range. 889 */ 890 static PSTAMDESC stamR3LookupFindFirstDescForRange(PSTAMLOOKUP pFirst, PSTAMLOOKUP pLast) 891 { 892 if (pFirst->pDesc) 893 return pFirst->pDesc; 894 895 PSTAMLOOKUP pCur = pFirst; 896 uint32_t iCur = 0; 897 for (;;) 898 { 899 uint32_t cChildren = pCur->cChildren; 900 if (iCur < pCur->cChildren) 901 { 902 /* 903 * Check all children. 904 */ 905 PSTAMLOOKUP *papChildren = pCur->papChildren; 906 do 907 { 908 PSTAMLOOKUP pChild = pCur->papChildren[iCur]; 909 if (pChild->pDesc) 910 return pChild->pDesc; 911 if (pChild->cChildren > 0) 912 { 913 /* One level down. */ 914 iCur = 0; 915 pCur = pChild; 916 break; 917 } 918 if (pChild == pLast) 919 return NULL; 920 } while (++iCur < cChildren); 921 } 922 else 923 { 924 /* 925 * One level up, checking current and its 'older' sibilings. 926 */ 927 if (pCur == pLast) 928 return NULL; 929 iCur = pCur->iParent + 1; 930 pCur = pCur->pParent; 931 if (!pCur) 932 break; 933 } 934 } 935 936 return NULL; 937 } 938 939 940 /** 941 * Finds the first sample descriptor for a given lookup range. 942 * 943 * This is for pattern range lookups. 944 * 945 * @returns Pointer to the first descriptor. 946 * @param pFirst The first node in the range. 947 * @param pLast The last node in the range. 948 */ 949 static PSTAMDESC stamR3LookupFindLastDescForRange(PSTAMLOOKUP pFirst, PSTAMLOOKUP pLast) 950 { 951 PSTAMLOOKUP pCur = pLast; 952 uint32_t iCur = pCur->cChildren - 1; 953 for (;;) 954 { 955 if (iCur < pCur->cChildren) 956 { 957 /* 958 * Check children backwards, depth first. 959 */ 960 PSTAMLOOKUP *papChildren = pCur->papChildren; 961 do 962 { 963 PSTAMLOOKUP pChild = pCur->papChildren[iCur]; 964 if (pChild->cChildren > 0) 965 { 966 /* One level down. */ 967 iCur = pChild->cChildren - 1; 968 pCur = pChild; 969 break; 970 } 971 972 if (pChild->pDesc) 973 return pChild->pDesc; 974 if (pChild == pFirst) 975 return NULL; 976 } while (iCur-- > 0); /* (underflow handled above) */ 977 } 978 else 979 { 980 /* 981 * One level up, checking current and its 'older' sibilings. 982 */ 983 if (pCur->pDesc) 984 return pCur->pDesc; 985 if (pCur == pFirst) 986 return NULL; 987 iCur = pCur->iParent - 1; /* (underflow handled above) */ 988 pCur = pCur->pParent; 989 if (!pCur) 990 break; 991 } 992 } 993 994 return NULL; 995 } 996 997 998 /** 999 * Look up the first and last descriptors for a (single) pattern expression. 1000 * 1001 * This is used to optimize pattern enumerations and doesn't have to return 100% 1002 * accurate results if that costs too much. 1003 * 1004 * @returns Pointer to the first descriptor in the range. 1005 * @param pRoot The root node. 1006 * @param pList The descriptor list anchor. 1007 * @param pszPat The name patter to lookup. 1008 * @param ppLastDesc Where to store the address of the last 1009 * descriptor (approximate). 1010 */ 1011 static PSTAMDESC stamR3LookupFindPatternDescRange(PSTAMLOOKUP pRoot, PRTLISTANCHOR pList, const char *pszPat, 1012 PSTAMDESC *ppLastDesc) 1013 { 1014 Assert(!pRoot->pParent); 1015 1016 /* 1017 * If there is an early enough wildcard, the whole list needs to be searched. 1018 */ 1019 if ( pszPat[0] == '*' || pszPat[0] == '?' 1020 || pszPat[1] == '*' || pszPat[1] == '?') 1021 { 1022 *ppLastDesc = RTListGetLast(pList, STAMDESC, ListEntry); 1023 return RTListGetFirst(pList, STAMDESC, ListEntry); 1024 } 1025 1026 /* 1027 * All statistics starts with a slash. 1028 */ 1029 while ( *pszPat++ == '/' 1030 && pRoot->cDescsInTree > 0 1031 && pRoot->cChildren > 0) 1032 { 1033 const char *pszEnd = strchr(pszPat, '/'); 1034 uint32_t cch = pszEnd ? pszEnd - pszPat : strlen(pszPat); 1035 if (!cch) 1036 break; 1037 1038 const char *pszPat1 = (const char *)memchr(pszPat, '*', cch); 1039 const char *pszPat2 = (const char *)memchr(pszPat, '?', cch); 1040 if (pszPat1 || pszPat2) 1041 { 1042 /* We've narrowed it down to a sub-tree now. */ 1043 PSTAMLOOKUP pFirst = pRoot->papChildren[0]; 1044 PSTAMLOOKUP pLast = pRoot->papChildren[pRoot->cChildren - 1]; 1045 /** @todo narrow the range further if both pszPat1/2 != pszPat. */ 1046 1047 *ppLastDesc = stamR3LookupFindLastDescForRange(pFirst, pLast); 1048 return stamR3LookupFindFirstDescForRange(pFirst, pLast); 1049 } 1050 1051 PSTAMLOOKUP pChild = stamR3LookupFindChild(pRoot, pszPat, cch, NULL); 1052 if (!pChild) 1053 break; 1054 1055 /* Advance */ 1056 if (!pszEnd) 1057 return *ppLastDesc = pChild->pDesc; 1058 pszPat = pszEnd; 1059 pRoot = pChild; 1060 } 1061 1062 /* No match. */ 1063 *ppLastDesc = NULL; 1064 return NULL; 844 1065 } 845 1066 … … 2036 2257 2037 2258 /** 2259 * Checks if the string contains a pattern expression or not. 2260 * 2261 * @returns true / false. 2262 * @param pszPat The potential pattern. 2263 */ 2264 static bool stamR3IsPattern(const char *pszPat) 2265 { 2266 return strchr(pszPat, '*') != NULL 2267 || strchr(pszPat, '?') != NULL; 2268 } 2269 2270 2271 /** 2038 2272 * Match a name against an array of patterns. 2039 2273 * … … 2133 2367 { 2134 2368 int rc = VINF_SUCCESS; 2135 2136 /* 2137 * All 2369 PSTAMDESC pCur; 2370 2371 /* 2372 * All. 2138 2373 */ 2139 2374 if (!pszPat || !*pszPat || !strcmp(pszPat, "*")) … … 2143 2378 2144 2379 STAM_LOCK_RD(pUVM); 2145 PSTAMDESC pCur;2146 2380 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 2147 2381 { … … 2162 2396 2163 2397 STAM_LOCK_RD(pUVM); 2164 /** @todo This needs to be optimized since the GUI is using this path for the VM info dialog. 2165 * Note that it's doing exact matching. Organizing the samples in a tree would speed up thing 2166 * no end (at least for debug and profile builds). */ 2167 PSTAMDESC pCur; 2398 #ifdef STAM_WITH_LOOKUP_TREE 2399 if (!stamR3IsPattern(pszPat)) 2400 { 2401 pCur = stamR3LookupFindDesc(pUVM->stam.s.pRoot, pszPat); 2402 if (pCur) 2403 rc = pfnCallback(pCur, pvArg); 2404 } 2405 else 2406 { 2407 PSTAMDESC pLast; 2408 pCur = stamR3LookupFindPatternDescRange(pUVM->stam.s.pRoot, &pUVM->stam.s.List, pszPat, &pLast); 2409 if (pCur) 2410 { 2411 for (;;) 2412 { 2413 if (RTStrSimplePatternMatch(pszPat, pCur->pszName)) 2414 { 2415 rc = pfnCallback(pCur, pvArg); 2416 if (rc) 2417 break; 2418 } 2419 if (pCur == pLast) 2420 break; 2421 pCur = RTListNodeGetNext(&pCur->ListEntry, STAMDESC, ListEntry); 2422 } 2423 Assert(pLast); 2424 } 2425 else 2426 Assert(!pLast); 2427 2428 } 2429 #else 2168 2430 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 2169 2431 { … … 2175 2437 } 2176 2438 } 2439 #endif 2177 2440 STAM_UNLOCK_RD(pUVM); 2178 2441 } … … 2200 2463 STAM_LOCK_RD(pUVM); 2201 2464 unsigned iExpression = 0; 2202 PSTAMDESC pCur;2203 2465 RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry) 2204 2466 {
Note:
See TracChangeset
for help on using the changeset viewer.