Need help with rewriting GetCountersNeededForAnalysis()

Sep 12, 2008 at 1:05 AM

I’m trying to rewrite the GetCountersNeededForAnalysis() function because this function by far takes the most time to process especially when there are a lot of performance counters in perfmon logs. The function needs to return an array of strings. The array contains the full path of counter paths such as \\Computer\Processor(0)\% Processor Time. The function compares the perf counter paths in the threshold file to the counter paths in the perfmon log and removes the duplicates. The problem is if the counter path in the threshold file specifies “\Processor(*)\% Processor Time”, then it needs to use that path versus an instance specific path such as “\Processor(_Total)\% Processor Time”.

<o:p> </o:p>

Some of the PAL users have logs with over 8000 performance counters and it’s taking PAL practically days to process them. Thank you.

<o:p> </o:p>

Function GetCountersNeededForAnalysis()<o:p></o:p>

    Dim aReturned(), a, b, i, m, bFound<o:p></o:p>

    Dim oAnalysis, oCounter, oChart<o:p></o:p>

    Dim aCountersFromObjects()<o:p></o:p>

    Dim sName<o:p></o:p>

    Dim sComputer1, sPerfCounterObject1, sPerfCounterName1, sPerfCounterInstance1<o:p></o:p>

    Dim sComputer2, sPerfCounterObject2, sPerfCounterName2, sPerfCounterInstance2<o:p></o:p>


    a = 0<o:p></o:p>

    For Each oAnalysis in g_aData<o:p></o:p>

        If oAnalysis.AllCountersFound = True Then<o:p></o:p>

            For Each oCounter in oAnalysis.Counters<o:p></o:p>

                For m = 0 to UBound(oCounter.MatchedCounters)<o:p></o:p>

                    ReDim Preserve aCountersFromObjects(a)<o:p></o:p>

                    aCountersFromObjects(a) = oCounter.MatchedCounters(m).FullPath<o:p></o:p>

                    OutputToConsoleAndLog "[GetCountersNeededForAnalysis] " & oCounter.MatchedCounters(m).FullPath<o:p></o:p>

                    a = a + 1<o:p></o:p>



            If oAnalysis.Charts(0).ChartTitle <> "NO CHARTS" Then<o:p></o:p>

                For Each oChart in oAnalysis.Charts<o:p></o:p>

                    For m = 0 to UBound(oChart.MatchedCounters)<o:p></o:p>

                        ReDim Preserve aCountersFromObjects(a)<o:p></o:p>

                        aCountersFromObjects(a) = oChart.MatchedCounters(m).FullPath<o:p></o:p>

                        a = a + 1<o:p></o:p>



            End If<o:p></o:p>

        End If<o:p></o:p>


<o:p> </o:p>

    i = 0<o:p></o:p>

    ReDim aReturned(0)<o:p></o:p>

    aReturned(0) = "\PlaceHolder(*)\PlaceHolder"    <o:p></o:p>

    Dim dctCounterListForRelog, sCounterPath<o:p></o:p>

    Set dctCounterListForRelog = CreateObject("Scripting.Dictionary")<o:p></o:p>

    OutputToConsoleAndLog "   Looking for duplicate counters in counter list..."<o:p></o:p>

    For Each sName in aCountersFromObjects<o:p></o:p>

        ' Look for duplicates<o:p></o:p>


        OutputToConsoleAndLog "[GetCountersNeededForAnalysis] UBound(aReturned):" & UBound(aReturned)<o:p></o:p>

        bFound = False<o:p></o:p>

        For a = 0 to UBound(aReturned)            <o:p></o:p>

            'Dim sComputer, sPerfCounterObject, sPerfCounterName, sPerfCounterInstance<o:p></o:p>

            sComputer1 = LCase(GetCounterComputer(sName))<o:p></o:p>

            sComputer2 = LCase(GetCounterComputer(aReturned(a)))<o:p></o:p>

            sPerfCounterObject1 = LCase(GetCounterObject(sName))<o:p></o:p>

            sPerfCounterObject2 = LCase(GetCounterObject(aReturned(a)))<o:p></o:p>

            sPerfCounterName1 = LCase(GetCounterName(sName))<o:p></o:p>

            sPerfCounterName2 = LCase(GetCounterName(aReturned(a)))<o:p></o:p>

            sPerfCounterInstance1 = LCase(GetCounterInstance(sName))<o:p></o:p>

            sPerfCounterInstance2 = LCase(GetCounterInstance(aReturned(a)))<o:p></o:p>

            If sComputer1 = sComputer2 AND sPerfCounterObject1 = sPerfCounterObject2 AND sPerfCounterName1 = sPerfCounterName2 Then<o:p></o:p>

                ' If the entry candidate has a "*" in the instance, then replace the existing entry.<o:p></o:p>

                If sPerfCounterInstance1 = "*" Then<o:p></o:p>

                    aReturned(a) = sName<o:p></o:p>

                    bFound = True<o:p></o:p>

                    Exit For<o:p></o:p>

                End If<o:p></o:p>

                ' If the instance name matches or if the aReturned array already has a wildcard entry, then we have it already.<o:p></o:p>

                If (sPerfCounterInstance1 = sPerfCounterInstance2) OR sPerfCounterInstance2 = "*" Then<o:p></o:p>

                    bFound = True<o:p></o:p>

                    Exit For<o:p></o:p>

                End If                <o:p></o:p>

            End If<o:p></o:p>


        If bFound = False Then<o:p></o:p>

            ReDim Preserve aReturned(i)<o:p></o:p>

            aReturned(i) = sName<o:p></o:p>

            i = i + 1<o:p></o:p>

            'OutputToConsoleAndLog "[GetCountersNeededForAnalysis] UBound(aReturned):" & UBound(aReturned)<o:p></o:p>

        End If<o:p></o:p>


    If aReturned(0) = "\PlaceHolder(*)\PlaceHolder" Then<o:p></o:p>

        OutputToConsoleAndLog "[GetCountersNeededForAnalysis] No counters in Threshold XML file found in the perfmon log."<o:p></o:p>


    End If <o:p></o:p>

    GetCountersNeededForAnalysis = aReturned<o:p></o:p>

End Function

Sep 22, 2008 at 1:17 AM
Edited Sep 22, 2008 at 1:32 AM
 Hi Clint , 
  at a first glance   I would move the following line  outside the nested for cycle:
  I do not made any test for now: I will done them on day time (now it's night and I'm too tired to make a test )  but the variable <sName> does not depend from the values of the nested loop so it should be better to move out  all the function calls.

         sComputer1 = LCase(GetCounterComputer(sName))    
         sPerfCounterObject1 = LCase(GetCounterObject(sName))
         sPerfCounterName1 = LCase(GetCounterName(sName)) 
         sPerfCounterInstance1 = LCase(GetCounterInstance(sName))

Another test you can try to reduce time  use the redim statement, that is a long opertion like each allocation operation
You can do in such way
 add  this lines
     For Each oCounter in oAnalysis.Counters
             a = a + (UBound(oCounter.MatchedCounters) - LBound(oCounter.MatchedCounters))  
 ' also, simpler, a = a + UBound(oCounter.MatchedCounters)    
   ReDim Preserve aCountersFromObjects(a)
 and erase the redim statement .
 even if you are adding a for/next loop ( but not nested) you are deleting multiple redim : the time  used should be lesser
 The same thing for the lines below.

please,let me know

Sep 23, 2008 at 4:50 AM
Ah, good eye. I'll move those up. That should at least save a few minutes for some folks. Thanks!