Home » Windows » Performance Counter shows different values when ReadOnly=false

Performance Counter shows different values when ReadOnly=false

Posted by: admin February 27, 2018 Leave a comment

Questions:

I was trying to figure out why certain performance counters aren’t updated in our production server, when I’ve hit this weird issue – the counter seems to return different RawValue values when it is not read only. When read-only it is always zero, when not read-only it shows different values.

Here is my PowerShell session showing this:

PS C:\Users\doron> $counter = new-object Diagnostics.PerformanceCounter
PS C:\Users\doron> $counter.CategoryName = "My category"
PS C:\Users\doron> $counter.CounterName = "My counter name"
PS C:\Users\doron> $counter.ReadOnly = 1
PS C:\Users\doron> $counter


CategoryName     : My category
CounterHelp      : My counter name
CounterName      : My counter name
CounterType      : NumberOfItems64
InstanceLifetime : Global
InstanceName     :
ReadOnly         : True
MachineName      : .
RawValue         : 0
Site             :
Container        :



PS C:\Users\doron> $counter.ReadOnly = 0
PS C:\Users\doron> $counter


CategoryName     : My category
CounterHelp      : My counter name
CounterName      : My counter name
CounterType      : NumberOfItems64
InstanceLifetime : Global
InstanceName     :
ReadOnly         : False
MachineName      : .
RawValue         : 20
Site             :
Container        :



PS C:\Users\doron> $counter.ReadOnly = 1
PS C:\Users\doron> $counter


CategoryName     : My category
CounterHelp      : My counter name
CounterName      : My counter name
CounterType      : NumberOfItems64
InstanceLifetime : Global
InstanceName     :
ReadOnly         : True
MachineName      : .
RawValue         : 0
Site             :
Container        :

The server is Windows 2008 R2, running .NET 4.5.

An important note is that all my other performance counters are not behaving like this, only some recently added performance counters (these are the ones that don’t work). For all the other counters, the RawValue id always identical, whether ReadOnly or not.

Any idea what could be causing this?

Answers:

Since you did not provide a lot of information on how you create the performance counter and who updates the counter at what point, I can only make an informed guess and tell you the difference between the two.

Difference of RawValue when ReadOnly=True vs Readonly=False

According to MSDN:

If the counter that you are reading is read-only, getting the RawValue property samples the counter at the time that the property is called.This action is equivalent to making an initial call to the NextSample method.

Source: http://msdn.microsoft.com/de-de/library/system.diagnostics.performancecounter.rawvalue.aspx

Indeed you can confirm this looking at the actual framework source for the RawValue property:

public long RawValue
{
  get
  {
    if (this.ReadOnly)
      return this.NextSample().RawValue;
    this.Initialize();
    return this.sharedCounter.Value;
  }
  ...
}

MSDN does not say what happens when ReadOnly is set to False, however looking at the code snippet above you will see that it will call Initialize and then return the value of an internal sharedCounter object, which is created by Initialize. Initialize is called in various places though and only the first call will really initialize the object.

Because the code is quite complex, I did not understand the complete process, but it seems that the value will be cached when the performance counter is not readonly and so you will see an old value.

Possible explanation

I have to guess here, because you did not say how you did the test actually, but if you initialize the performance counter before you updated any value, then I would assume that you see a RawValue of 0 everytime, even if the counter is updated in the meantime.

Now as soon as you set ReadOnly to True and query RawValue again, you will see the actual value that the PerformanceCounter has at this moment.

An interesting experiment would be to call NextSample() instead of using RawValue. In my opinion you should get the same results in both cases then.

Hope this helps!