Or better yet! You want at that data to generate graphs of the metrics over the duration of the test. Sure, you can do this by firing up good 'ol Perfmon and logging the values or you can just get them from your load test repository with some SQL. Why have Perfmon logging when VS2008 already does this for you?
I have a need for just such an action and I've been working on the SQL statements to extract the data I need. It's not complete, but this is a major step forward to allowing me to finish up the SPs I want to collect the data dynamically for consumption by managers and other QA folks.
Looking at the handy dandy schema of the load test repository (located here for all to gander) I have created some SQL statements that take care of the leg work for me.
1: SELECT LoadTestPerformanceCounterInstance.InstanceId,
2: LoadTestPerformanceCounterCategory.CategoryName,
3: LoadTestPerformanceCounter.CounterName,
4: LoadTestPerformanceCounterInstance.InstanceName, LoadTestPerformanceCounterCategory.MachineName,
5: AVG(LoadTestPerformanceCounterSample.ComputedValue) AS AverageValue,
6: stdev(LoadTestPerformanceCounterSample.ComputedValue) as StdDev,
7: count(LoadTestPerformanceCounterSample.ComputedValue) as Count
8: FROM LoadTestPerformanceCounterCategory INNER JOIN
9: LoadTestPerformanceCounter INNER JOIN
10: LoadTestPerformanceCounterInstance ON LoadTestPerformanceCounter.LoadTestRunId = LoadTestPerformanceCounterInstance.LoadTestRunId AND
11: LoadTestPerformanceCounter.CounterId = LoadTestPerformanceCounterInstance.CounterId ON
12: LoadTestPerformanceCounterCategory.CounterCategoryId = LoadTestPerformanceCounter.CounterCategoryId AND
13: LoadTestPerformanceCounterCategory.LoadTestRunId = LoadTestPerformanceCounter.LoadTestRunId INNER JOIN
14: LoadTestPerformanceCounterSample ON LoadTestPerformanceCounterInstance.LoadTestRunId = LoadTestPerformanceCounterSample.LoadTestRunId AND
15: LoadTestPerformanceCounterInstance.InstanceId = LoadTestPerformanceCounterSample.InstanceId
16: WHERE (LoadTestPerformanceCounter.LoadTestRunId = 83)
17: GROUP BY LoadTestPerformanceCounterCategory.CategoryName, LoadTestPerformanceCounter.CounterName, LoadTestPerformanceCounterInstance.InstanceName,
18: LoadTestPerformanceCounterInstance.InstanceId, LoadTestPerformanceCounterCategory.MachineName
19: ORDER BY LoadTestPerformanceCounterInstance.InstanceId
In the above example, the reference to LoadTestRunId is hard coded to a previous run that I have in my results repository. For all my other SPs I use the GUID of the test and will convert the above SQL statement to reference GUID all in good time. The query above returns results like this:
1: 0 .NET CLR Memory Gen 0 heap size w3wp 10.0.0.11 944824777.209431 185400315.203616 721
2: 1 .NET CLR Memory Large Object Heap size w3wp 10.0.0.11 86994000.5298197 29625345.9051784 721
3: 2 .NET CLR Memory # Gen 0 Collections w3wp 10.0.0.11 132.608876560333 69.5129454689118 721
4: 3 .NET CLR Memory Gen 2 heap size w3wp 10.0.0.11 197119053.001387 78824416.0154383 721
5: 4 .NET CLR Memory Allocated Bytes/sec w3wp 10.0.0.11 63521791.4160888 91335026.9218956 721
6: 5 .NET CLR Memory # Gen 2 Collections w3wp 10.0.0.11 29.5104022191401 12.1351287581502 721
7: 6 .NET CLR Memory Promoted Memory from Gen 0 w3wp 10.0.0.11 42540355.2815534 13356693.0175676 721
8: 7 .NET CLR Memory # Induced GC w3wp 10.0.0.11 0 0 721
9: 8 .NET CLR Memory Gen 0 Promoted Bytes/Sec w3wp 10.0.0.11 418557.084366331 1120132.98732717 721
10: 9 .NET CLR Memory Promoted Memory from Gen 1 w3wp 10.0.0.11 21740368.0721221 25126733.8606902 721
11: 10 .NET CLR Memory # GC Handles w3wp 10.0.0.11 3750.73370319001 216.191892870829 721
12: 11 .NET CLR Memory # Gen 1 Collections w3wp 10.0.0.11 70.0693481276005 35.4698332819129 721
13: 12 .NET CLR Memory Gen 1 heap size w3wp 10.0.0.11 62394980.9237171 31034211.4233198 721
14: 13 .NET CLR Memory Finalization Survivors w3wp 10.0.0.11 8217.1040221914 3024.02383909951 721
15: 14 .NET CLR Memory Promoted Finalization-Memory from Gen 0 w3wp 10.0.0.11 11415345.6768377 11434973.2174913 721
16: 15 .NET CLR Memory % Time in GC w3wp 10.0.0.11 3.48545611573799 6.73310861817717 721
The first column is the InstanceId of the perfmon counter and the information for the counter is split up into three separate columns (CategoryName, CounterName and InstanceName) but the column that ties them all together is the InstanceId.
Ok. That's fine and dandy but what about graphing the metrics over the duration of the load test?
Well, that's another SQL query I wrote that is in the alpha stage of development. In the above example I displayed 15 out of 466 metrics that were logged. Let's choose to graph the .NET CLR Memory Gen 2 heap size for w3wp. This particular metric happens to be InstanceId #3 this time around and we can use it in the SQL statement below to extract the data that can eventually be used to graph the results.
1: SELECT LoadTestPerformanceCounterInstance.InstanceName,
2: LoadTestPerformanceCounterSample.ComputedValue
3: FROM LoadTestPerformanceCounterInstance INNER JOIN
4: LoadTestPerformanceCounterSample ON LoadTestPerformanceCounterInstance.LoadTestRunId = LoadTestPerformanceCounterSample.LoadTestRunId AND
5: LoadTestPerformanceCounterInstance.InstanceId = LoadTestPerformanceCounterSample.InstanceId
6: WHERE (LoadTestPerformanceCounterInstance.LoadTestRunId = 83) AND (LoadTestPerformanceCounterInstance.InstanceId = 3)
7: ORDER BY LoadTestPerformanceCounterSample.TestRunIntervalId
This query yields the results of:
1: w3wp 0
2: w3wp 0
3: w3wp 96
4: w3wp 3231264
5: w3wp 2.170597E+07
6: w3wp 2.170597E+07
7: w3wp 2.170597E+07
8: w3wp 2.976022E+07
9: w3wp 2.976022E+07
10: w3wp 2.976022E+07
11: w3wp 2.976022E+07
12: w3wp 4.127677E+07
13: w3wp 4.127677E+07
14: w3wp 4.127677E+07
and so on and so on until all 722 metrics are displayed. We can take those 722 metrics and copypasta into Excel and generate a quick and dirty graph:
Viola! Quick and dirty graph from Excel!
I'll need to change the column output to show more details on the metrics to display all three columns to better identify the perfmon metric and also display the time that the metric was taken.
After I do all that I'll need to write some code to generate graphs on the fly. I'm thinking that this project on SourceForge will fit the bill nicely and there seems to be a bunch of examples out on the 'net how to use ZedGraph to it's fullest.
Oh yeah! Almost forgot. I need to double check the results between the first query and the individual information for InstanceId 3 metric (the .NET CLR Gen 2 heap size for w3wp). The first query output says the average value is 197119053.001387. Take the average of output that I did the copypasta into Excel gonkulates to an average of 197119053.4. The difference between the two? A measly 0.355. I'm thinking that is good 'nuff for government work.
Now I just need to finish up the queries and get them into SPs and integrate them with the other code that I've written that does automagic before/after comparison of transaction response times (more on that at a later date).
No comments:
Post a Comment