Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report CPU usage by core #42

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

MathiasMagnus
Copy link

Because nobody seemed to get the ball rolling on this (and it would be mighty useful) I thought I'd get things going by doing part of the work, hoping others will pick up the other, seemingly more involved part: hooking the info up to UI. This draft PR addresses #9.

If you would like to see this feature happen, please tune into development

Per-core CPU load reads on Windows AFAIK is only available through WMI, which is a C++ API. While WMI may be operable from COM alone, that's like flying an X-Wing blindfolded, which I don't intend to do. For the purpose of enabling per-core reading (and later GPU readings, which was also requested) this implementation adds a C++ translation unit exposing a C API.

Notes:

  • The implementation uses the C++/WinRT wrapper for handling COM more tersely. There are no calls to the Windows Runtime. (Not that I'm aware of.) If someone really wants to unroll the COM wrappers, be my guest.
  • The /permissive flag added to the C++ source file is a temporary workaround to a bug in C++/WinRT, generating non-strictly ISO C++ headers. This should be fixed in a future version of the Windows SDK.
  • The implementation uses WIL for two tiny parts of the code, both can be easily removed if dependencies are a hassle
    • wrapper for the BSTR type
    • wrapper for the VARIANT type
  • The prototype was a C++ application independent of NTop, I left it in comments for reference.
    • The C version (omitting error handling) is in main.c.
    • These parts should be removed in final versions, I just left them to show how to use the C API.
  • Added generator expression in CMake for declarative option handling as opposed to imperative branching.

Call to action

If someone is interested (either @gsass1 or anyone else) in hooking this information up to the UI, which too is a non-zero amount of work, help push it through the finish line. I did this part, because I saw that obtaining this info was non-trivial (to say the least) and if this was blocking people from making it happen: now it's done.

@gsass1
Copy link
Owner

gsass1 commented Jul 26, 2021

Thanks @MathiasMagnus! CPU-usage by core is definitely something that should be added into NTop. Actually I worked on this a while back: https://github.com/gsass1/NTop/tree/multiple-cpus, albeit instead of WinRT I used the PDH. I'm not too sure if what I wrote even worked though.

Right now I can't work too much on NTop, mainly because I don't have enough time and I barely use Windows for development anymore. But if only hooking up the loads to the UI is left, then I can work on that in the following days. Then when that's done we can discuss WinRT vs PDH.

@MathiasMagnus
Copy link
Author

@gsass1 Thanks for pointing to your working branch. AFAICT the only thing left is hooking the info up to the UI.

The provider in this PR is WMI (Windows Management Infrastructure) which is an API to control/query just about anything on the system. WMI reads the CPU load as seen by the kernel. My implementation is sub-optimal in the sense that every refresh it creates a new enumerable query using WQL (Windows Query Language) which is a subset of SQL limited to queries only. I would expect WMI to do some kind of caching and if I query the same thing over and over again, it's not going to parse the WQL string again and again. The more optimal way is to create a refresher object which subscribes to some metric (CPU load eg.) and a refresher object means that this metric will be queried over and over again. However, refresher objects seem to only have addObjectByPath routines and no WQL, and I've not figured out yet how to set a refresher to an enumerable query using the object path to Win32_PerfFormattedData_PerfOS_Processor.

For the time being, this works (see the console application in the PR which does nothing just spews core loads to the console). In the long run I'd like to convert the query to use IWbemConfigureRefresher which communicates just the situation NTop does: ask the kernel to measure some metric constantly as it will be continuously queried in the future.

@MathiasMagnus
Copy link
Author

@gsass1 I've seen you haven't pushed new work to your working branch. Just wanted to let you know I started tinkering with both displaying the info and reducing CPU load by moving to IWbemConfigureRefresher and IWbemHiPerfEnum. You shouldn't beat yourself up over having to get there. Of course, anyone is willing to beat me/us to the punch, as my hobby tinker time is extremely limited. I'll try pushing my work in sensible batches to help others, who may want to pick up on my work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants