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:
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.
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.
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.
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,
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?
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".
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?
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.