ThePhD / infoware

C++ Library for pulling system and hardware information, without hitting the command line.
Creative Commons Zero v1.0 Universal
412 stars 85 forks source link

Handle Macs' CPUs better #12

Closed nabijaczleweli closed 5 years ago

nabijaczleweli commented 5 years ago

11 happened because the Mac the author was using didn't have /proc/cpuinfo – there should probably be either (a) an alt name for /proc/cpuinfo or (b) some other way of getting that data out of Macs.

nabijaczleweli commented 5 years ago

Turns out neither me nor PhD have a Mac so, if someone wants to contribute in some way – the comments on this issue and PRs are always open

corbin-r commented 5 years ago

I have a MacBook Pro so I can help with diagnosing and fixing this.

corbin-r commented 5 years ago

According to this source. All that has to be called is sysctl -a | grep machdep.cpu this returns a list similar to cat /proc/cpuinfo

nabijaczleweli commented 5 years ago

So there's no way to do it without spawning another process? Sucks, but workable.

OTOH, I can't seem to find the clock freq in the screenshot in the blog post?

corbin-r commented 5 years ago

Sadly yes, another process will have to be spawned but, clock freq is reported using: sysctl -n machdep.cpu.brand_string, granted it spits out the entire CPU model: Intel(R) Core(TM) i5-6287U CPU @ 3.10 GHz (example from my MacBook Pro).

Since all that would be needed is the clock, substr could be used, I can look to see if there's other options because getting the entire CPU model name and only using the clock would be kind of a waste.

EDIT I found another potential answer: sysctl hw.cpufrequency this spits out (from my MBP): hw.cpufrequency: 3100000000, this appears more inline with what cat /proc/cpuinfo spits out for clock req (see: cpu Mhz reported by cat /proc/cpuinfo) (ref: https://apple.stackexchange.com/questions/229407/cli-get-cpu-real-speed-e-g-intel-speedstepping)

nabijaczleweli commented 5 years ago

Since machdep.cpu.brand_string is, well, the CPU's branding, it's (a) not guaranteed to contain the freq, and (b) will not take into account any sort of clock variation (OC, &c.).

For now, could you check with the cpu example on the enchancement/darwin-cpu if the sysctl-based frequency acquiring method works for you?

corbin-r commented 5 years ago

Absolutely, I'll give it a shot. I'll let you know in a little bit.

nabijaczleweli commented 5 years ago

Oh, and, @cgmx, if you'd be so kind, do /sys/devices/system/cpu/cpu0/cache/index{1,2,3}/ and children exist on OSX?

corbin-r commented 5 years ago

Unsure, I'll take a look however.

corbin-r commented 5 years ago

Okay: /sys/devices/system/cpu/cpu0/cache/index{1,2,3}/ does not exist, as macOS in Apple's infinite or not so infinite wisdom doesn't have /sys/. However, according to this reference you can retrieve cache size via: sudo sysctl -a | grep cache This will return a list of all cache information in the system (on macOS):

kern.flush_cache_on_write: 0
kern.kernelcacheuuid: 484E1E3E-8A71-68FE-7DAE-CAFF66FF04C7
kern.namecache_disabled: 0
vm.vm_page_filecache_min: 1257508
vm.enforce_shared_cache_dir: 1
vfs.generic.nfs.client.access_cache_timeout: 60
vfs.generic.nfs.client.readlink_nocache: 0
vfs.generic.nfs.server.reqcache_size: 64
net.inet.ip.rtmaxcache: 128
net.inet.tcp.clear_tfocache: 0
net.inet6.ip6.rtmaxcache: 128
hw.cacheconfig: 4 2 2 4 0 0 0 0 0 0
hw.cachesize: 17179869184 32768 262144 4194304 0 0 0 0 0 0
hw.cachelinesize: 64
hw.l1icachesize: 32768
hw.l1dcachesize: 32768
hw.l2cachesize: 262144
hw.l3cachesize: 4194304
machdep.cpu.cache.linesize: 64
machdep.cpu.cache.L2_associativity: 4
machdep.cpu.cache.size: 256
security.mac.asp.cache_entry_count: 2406
security.mac.asp.cache_allocation_count: 2424
security.mac.asp.cache_release_count: 18
nabijaczleweli commented 5 years ago

Thanks, I hate it!

nabijaczleweli commented 5 years ago

Alright! This (mostly) covers all funxions that relied on cpuid. Could you run the CPU example on the enchancement/darwin-cpu?

corbin-r commented 5 years ago

Hey sorry, I'll get testing this. Had a crazy weekend and couldn't get to it.

corbin-r commented 5 years ago

Here's the output from CPU example:

  Quantities:
    Logical CPUs : 16
    Physical CPUs: 8
    CPU packages : 1

  Caches:
    L1:
      Size         : 65536B
      Line size    : 64B
      Associativity: 0
      Type         : Unified
    L2:
      Size         : 262144B
      Line size    : 64B
      Associativity: 0
      Type         : Unified
    L3:
      Size         : 4194304B
      Line size    : 64B
      Associativity: 0
      Type         : Unified

  Architecture: x64
  Frequency: 3100000000 Hz
  Endianness: Little-Endian
  Model name:  Intel(R) Core(TM) i5-6287U CPU @ 3.10GHz
  Vendor ID: GenuineIntel

  Instruction set support:
    3D-now!: false
    MMX    : true
    SSE    : true
    SSE2   : true
    SSE3   : true
    AVX    : false
corbin-r commented 5 years ago

I can tell you right off the bat it's identifying my core quantities wrong. The i5-6287U Has: 4 logical CPUs, 2 physical CPUs, and 1 CPU package.

nabijaczleweli commented 5 years ago

Thanks! Hmm, weird... What does sysctl machdep.cpu say?

corbin-r commented 5 years ago

Interesting, so machdep.cpu.logical_per_package and machdep.cpu.cores_per_package print the same as my test output from enchancement/darwin-cpu. However: machdep.cpu.core_count and machdep.cpu.thread_count reports: 2 & 4.

So this is actually correct:

c = core
lc = logical core
t = thread
p = package

2c + 4t = 8c/p * 2 = 16lc/p
corbin-r commented 5 years ago

Only explanation I have for this is that "logical per package" is taking into account the total amount of physical & logical cores/threads (2 cores + 4 threads) * 2 (because of HyperThreading), so technically yes this would be "16 logical 'CPUs' per package".

nabijaczleweli commented 5 years ago

Oh, thanks, musta missed those keys when looking through the logs!

If the latest commits on enchancement/darwin-cpu fix the count and odd spacing of model_name() then this is g2g!

corbin-r commented 5 years ago

Oh you're way good! macOS doesn't make it easy like any other Linux distro sadly. I'll run another test and then let you know

corbin-r commented 5 years ago

Just pulled latest changes from enchancement/darwin-cpu, CPU example output still reports:

Quantities:
    Logical CPUs: 16
    Physical CPUs: 8
    CPU Packages: 1
corbin-r commented 5 years ago

Also per your comment here, there will always be 1 package as no Mac systems have more than one package (>1 CPU)

Edit Unless in the off chance someone runs this on an old Apple XServe unit but this case is highly unlikely.

nabijaczleweli commented 5 years ago

wait what theh ell I changed it to use machdep.cpu.{core_count,thread_count} and you said those were the right ones aaaaaaaaaAAAAAAAAAAAAA

corbin-r commented 5 years ago

It's all good. We'll figure this out... Like I said what the system logic is doing (at least my hypothesis is), that it's taking into account ALL available packages, taking the physical core count which would be:

Logical CPUs: 4
Physical CPUs: 2
CPU Packages: 1

Remember with Intel HyperThreading whatever physical count of CPUs (in terms of physical cores) you have, effectively double as HyperThreading creates logical CPUs based off your physical ones: (For example on my MBP): 2 cores (physical) -> 4 cores (logical w/HyperThreading) 4 threads (physical) -> 8 threads (logical w/HyperThreading)

So after thinking about this more, that printout from infoware is correct it just isn't showing "physical" core package, it's showing total core package (which takes into account HyperThreading). I might be wrong but this seems to be what it's doing.

corbin-r commented 5 years ago

I'm going to do a little more digging into Intel's SMT methodology and see if this is actually the case.

corbin-r commented 5 years ago

I'm going to do a little more digging into Intel's SMT methodology and see if this is actually the case.

naav commented 5 years ago

Works for me. iMac 17,1 with Intel i5 6600:

$ sysctl -a | grep machdep.cpu.*count
machdep.cpu.core_count: 4
machdep.cpu.thread_count: 4

$ ./out/examples/cpu 

  Quantities:
    Logical CPUs : 4
    Physical CPUs: 4
    CPU packages : 1

  Caches:
    L1:
      Size         : 65536B
      Line size    : 64B
      Associativity: 0
      Type         : Unified
    L2:
      Size         : 262144B
      Line size    : 64B
      Associativity: 0
      Type         : Unified
    L3:
      Size         : 6291456B
      Line size    : 64B
      Associativity: 0
      Type         : Unified

  Architecture: x64
  Frequency: 3300000000 Hz
  Endianness: Little-Endian
  Model name: Intel(R) Core(TM) i5-6600 CPU @ 3.30GHz
  Vendor ID: GenuineIntel

  Instruction set support:
    3D-now!: false
    MMX    : true
    SSE    : true
    SSE2   : true
    SSE3   : true
    AVX    : false
nabijaczleweli commented 5 years ago

Well git pulled, Cicada. Cheers.

nabijaczleweli commented 5 years ago

Changes landed in master, closing.