@heartlocker commented on Mon Jul 24 2017
As the .NET Core project could run on Windows, Linux and Mac OS. Is it possible for me to get the PhysicalMemory size of the running machine on these three OS. Just like in .NET framework, by using Microsoft.VisualBasic.Devices.ComputerInfo
to get the Physical Memory information of the windows machine
@Petermarcu commented on Wed Jul 26 2017
@AlexGhiondea , should this issue be moved to CoreFX to make an API proposal?
@AlexGhiondea commented on Wed Jul 26 2017
@Petermarcu yes -- I will move it.
This is probably a larger discussion and API design we should have about how to get common system information in general across platforms.
Do we want "RuntimeInformation" to encompass this sort of thing? Although there's a real risk of it becoming a "grab bag of stuff" (and it sort of already is...), I'm not sure there's a better place for it.
That was the first thing I thought of. Yes, it may become a grab bag of stuff but hopefully its common information people want / need to know about the hardware, OS, etc. Kinda wish it wasn't under InteropServices but that ship has sailed :(
@mellinoe , do you want to carry this forward and make an API proposal with a basic set of capabilities?
There is some stuff already on Environment of course (and proposals for more --
https://github.com/dotnet/corefx/issues/16767)
Unless we've pivoted in this regard, then we don't want to be adding new stuff into legacy types like Environment
... we certainly could have changed our minds about that, though. That was kind of the impetus for developing RuntimeInformation
in the first place.
@mellinoe聽, do you want to carry this forward and make an API proposal with a basic set of capabilities?
Sure, I can come up with something. I'll try to come up with some reasonable basic set and see how different OS's expose that info.
It would be very helpful to add new class to System.Diagnostics used solely for the purpose of gathering all important information on the physical system even if this information would be available in other parts of framework. The reason is that besides of running on different operating systems .NET Core may run on different hardware (including IoT and mobile devices).
```C#
public class System.Diagnostic.Hardware/Machine
// with some of the properties
public static long PhysicalMemory; // (in bytes)
public static int ProcessorSockets;
public static int ProcessorCount;
public static int ProcessorCoreCount; // alternatively ThreadsPerCore (for SMT processors)
public static int USB2Ports;
public static int USB3Ports;
public static int GraphicsAccelerators;
public static int GraphicsMemory;
public static int DisplayCount ; // additional benefit - ability to detect headless hardware
public static int DisplayResolution (ppi)
public static int NetworkInterfaceCount;
public static long NetworkInterfaceSpeed;
public static int Gyroscope;
public static int GyroscopeAxisCount;
public static bool Gps;
public static bool Galileo;
public static bool Compass;
public static int Accelerometer;
public static int AccelerometerAxisCount;
public static int SpeakersCount;
public static int MicrophoneCount;
public static int CameraCount;
public static int CameraResolution; // pixels
public static int HardDriveCount;
public static int HardDriveCapacity;
public static int HardDriveType;
```
The code above is an oversimplified sketch since it would be necessary to provide details for every 'complex' hardware with breakdown of features for every individual device i.e. display, network interface, graphics accelerator, hdd etc.
In addition it would be possible to list here selectively only the device types which are currently supported by .NET Framework/Core or list all and throw PNSE for not supported devices i.e. Serial ports but not Jtag port (or PNSE exception for Jtag). This would provide additional level of information on framework for user communicating hardware support matrix of framework.
Another use case here is getting the identifier of various pieces of the hardware to know if you are on the same machine or a different one or if the hardware in the system has changed. Things like Processor Id, BIOS information, and Motherboard information.
There are some new capabilities in Linux kernel which could be useful for collecting hardware and performance data: Windows Management Instrumentation Now A Formal Bus With Linux 4.13. Kernel changes allow for fast feature uptake and can be safely used for forward looking feature implementation. I do not know very much about details of Linux WMI implementation so it would helpful to ask Linux experts for their opinion.
One thing that needs to be reflected in the API is that on some systems, or some configurations of systems, certain pieces of information will not be available, at all. If information is not available or permitted to be accessed by the system, that result should be expressible through the API itself, not as an exception. We can choose a "least common denominator" set of things that we KNOW will be available everywhere, but that isn't useful, especially not for a query API like this.
The NetworkInformation types, which I ported a while back to Linux and macOS, are a very good example of what NOT to do in this kind of API. They throw PlatformNotSupportedException's all over the place because many pieces of information are either inaccessible, represented differently, or just plain don't make sense for non-Windows platforms. These API's were never designed to be used outside of Windows, so it's not a surprise that they don't work well on Linux or Mac.
The NetworkInformation types, which I ported a while back to Linux and macOS, are a very good example of what NOT to do in this kind of API
Agree that PSNE exception is not very useful type of information from hardware query. But in principle what has to be presented to user this is the following matrix of capabilities:
This could be encapsulated in simple enum and property plus capabilities query i.e.:
```C#
public enum HardwareInfo
{
Unknown = 0,
NoInfo,
NoInfoOnPlatform,
NoAccess,
Partial,
Full
}
public abstract class DeviceInfo
{
public HardwareInfo HardwareInfo { get; protected set; }
// Capabilities query similar to RuntimeInformation
public abstract HardwareInfo IsSupported(string queryCapability);
}
[Flags]
public enum ProcessorConfiguration
{
Unknown = 0,
SymmetricMultiProcessing = 1,
BigLittle = 2,
// APU means that processor contains general purpose CPU core(s) and some accelerators
ApplicationProccessingUnit = 4,
GraphicsAccelerator = 8,
FpgaAccelerator = 16,
AiAccelerator = 32
}
public class ProcessorInfo : DeviceInfo
{
public int SocketsCount { get; protected set; }
public int ProcessorCount { get; protected set; }
public enum ProcessorConfiguration { get; protected set; }
// Override abstract IsSupported
public override HardwareInfo IsSupported(string queryCapability)
{
switch(queryCapability)
{
case namof(SocketsCount):
return QuerySocketsCountCapabilities();
case nameof(ProcessorCount):
return QueryProcessorCountCapabilities();
case nameof(ProcessorConfiguration):
return QueryProcessorConfigurationCapabilities();
default:
throw new ArgumentException(nameof(queryCapability));
}
}
}
public class SmpProcessorInfo : ProcessorInfo
{
public int CoreCount {get; protected set; }
public int ThreadsPerCore { get; protected set; }
public InstructionSet InstructionSet { get; protected set; }
// Override abstract IsSupported
public override HardwareInfo IsSupported(string queryCapability)
{
// implementation
}
}
// First look at this problem
public class BigLittleProcessorInfo : ProcessorInfo
{
public CoreType[] CoreTypes { get; protected set; }
public IReadOnlyDictionary
public IReadOnlyDictionary
public IReadOnlyDictionary
// Override abstract IsSupported
public override HardwareInfo IsSupported(string queryCapability)
{
// implementation
}
}
// Most important values i.e. for SIMD intrinsics
[Flags]
public enum CpuidX86 : ulong
{
Unknwown = 0,
// No values set at this stage
Sse,
Sse2,
Sse3,
Ssse3,
Sse41,
Sse42,
Avx,
Avx2,
Avx512, // This one has to be more complex
Aes,
Fma,
Tsx,
.....
}
public struct CpuidValue
{
public uint EAX;
public uint EBX;
public uint ECX;
public uint EDX;
}
public class X86ProcessorInfo : SmpProcessorInfo
{
public CpuidX86 Cpuid { get; protected set; }
public int FirstLevelCache { get; protected set; }
public int SecondLevelCache { get; protected set; }
public bool IsSecondLevelCacheShared { get; protected set; }
public int ThirdLevelCache { get; protected set; }
public bool IsThirdLevelCacheShared { get; protected set; }
// other items ......
// Override abstract IsSupported
public override HardwareInfo IsSupported(string queryCapability)
{
// implementation
}
public static CpuidValue GetCpuid(uint eaxQueryValue) { }
}
public class PowerProcessorInfo : SmpProcessorInfo
{
....
}
public class ArmSmpProcessorInfo : SmpProcessorInfo
{
....
}
public class ArmBlProcessorInfo : BigLittleProcessorInfo
{
....
}
public class Hardware
{
public static HardwareInfo IsSupported(string queryCapability)
{
switch(queryCapability)
{
case namof(ProcessorInfo):
return QueryProcessorInfoCapabilities();
// ......
}
// could be null - in this case check what is the reason
public static ProcessorInfo ProcessorInfo { get; private set; }
// all other devices
}
// usage
var processor = Hardware.ProcessorInfo;
if (processor is ArmSmpProcessorInfo armProc)
{
// use armProc in code
}
else if (processor is X86ProcessorInfo x86Proc)
{
// use x86Proc
}
else
{
var support = Hardware.IsSupported(nameof(Hardware.ProcessorInfo));
// use support info
}
```
This is loose outline how it can be done for processor. I think that this kind of pattern which tries to get only hardware features and not OS hardware abstractions would be most meaningful one and would escape problem of being not present in given OS. If info is not available one can query support.
Above example could be very useful for determining SIMD support on given platform - see issue dotnet/corefx#22843
@mellinoe , should we start a prototype or two in corefxlab and start filling in some of these ideas?
@mellinoe @Petermarcu I would volunteer to do some work in such project if team would be interested
@ericstj as well. Let's see if we can get a proposal together and get a project rolling.
I've been thinking about this and wanted to share a few principles that we should remember from past API.
Things like CPU cores|clock|cache and memory all make sense for potentially making CPU vs memory tradeoffs. Some set of hardware identifiers that are exceptionally stable may make sense for machine identification.
I'm not sure about the others (eg: camera, display, gps, etc): how would someone make use of those without some sort of abstraction for actually interacting with those devices?
If folks can enumerate some more scenarios that would help.
Are there relevant de facto standards for this info - such that libraries exist on both Unix and Windows? Perhaps then our API could be relatively thin?
For device enumeration Windows has Setup API and WMI. Setup API was never something we had inbox in .NET (though many folks have written wrappers) but we did have System.Management for WMI. I believe the equivalent is on linux is libudev. I haven't looked at Linux's WMI implementation @4creators mentioned above but that'd be something to examine as part of the System.Management issue.
I still question how useful device enumeration is without having some common way of interacting with the devices. For instance: what good is it to know the machine has a GPU unless I can give it work to do? What good is it to know that the machine has a GPS unless I can read its coordinates?
I think we need to fully describe the scenarios we're trying to enable to make sure we're scoping this correctly. "Wrap device enumeration" while interesting is probably not something we want to lump together with "expose the amount of memory and CPUs available on the machine". I think we should scope this issue down to some key scenarios then design the API that fits those.
@mellinoe are you still planning on working on a proposal for this? @ericstj brings up very valid points that should be considered in that proposal, so if you do please consider scenarios of why would it be useful to expose some of this info.
I don't really have more time at the moment for this, maybe in the coming weeks.
ok, flagging it as up-for-grabs then so that if anybody else is interested on this they can throw a proposal.
@joperezr
Hi, is this issue for starters?
I need this feature, and I see it marked as 'up-for-grabs'.
How long do you think it will take to develop the feature for Linux and Apple?
I need to grasb Linux harware info such as following
some java code is as following
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
ComputerSystem computerSystem = hal.getComputerSystem();
CentralProcessor processor = hal.getProcessor();
NetworkIF[] networkIFs = hal.getNetworkIFs();
final Firmware firmware = computerSystem.getFirmware();
1 Model via computerSystem.getModel())
2 ProcessorId via processor.getProcessorID())
3 firmware version via firmware.getVersion())
4 network mac address via if(networkIFs.length > 0) { networkIFs[0].getMacaddr()) }
5 linux machineId
Can anybody help me in it?
Even if somebody point me to third party nuget package then it will also be helpful
@baruchiro I'm not super familiar with RuntimeInformation but it seems to be that we mostly just get all the current information from Pinvoking into native functions like the following:
I'm not sure if all the requested information will be easy to get on all of our supported Unix distros, but I think that is the point of this issue. The idea is to find if there is extra runtime information that we can consistently get across all of our supported OSes without introducing new dependencies (like the need to install a new native dependency on the system). Once that is found, we will need to find an Api proposal that will have to pass through a review to see if this is something we want to add to the framework, and if it is, then we will add it. Here is a list of the next steps to do here:
Hi!
Is there any estimate of when this should be implemented?
I think this should be implemented as soon as possible. .NET Core is about 3.0, this issue is not suitable for Future
.馃槃
We currently don't have good consensus on a API to detect runtimes, if you are concerned with something other than that feel free to open a new issue for that.
@joperezr, there were several open issues that were merged into this issue (such as https://github.com/dotnet/standard/issues/327).
I'm not sure I fully understand what exactly you mean by "detect runtime," but I miss the ability to check the hardware of the computer I'm running (more specifically CPU, memory, motherboard etc..) and the amount of computer resource that in use / free (CPU, memory, etc...)
https://github.com/dotnet/standard/issues/327 definitely seems like a separate issue from this one (though it should clearly be an issue in dotnet core.)
really need for this
@WeihanLi What are the specific bits of information you need?
Hi @jkotas , I wanna develop a monitor service, monitor the system cpu/memory/disk usage, if some usage above the level custom defined, send email or do something else to notify someone.
Currently, mainly for system memory & disk usage
@WeihanLi None of the APIs listed in this issue return system cpu/memory/disk usage.
I came here from the issue here https://github.com/dotnet/standard/issues/327 , should I open a new issue here? @jkotas
---------- Update -----------
open a new issue here https://github.com/dotnet/corefx/issues/38914
when support get hardware infomation across OS?
These apis are urgently needed.
yeah NodeJs has this since the inception
var os = require('os');
console.log(os.cpus());
console.log(os.totalmem());
console.log(os.freemem())
So I guess there is no update on this ?
Would be nice at lest get direct access to cpuid instruction without needing to create bytecodes for this manually...
I have done a workaround to get hardware info as per Platform. For windows I have used old way of system Management classes, for Linux i have used different Bash commands to Get Processor Id, Model,model version,machine id.
Following are some linux commands i am using
**1. "LinuxModel": "cat /sys/class/dmi/id/product_name"
Waiting for some support in the .net core framework soon
@KamranShahid Thank you for the workaround. I think we need to offer workarounds here, since it doesn't seem the .NET team planning to solve it soon.
In my company, we also use
6. "LinuxTotalMemory": "awk '/MemTotal/ {print $2}' /proc/meminfo"
@KamranShahid Thank you for the workaround. I think we need to offer workarounds here, since it doesn't seem the .NET team planning to solve it soon.
In my company, we also use
6. "LinuxTotalMemory": "awk '/MemTotal/ {print $2}' /proc/meminfo"
Agreed @baruchiro . I have same motive to help-out others till there comes something supported in the framework
Since there is so much possible information about each subject to get, maybe there should be separate classes for memory, processor and all the other topics. There is already DriveInfo
that can be used on Linux as well if you initialise it with the path you're interested in. All these classes could be grouped in some "system/hardware information" namespace.
But then again, does this have to be in the framework itself? Couldn't we just create a NuGet package for that?
The advantage of having your own nuget package is that you can update much more quickly, without going through the .NET team and waiting for their releases.
In my mind, the framework should contain the "enduring basics" especially ones that have a clear, efficient implementation. And for more elaborate things - it would be great to have a community package.
@danmosemsft I agree. I can't lead a package myself, but I'm ready to join one today.
@danmosemsft I completely agree.
Moreover, there is already proven solution in the form of hwloc which also has python and rust bindings and is supported on Linux/Windows/Mac.
It would make sense to provide cross platform bindings through hwloc and get the breadth of information it already provides from the ability to generate complete topologies including:
I think this screenshot of lstopo of an AMD ThreadRipper 3970x best summarizes what can be gleaned from it:
I'd like to add another unfortunate data-point to this discussion.
I think that when possible, the relevant hardware information should be considered as JIT time constants to help select the proper code path.
One recent and very unfortunate case I've encountered is PDEP
on AMD systems:
https://twitter.com/trav_downs/status/1203425075896225792
To summerize: While AMD processors officially support this opcode, it is really implemented in microcode via a loop and might execute anywhere between 18-289 cycles.
The only proper way to handle such erratic CPU behaviour (and it's really not the last, nor the first time this sort of thing happens and will continue to happen) is to provide the above mentioned HW information to developers while also making sure that the JIT can and will treat this information (CPU model, family, manufacturer, cache line sized, etc.) as a constant when it comes to code-generation.
If this feels like I'm just piling on to an existing issue, let me know, I will gladly open a separate issue for this.
@damageboy That sounds like very specific data for a rare use case, far from simply gathering the most basic data about the system environment, like free RAM or system-wide CPU usage. But when I glance over this issue again, it seems to go in that direction altogether.
So maybe I should ask to include just free/total RAM information and some CPU usage counters into .NET, maybe the Environment
class, and leave all those tiniest details (that only apply to certain environments) to a third-party package?
@damageboy could you open a new issue for that (interesting, though)?
So maybe I should ask to include just free/total RAM information and some CPU usage counters into .NET
RAM info should be already on the Process class (notwithstanding this recent fix)
@danmosemsft Ehm, I'm talking about the system total and system free memory, not the used memory by a single process. AFAIK this information is not available up to .NET Core 2.2, probably also not in 3.1. I could not find suitable Windows API functions. There's the Linux free
command to determine those. I'm especially interested in separate numbers for buffers/cache memory usage to determine the actual memory need, not including caches that fill up the free memory. Basically everything from here:
$ free -h
total used free shared buff/cache available
Mem: 15G 5.4G 726M 1.3G 9.2G 8.3G
Swap: 4.0G 100M 3.9G
CPU counters could be used to determine how much the CPU is currently used. In Linux there are different counters, available with iostat
:
avg-cpu: %user %nice %system %iowait %steal %idle
5.00 0.00 0.69 7.25 0.00 87.06
@ygoe oh of course - my bad.
OK, to make this issue concrete -- I think we need a concrete API proposal
@richlander you have spent a lot of time thinking about the memory and CPU counters that the runtime itself should read (for example, to properly respect limits on a container). Any thoughts here?
GC.GetGCMemoryInfo
is the (container-aware) API added in 3.0 that returns memory details about memory used and available.
GetGCMemoryInfo doesn't sound like it would return system-wide data.
Returning non-virtualized system-wide data does not make sense in containers.
Yeah, but I'm not using containers. 馃槈 I'm fully aware that inside containers you have a very limited view on the host system.
@jkotas: that is really on a case-by-case basis, no?
CPU manufacturer and cache layout, for example, make a lot of sense and remain constant for all cases (unless the virtualization engine is lying to you by emulating CPUID), while the more often virtualized properties have to be the virtualized/containerized versions too.
Specifically, CPU topology and memory would have to be container aware.
Virtualization is already good at exposing the virtual values through the normal "APIs".
It would take herculean efforts to read/access the physical/host properties in a virtualized system.
Some of my projects are planning to be hosted in Linux but I can't get the hardware info. Is there any update on this? or anybody will be working on this?
I find java they have oshi but all net core are talking about the "RuntimeInformation"
Some of my projects are planning to be hosted in Linux but I can't get the hardware info. Is there any update on this? or anybody will be working on this?
I find java they have oshi but all net core are talking about the "RuntimeInformation"
At the current time you have to be specific about what hardware information currently you requires. There are limited support and some workaround as listed above which can be used scenario by scenario
@KamranShahid
I think you will find partial overlap between what you want and what WILL be provided in:
https://github.com/dotnet/runtime/issues/785
@KamranShahid the specific hardwares are cpu, disk, network, board, memory, the information include the name, unique id, manufacture or some other infomations wihch like the WMI can provided before. some of the product require a license based on the hardware and now we need to rewrite this in C++ insead of .net core.
find this MatthewKing/DeviceId
@KamranShahid the specific hardwares are cpu, disk, network, board, memory, the information include the name, unique id, manufacture or some other infomations wihch like the WMI can provided before. some of the product require a license based on the hardware and now we need to rewrite this in C++ insead of .net core.
It s up-to you. Mine problem was solved as per above hack that time
I find the following names ambiguous, is this indicating the cache exists? it's size and if so what metric. (Potentially only comments but a better name would also help)
c#
public int FirstLevelCacheSize { get; protected set; }
public int SecondLevelCache { get; protected set; }
public int ThirdLevelCache { get; protected set; }
What I am mainly looking for out of this is an easy way to determine when tis best to ATTEMPT to go parallel, see https://github.com/dotnet/runtime/issues/37602 for further info.
Thank you for your time!
Most helpful comment
Another use case here is getting the identifier of various pieces of the hardware to know if you are on the same machine or a different one or if the hardware in the system has changed. Things like Processor Id, BIOS information, and Motherboard information.