Can you post reproducable code showing this? I.e. code
that anyone can copy/past and run directly, that makes
it easier to understand your problem. I didn't manage
to reproduce it.
I'm not convinced your usage scenario is a compelling
reason to create and destroy counters all the time, but
then I don't know the full scenario. Can the user selecy
any random counter to display, or is it some restrictede
set of counters?
If you can describe the problem a bit more detail, we
might come up with an alternative solution. Creating
counters all the time is relatively painful, so you
really want to avoid it if possible.
Here's the page code:
-----------------------------------------------------------------------
<%@ Page Language="C#" ContentType="text/xml" %>
<%@ Import namespace="System.Diagnostics" %>
<%@ Import namespace="System.Xml" %>
<script language="C#" runat="server">
static int PERF_TYPE_NUMBER = 0x00000000; // a number (not a counter)
static int PERF_TYPE_COUNTER = 0x00000400; // an increasing numeric value
static int PERF_TYPE_TEXT = 0x00000800; // a text field
static int PERF_TYPE_ZERO = 0x00000C00; // displays a zero
static int PERF_COUNTER_VALUE = 0x00000000; // display counter value
static int PERF_COUNTER_RATE = 0x00010000; // divide ctr / delta time
static int PERF_COUNTER_FRACTION = 0x00020000; // divide ctr / base
static int PERF_COUNTER_BASE = 0x00030000; // base value used in
fractions
static int PERF_COUNTER_ELAPSED = 0x00040000; // subtract counter from
current time
static int PERF_COUNTER_QUEUELEN = 0x00050000; // Use Queuelen processing
func.
static int PERF_COUNTER_HISTOGRAM = 0x00060000; // Counter begins or ends
a histogram
static int PERF_COUNTER_PRECISION = 0x00070000; // divide ctr / private
clock
static int PERF_TIMER_TICK = 0x00000000; // use system perf. freq for
base
static int PERF_TIMER_100NS = 0x00100000; // use 100 NS timer time base
units
static int PERF_OBJECT_TIMER = 0x00200000; // use the object timer freq
public void Page_Load(Object sender, EventArgs e)
{
// Result Document
XmlDocument PerformanceDocument = new XmlDocument();
XmlElement PerformanceElement =
PerformanceDocument.CreateElement("performance");
PerformanceDocument.AppendChild(PerformanceDocument.CreateProcessingInstruct
ion("xml", "version=\"1.0\" encoding=\"UTF-8\""));
PerformanceDocument.AppendChild(PerformanceElement);
SampleSystemPerformance(PerformanceElement);
// Render the Document
XmlTextWriter XmlOutputWriter = new XmlTextWriter(Response.Output);
PerformanceDocument.WriteTo(XmlOutputWriter);
XmlOutputWriter.Close();
}
void SampleSystemPerformance(XmlElement PerformanceElement)
{
// System Counters
RenderCounterSample(PerformanceElement, "Processor\\% Processor
Time\\_Total");
RenderCounterSample(PerformanceElement, "Memory\\Available Mbytes");
RenderCounterSample(PerformanceElement, "Memory\\Pages/sec");
RenderCounterSample(PerformanceElement, "System\\Context Switches/sec");
RenderCounterSample(PerformanceElement, "Process\\Handle
Count\\aspnet_wp");
}
PerformanceCounter CreatePerformanceCounter(string CounterName)
{
if( CounterName == null )
{
throw new ArgumentNullException();
}
// Create Counter
string[] Components = CounterName.Split('\\');
if( Components.Length == 2 )
{
return new PerformanceCounter(Components[0], Components[1]);
}
else if( Components.Length == 3 )
{
return new PerformanceCounter(Components[0], Components[1],
Components[2]);
}
else if( Components.Length == 4 )
{
return new PerformanceCounter(Components[0], Components[1],
Components[2], Components[3]);
}
throw new ArgumentException();
}
void RenderCounterSample(XmlElement ParentElement, string CounterName)
{
RenderCounterSample(ParentElement, CounterName,
CreatePerformanceCounter(CounterName).NextSample());
}
void RenderCounterSample(XmlElement ParentElement, string CounterName,
CounterSample Sample)
{
XmlElement SampleElement =
ParentElement.OwnerDocument.CreateElement("counter-sample");
long CounterType = (int)Sample.CounterType & 0x00000C00;
long CounterSubtype = (int)Sample.CounterType & 0x000F0000;
long TimerBase = (int)Sample.CounterType & 0x00300000;
SampleElement.SetAttribute("counter", CounterName);
SampleElement.SetAttribute("counter-type",
((int)Sample.CounterType).ToString("X08"));
SampleElement.SetAttribute("raw-value", Sample.RawValue.ToString());
if( CounterType == PERF_TYPE_NUMBER )
{
// The value is enough for this counter
}
else if( CounterType == PERF_TYPE_COUNTER )
{
if( CounterSubtype == PERF_COUNTER_VALUE )
{
}
else if( CounterSubtype == PERF_COUNTER_RATE )
{
// Time
if( TimerBase == PERF_TIMER_TICK )
{
SampleElement.SetAttribute("time-stamp", Sample.TimeStamp.ToString());
SampleElement.SetAttribute("system-frequency",
Sample.SystemFrequency.ToString());
}
else if( TimerBase == PERF_TIMER_100NS )
{
SampleElement.SetAttribute("time-stamp-100nsec",
Sample.TimeStamp100nSec.ToString());
}
else if( TimerBase == PERF_OBJECT_TIMER )
{
}
}
}
ParentElement.AppendChild(SampleElement);
}
</script>
Add any namespaces it needs, I didn't post the whole page for clarity so I
might have left some out. If you run this under Windows 2000 Server (NOT
Win2k3, it works fine there) you will see that the handle count for
aspnet_wp will keep going up untill the application restarts. It eats 9
handles per counter, so feel free to add more counters to speed up the
process (Asp.Net app restarts once you get to 4 or 5 thousand handles).
And just to let you know - calling PerformanceCounter.Close on those counter
objects does not help, if you want to go ahead and change
RenderCounterSample to this:
void RenderCounterSample(XmlElement ParentElement, string CounterName)
{
PerformanceCounter Counter = CreatePerformanceCounter(CounterName);
RenderCounterSample(ParentElement, CounterName, Counter.NextSample());
Counter.Close();
}
I eventually used WMI to gather the performance counters I need but I think
that's less than ideal solution. And of course the code is not finished, it
will not render all the information needed for all counter types but it
works for the ones I'm watching. I'll add more when I need it.
Jerry
> Can you post reproducable code showing this? I.e. code
> that anyone can copy/past and run directly, that makes
[quoted text clipped - 11 lines]
> counters all the time is relatively painful, so you
> really want to avoid it if possible.