开发者

Naming multi-instance performance counters in .NET

开发者 https://www.devze.com 2023-01-02 08:43 出处:网络
Most multiple instance performance counters in Windows seem to automatically(?) have a #n on the end if there\'s more than one instance with the same name.

Most multiple instance performance counters in Windows seem to automatically(?) have a #n on the end if there's more than one instance with the same name.

For example: if, in Perfmon, you look under the Process category, you'll see:

...
dwm
explorer
explorer#1
...

I have two explorer.exe processes, so the second counter has #1 appended to its name.

When I attempt to do this in a .NET application:

  • I can create the category, and register the instance (using the PerformanceCounterCategory.Create that takes a CounterCreationDataCollection).
  • I can open the counter for write and write to it.

When I open the counter a second time (in another process), it opens the same counter. This means that I have two processes fighting over the counters.

The documentation for PerformanceCounter.InstanceName states that # is not allowed in the name.

So: how do I have multiple-instance performance counters that are actually multiple instance? And where the second (and subsequent) instances get #n appended to the name?

That is: I know that I can put the process ID (e.g.) on the instance name. This works, but has the unfortunate side effect that restarting the process results in a new PID, and Perfmon continues monitoring the old counter.

Update:

I'm creating the category (and counter) as follows:

const string categoryName = "Test App";
const string counterName = "Number of kittens";
string instanceName =
    Path.GetFileNameWithoutExtension(
        Proce开发者_C百科ss.GetCurrentProcess().MainModule.FileName);

if (!PerformanceCounterCategory.Exists(categoryName))
{
    var counterCreationDataCollection = new CounterCreationDataCollection
        {
            new CounterCreationData(counterName, "",
                PerformanceCounterType.NumberOfItems32)
        };

    PerformanceCounterCategory.Create(categoryName, "",
        PerformanceCounterCategoryType.MultiInstance,
        counterCreationDataCollection);
}

I'm opening the counter as follows:

PerformanceCounter counter = new PerformanceCounter(
        categoryName, counterName, instanceName, readOnly: false);


I think your issue is with the fact the .NET is more loose in regards to performance counters, and is actually bypassing the PerfLib Win API.

When using the native PerfLib API, you register categories during setup - and create instances from the process using handles. So with native API there is no straightforward way to share a counter instance. So when two counter instances are accessed with the same name, they actually have different handles and are marked by # appropriately.

In .NET as you simply address a counter and instance by name, you are in danger of cross updates. As .NET takes the name and enumerates(using the WMI) the instances even if they are being used by a different application.

I think that adding the PID* is indeed the smartest solution - as you both have better track-ability and no collision. Regarding the issue with restart creating a new counter, I fail to see the problem; if you allow more than one instance of the process to run at a given time how would you know if this instance was created due to a restart or simply running another executable?

If you do have a dependency of some sort between the processes, you can cleanup stale counters or employ some other logic. While in PerfMon you can watch "*" all instances.

*Or if you have some logic behind the process, which is maintained without regard to restarts - such as a task id of some sort.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号