It is currently December 12th, 2018, 4:07 am

PerfMonPDH Performance Data Plugin

Share your custom plugins and applications to enhance Rainmeter.
rxtd
Posts: 65
Joined: April 30th, 2017, 11:51 am

Re: PerfMonPDH Performance Data Plugin

rxtd » September 2nd, 2018, 11:50 am

Hello, buckb.
I found one another useful thing that PerfMonPDH lacks.
There are some values that perfmon doesn't provide counters for but that can be calculated using other counters.
Well, I am specifically interested in shared memory that is <Working set> - <Working set - Private>, but there can be other cases, such as read to write ratio or something.
PerfmonPDH can not use such values neither for sorting nor for rollup. And if I want to, for example, obtain approximate RAM usage of chrome it is a problem, because rough approximate value for it is (sum(working set private) + max(working set shared)).

I think, I have a solution. And I believe that it can be implemented and won't cause performance issues.
We can add a virtual "counters" that won't be obtained from PDH but calculated from other counters.
I propose the following syntax:

Code: Select all

CounterList = Counter1 | Counter2
ExpressionList = <Expression1> | <Expression2>
RollupExpressionList = <RollupExpression1> | <RollupExpression2>
Where expression can contain any numbers, +-/*^, ?:, parentheses and references to counters in the following form:

Code: Select all

reference = c <decimalNumber> <nameIdentifier> <numberIdentifier> <valueType> | e <decimalNumber> <nameIdentifier> <numberIdentifier>
nameIdentifier = | ( instanceName )
numberIdentifier = | [ instanceNumber ]
valueType = R | F
RollupExpressions are the same as usual Expressions but references has different form:

Code: Select all

reference = c <decimalNumber> <nameIdentifier> <numberIdentifier> <valueType> | <expressionType> <decimalNumber> <nameIdentifier> <numberIdentifier> <rollupFunction>
expressionType = e | r
nameIdentifier = | ( instanceName )
numberIdentifier = | [ instanceNumber ]
valueType = R | F
rollupFunction = s | a | m | M | c | i
Actually, Expressions are pretty mush the same as what we can do with several final Child Measures in Rainmeter formulas without rollup and RollupExpressions—with rollup, but it can be used for sorting.

All Expressions can reference all counters preceding them and can not reference themselves and counters following them. Usual Expressions can reference any usual counters and can't reference RollupExpressions. RollupExpressions can reference any of usual counters and Expressions.

Child measures will have two more types: one for Expression, one for RollupExpression. RollupFunction in this types won't do anything.
SortBy will have two more types: one for Expressions, one for RollupExpressions.

If expressions are used then SortRollupFunction is inactive.

Usual Expressions can be used in any situation. RollupExpressions can be used only if rollup is turned on.
The example of using plugin after update:

Code: Select all

[measureParent]
Measure = Plugin
Plugin = PerfMonPDH
Type = Parent
ObjectName = Process
CounterList = Working Set | Working Set - Private
ExpressionList = c0R - c1R
RollupExpressionList = c1Rs + e0M
SortBy = RollupExpression
SortCounterIndex = 0
Blacklist = _Total
Rollup = 1

[measureChild]
Measure = Plugin
Plugin = PerfMonPDH
Type = GetRollupExpression
Parent = measureParent
CounterIndex = 0
InstanceIndex = 0
I've looked into code, and I believe I know how to implement it.

What do you think about it?
buckb
Posts: 34
Joined: February 12th, 2018, 12:47 am

Re: PerfMonPDH Performance Data Plugin

buckb » September 2nd, 2018, 11:12 pm

Hi rxtd,

I only have one concrete suggestion regarding your proposed enhancements. Specifically, I think it would be better if your new syntax used longer keyword names. I find "c1Rs + e0M" a bit too cryptic. I go overboard sometimes in using long names, but I find the improved readability worth it.

However, I do have a generalized comment regarding enhancements that you, I, or anyone else might implement. When I first started PerfMonPDH, I considered providing a very limited plugin interface that simply returned counter data as long result strings. Something like "Instance1Counter1=x Instance1Counter2=y, ...", or perhaps XML encoded. The skin could then pick apart and process the data, most likely using Lua.

Your extensions could be implemented with a combination of a generic counter retrieval interface and some Lua. I know there would be a performance penalty to this approach, but this method has the benefit of making it easier for a skin developer to implement specialized features. I am wary of feature creep in the plugin itself and am drawn to the idea of keeping PerfMonPDH as close to the source performance data as possible. But you shouldn't listen to me. I just implemented a couple of new features in PerfMonPDH and didn't follow this advice!

Finally, if you intend to release your enhanced version of PerfMonPDH (as opposed to developing solely for your own use), I think you should give it a new name (PerfMonRXTD?) to minimize compatability problems between different skins. Simply using different version numbers is not sufficient.

--buckb


P.S.

I've added your LogicalDisk rollup code to PerfMonPDH. I did make a change, though. I've provided two different naming/rollup schemes: LogicalDiskDriveLetter does precisely what your mod does (rollup by drive letter), while LogicalDiskMountPoint rolls up by (you guessed it) mount points. I've also added two new child measure types to retrieve the Sum/Average/Minimum/Maximum/Count for all instances of a given counter, subject to filtering and rollup. They are GetRawCounterAll and GetFormattedCounterAll. I just added these features yesterday, so I'll need to test for a few days before posting.
rxtd
Posts: 65
Joined: April 30th, 2017, 11:51 am

Re: PerfMonPDH Performance Data Plugin

rxtd » September 3rd, 2018, 9:05 am

buckb wrote:it would be better if your new syntax used longer keyword names
Yeah, probably. At least, it would fit better since other options have long names.
buckb wrote:I know there would be a performance penalty to this approach, but this method has the benefit of making it easier for a skin developer to implement specialized features.
I see what you mean but performance is essential for me. Although I'm not too limited in CPU time, Rainmeter is a single threaded application, and with enough count of complex skins it's easy to make it lag at updates.
0% CPU spent in any plugin would satisfy me ;-)
And LUA is slower than native code. Probably, times slower. Not to mention (de)serialization.
buckb wrote:Finally, if you intend to release your enhanced version of PerfMonPDH (as opposed to developing solely for your own use), I think you should give it a new name (PerfMonRXTD?) to minimize compatability problems between different skins.
Good idea.
I think I will also start a new thread, if you don't mind, so that people who don't read all posts will know about my modification.
buckb
Posts: 34
Joined: February 12th, 2018, 12:47 am

Re: PerfMonPDH Performance Data Plugin

buckb » September 3rd, 2018, 5:07 pm

rxtd wrote: I see what you mean but performance is essential for me. Although I'm not too limited in CPU time, Rainmeter is a single threaded application, and with enough count of complex skins it's easy to make it lag at updates.
I understand. After all, I chose the native-code route myself.
rxtd wrote: I think I will also start a new thread, if you don't mind, so that people who don't read all posts will know about my modification.
I don't mind at all. I look forward to following your work.


--buckb
buckb
Posts: 34
Joined: February 12th, 2018, 12:47 am

Re: PerfMonPDH Performance Data Plugin

buckb » September 4th, 2018, 6:52 pm

Updated plugin to version 2.0.1.3
  • Changed parent option DisplayName to NameFormat and associated option value Original to Default
  • Added NameFormat options for LogicalDisk rollup: LogicalDiskDriveLetter and LogicalDiskMountPoint (thanks to rxtd)
  • Added new child measures GetRawCounterAll and GetFormattedCounterAll
  • Source included
Please refer to the readme in the Plugins directory for details.


--buckb
rxtd
Posts: 65
Joined: April 30th, 2017, 11:51 am

Re: PerfMonPDH Performance Data Plugin

rxtd » September 5th, 2018, 12:27 pm

buckb,
Do you know if perfmon instance names can contain '|' symbol?
This page doesn't have it as special character, so i think '|' can't be used for separation if rainmeter option can contain several instance names.
What do you think?
buckb
Posts: 34
Joined: February 12th, 2018, 12:47 am

Re: PerfMonPDH Performance Data Plugin

buckb » September 5th, 2018, 6:02 pm

rxtd wrote:Do you know if perfmon instance names can contain '|' symbol?
I don't know the answer.

I chose the pipe character to be consistent with the syntax of other Rainmeter plugins. If someone runs across a Perfmon counter or instance that contains a pipe character, then PerfMonPDH can be enhanced to allow "escaping".


--buckb
rxtd
Posts: 65
Joined: April 30th, 2017, 11:51 am

Re: PerfMonPDH Performance Data Plugin

rxtd » September 10th, 2018, 6:32 pm

buckb,
I posted my mod in this topic, if you are interested.
rxtd
Posts: 65
Joined: April 30th, 2017, 11:51 am

Re: PerfMonPDH Performance Data Plugin

rxtd » September 13th, 2018, 2:21 pm

Hi, buckb.
I've just profiled Rainmeter with my mod of your plugin, with few perfmon/process skins running at update rate 100 to get clearer picture. I discovered that PdhCollectQueryData call takes about 60% of all CPU time consumed by application. I think that multithreading is really needed here. However, I can't come up with relatively easy way to implement it.
You wrote in the first post of this topic that "PerfMonPDH has been architected to be multithreaded should the need arise".
What did you mean by it?
buckb
Posts: 34
Joined: February 12th, 2018, 12:47 am

Re: PerfMonPDH Performance Data Plugin

buckb » September 13th, 2018, 7:35 pm

rxtd wrote:You wrote in the first post of this topic that "PerfMonPDH has been architected to be multithreaded should the need arise". What did you mean by it?
I was referring to two aspects of the plugin and its parent/child model:
  • Data collection and processing is done in parent measures only. This helps to isolate the code that would need to run in separate threads.
  • Having child measures only consume data generated by parents enables the child measures to remain synchronized with one another. Suppose that the PDH data collection, instance matching, sorting, etc. is running in a separate thread. If a parent measure then grabs a snapshot of this performance data when it updates, all the associated child measures will see a consistent parent dataset.

--buckb