Changeset 80650 in vbox
- Timestamp:
- Sep 8, 2019 10:33:08 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/STAM.cpp
r80648 r80650 1000 1000 1001 1001 /** 1002 * Finds the first sample descriptor for a given lookup range.1002 * Finds the last sample descriptor for a given lookup range. 1003 1003 * 1004 1004 * This is for pattern range lookups. … … 1133 1133 * 1134 1134 * @returns Pointer to the first descriptor in the range. 1135 * @param pRoot The root node. 1136 * @param pchPrefix The name prefix. 1137 * @param cchPrefix The name prefix length (can be shorter than the 1138 * actual string). 1135 * @param pRoot The root node. 1136 * @param pchPrefix The name prefix. 1137 * @param cchPrefix The name prefix length (can be shorter than the 1138 * actual string). 1139 * @param ppLastDesc Where to store the address of the last descriptor. 1139 1140 * @sa stamR3LookupFindPatternDescRange 1140 1141 */ 1141 static PSTAMDESC stamR3LookupFindFirstByPrefix(PSTAMLOOKUP pRoot, const char *pchPrefix, uint32_t cchPrefix) 1142 { 1142 static PSTAMDESC stamR3LookupFindByPrefixRange(PSTAMLOOKUP pRoot, const char *pchPrefix, uint32_t cchPrefix, 1143 PSTAMDESC *ppLastDesc) 1144 1145 { 1146 *ppLastDesc = NULL; 1143 1147 Assert(!pRoot->pParent); 1144 1145 /* 1146 * All statistics starts with a slash. 1147 */ 1148 while ( cchPrefix > 0 1148 AssertReturn(cchPrefix > 0, NULL); 1149 1150 /* 1151 * We start with a root slash. 1152 */ 1153 if (!cchPrefix || *pchPrefix != '/') 1154 return NULL; 1155 1156 /* 1157 * Walk thru the prefix component by component, since that's how 1158 * the lookup tree is organized. 1159 */ 1160 while ( cchPrefix 1149 1161 && *pchPrefix == '/' 1150 1162 && pRoot->cDescsInTree > 0 … … 1157 1169 if (!pszEnd) 1158 1170 { 1159 /* We've narrowed it down to a sub-tree now. */ 1160 for (size_t i = 0; i < pRoot->cChildren; i++) 1171 /* 1172 * We've narrowed it down to a sub-tree now. If we've no more prefix to work 1173 * with now (e.g. '/Devices/'), the prefix matches all the children. Otherwise, 1174 * traverse the children to find the ones matching the prefix. 1175 */ 1176 if (!cchPrefix) 1161 1177 { 1162 PSTAMLOOKUP pCur = pRoot->papChildren[i]; 1163 if (pCur->cch >= cchPrefix) 1178 *ppLastDesc = stamR3LookupFindLastDescForRange(pRoot->papChildren[0], pRoot->papChildren[pRoot->cChildren - 1]); 1179 return stamR3LookupFindFirstDescForRange(pRoot->papChildren[0], pRoot->papChildren[pRoot->cChildren - 1]); 1180 } 1181 1182 size_t iEnd = pRoot->cChildren; 1183 if (iEnd < 16) 1184 { 1185 /* Linear scan of the children: */ 1186 for (size_t i = 0; i < pRoot->cChildren; i++) 1164 1187 { 1165 int iDiff = memcmp(pCur->szName, pchPrefix, cchPrefix); 1166 if (iDiff == 0) 1167 return stamR3LookupFindFirstDescForRange(pCur, pRoot->papChildren[pRoot->cChildren - 1]); 1168 if (iDiff > 0) 1169 break; 1188 PSTAMLOOKUP pCur = pRoot->papChildren[i]; 1189 if (pCur->cch >= cchPrefix) 1190 { 1191 int iDiff = memcmp(pCur->szName, pchPrefix, cchPrefix); 1192 if (iDiff == 0) 1193 { 1194 size_t iLast = i; 1195 while (++iLast < pRoot->cChildren) 1196 { 1197 PSTAMLOOKUP pCur2 = pRoot->papChildren[iLast]; 1198 if ( pCur2->cch < cchPrefix 1199 || memcmp(pCur2->szName, pchPrefix, cchPrefix) != 0) 1200 break; 1201 } 1202 iLast--; 1203 1204 *ppLastDesc = stamR3LookupFindLastDescForRange(pCur, pRoot->papChildren[iLast]); 1205 return stamR3LookupFindFirstDescForRange(pCur, pRoot->papChildren[iLast]); 1206 } 1207 if (iDiff > 0) 1208 break; 1209 } 1170 1210 } 1171 1211 } 1172 break; 1173 } 1174 1175 uint32_t cchElement = pszEnd - pchPrefix; 1176 PSTAMLOOKUP pChild = stamR3LookupFindChild(pRoot, pchPrefix, cchElement, NULL); 1212 else 1213 { 1214 /* Binary search to find something matching the prefix, followed 1215 by a reverse scan to locate the first child: */ 1216 size_t iFirst = 0; 1217 size_t i = iEnd / 2; 1218 for (;;) 1219 { 1220 PSTAMLOOKUP pCur = pRoot->papChildren[i]; 1221 int iDiff; 1222 if (pCur->cch >= cchPrefix) 1223 iDiff = memcmp(pCur->szName, pchPrefix, cchPrefix); 1224 else 1225 { 1226 iDiff = memcmp(pCur->szName, pchPrefix, pCur->cch); 1227 if (!iDiff) 1228 iDiff = 1; 1229 } 1230 if (iDiff > 0) 1231 { 1232 if (iFirst < i) 1233 iEnd = i; 1234 else 1235 return NULL; 1236 } 1237 else if (iDiff < 0) 1238 { 1239 i += 1; 1240 if (i < iEnd) 1241 iFirst = i; 1242 else 1243 return NULL; 1244 } 1245 else 1246 { 1247 /* Match. Reverse scan to find the first. */ 1248 iFirst = i; 1249 while ( iFirst > 0 1250 && (pCur = pRoot->papChildren[iFirst - 1])->cch >= cchPrefix 1251 && memcmp(pCur->szName, pchPrefix, cchPrefix) == 0) 1252 iFirst--; 1253 1254 /* Forward scan to find the last.*/ 1255 size_t iLast = i; 1256 while (++iLast < pRoot->cChildren) 1257 { 1258 pCur = pRoot->papChildren[iLast]; 1259 if ( pCur->cch < cchPrefix 1260 || memcmp(pCur->szName, pchPrefix, cchPrefix) != 0) 1261 break; 1262 } 1263 iLast--; 1264 1265 *ppLastDesc = stamR3LookupFindLastDescForRange(pRoot->papChildren[iFirst], pRoot->papChildren[iLast]); 1266 return stamR3LookupFindFirstDescForRange(pRoot->papChildren[iFirst], pRoot->papChildren[iLast]); 1267 } 1268 1269 i = iFirst + (iEnd - iFirst) / 2; 1270 } 1271 } 1272 break; 1273 } 1274 1275 /* Find child matching the path component: */ 1276 uint32_t cchChild = pszEnd - pchPrefix; 1277 PSTAMLOOKUP pChild = stamR3LookupFindChild(pRoot, pchPrefix, cchChild, NULL); 1177 1278 if (!pChild) 1178 1279 break; 1179 1280 1180 /* Advance */1181 cchPrefix -= cch Element;1281 /* Advance: */ 1282 cchPrefix -= cchChild; 1182 1283 pchPrefix = pszEnd; 1183 1284 pRoot = pChild; … … 1751 1852 STAM_LOCK_WR(pUVM); 1752 1853 1753 PSTAMDESC pCur = stamR3LookupFindFirstByPrefix(pUVM->stam.s.pRoot, pszPrefix, (uint32_t)cchPrefix); 1754 while (pCur) 1755 { 1756 PSTAMDESC const pNext = RTListNodeGetNext(&pCur->ListEntry, STAMDESC, ListEntry); 1757 size_t const cchName = strlen(pCur->pszName); 1758 if ( cchName >= cchPrefix 1759 && memcmp(pCur->pszName, pszPrefix, cchPrefix) == 0) 1854 PSTAMDESC pLast; 1855 PSTAMDESC pCur = stamR3LookupFindByPrefixRange(pUVM->stam.s.pRoot, pszPrefix, (uint32_t)cchPrefix, &pLast); 1856 if (pCur) 1857 for (;;) 1858 { 1859 PSTAMDESC const pNext = RTListNodeGetNext(&pCur->ListEntry, STAMDESC, ListEntry); 1860 Assert(strncmp(pCur->pszName, pszPrefix, cchPrefix) == 0); 1861 1760 1862 rc = stamR3DestroyDesc(pCur); 1761 else 1762 break;1763 1764 /* advance. */1765 pCur = pNext;1766 }1863 1864 /* advance. */ 1865 if (pCur == pLast) 1866 break; 1867 pCur = pNext; 1868 } 1767 1869 1768 1870 STAM_UNLOCK_WR(pUVM); … … 2661 2763 2662 2764 /** 2663 * Checks if the string contains a pattern expression or not.2664 *2665 * @returns true / false.2666 * @param pszPat The potential pattern.2667 */2668 static bool stamR3IsPattern(const char *pszPat)2669 {2670 return strchr(pszPat, '*') != NULL2671 || strchr(pszPat, '?') != NULL;2672 }2673 2674 2675 /**2676 2765 * Match a name against an array of patterns. 2677 2766 * … … 2799 2888 STAM_LOCK_RD(pUVM); 2800 2889 #ifdef STAM_WITH_LOOKUP_TREE 2801 if (!stamR3IsPattern(pszPat)) 2890 size_t const cchPat = strlen(pszPat); 2891 const char *pszAsterisk = (const char *)memchr(pszPat, '*', cchPat); 2892 const char *pszQuestion = (const char *)memchr(pszPat, '?', cchPat); 2893 if (!pszAsterisk && !pszQuestion) 2802 2894 { 2803 2895 pCur = stamR3LookupFindDesc(pUVM->stam.s.pRoot, pszPat); … … 2809 2901 } 2810 2902 } 2903 /* Is this a prefix expression where we can use the lookup tree to 2904 efficiently figure out the exact range? */ 2905 else if ( pszAsterisk == &pszPat[cchPat - 1] 2906 && pszPat[0] == '/' 2907 && !pszQuestion) 2908 { 2909 PSTAMDESC pLast; 2910 pCur = stamR3LookupFindByPrefixRange(pUVM->stam.s.pRoot, pszPat, (uint32_t)(cchPat - 1), &pLast); 2911 if (pCur) 2912 { 2913 for (;;) 2914 { 2915 Assert(strncmp(pCur->pszName, pszPat, cchPat - 1) == 0); 2916 if (fUpdateRing0) 2917 stamR3Refresh(pUVM, pCur, &bmRefreshedGroups); 2918 rc = pfnCallback(pCur, pvArg); 2919 if (rc) 2920 break; 2921 if (pCur == pLast) 2922 break; 2923 pCur = RTListNodeGetNext(&pCur->ListEntry, STAMDESC, ListEntry); 2924 } 2925 Assert(pLast); 2926 } 2927 else 2928 Assert(!pLast); 2929 } 2811 2930 else 2812 2931 { 2932 /* It's a more complicated pattern. Find the approximate range 2933 and scan it for matches. */ 2813 2934 PSTAMDESC pLast; 2814 2935 pCur = stamR3LookupFindPatternDescRange(pUVM->stam.s.pRoot, &pUVM->stam.s.List, pszPat, &pLast); … … 2833 2954 else 2834 2955 Assert(!pLast); 2835 2836 2956 } 2837 2957 #else
Note:
See TracChangeset
for help on using the changeset viewer.