1

Essentially what I want is to extract the byte size of the L3 cache from lscpu. The tricky part is that the units lscpu uses is not consistent across versions and what I need has to work with all versions (including the versions before the --bytes option was available). lscpu from what I can see will either use K, KiB, M or MiB so that is what I'm trying to parse.

Here is what lscpu outputs:

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                16
On-line CPU(s) list:   0-15
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             16
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 60
Model name:            Intel Core Processor (Haswell, no TSX, IBRS)
Stepping:              1
CPU MHz:               2299.998
BogoMIPS:              4599.99
Virtualization:        VT-x
Hypervisor vendor:     KVM
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              4096K
L3 cache:              16384K
NUMA node0 CPU(s):     0-15
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single ssbd ibrs ibpb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat md_clear spec_ctrl

And this is what I have so far but can't seem to finish it off.

$ lscpu | awk '/L3 cache:/{print $3$4;next};/(M|MiB)$/{printf "%u\n", $3*(1024*1024);next};/(K|KiB)$/{printf "%u\n", $3*1024;next}'
0
32768
32768
4194304
16384K

Any ideas how to tweak my awk command to get this working?

Edit: My expected output would just be:

16777216
Cyrus
  • 84,225
  • 14
  • 89
  • 153
TreeWater
  • 761
  • 6
  • 13
  • `16777216` would be the output if the input was `16384KiB` but it's not, it's `16384K` and so the output should be `16384000` since 1K is 1000 while 1KiB is 1024. See https://en.wikipedia.org/wiki/Binary_prefix. – Ed Morton Jul 28 '21 at 04:23

3 Answers3

2

Really Cyrus' answer is the optimal, but if you're set on awk, try this:

 awk -F: 'BEGIN{def=1024}/^L3/{if($2~/M/){def=def*def}; printf "%u\n", $2*def}'
tink
  • 14,342
  • 4
  • 46
  • 50
  • This looks to be exactly what I need. Couldn't uses the solution from Cyrus, left details why in comment response. Thanks! – TreeWater Jul 27 '21 at 21:18
  • 1 question I do have going through is what is the purpose of using gsub here? Quick testing without it doesn't appear to change anything and I can't really pick up on what it is doing – TreeWater Jul 27 '21 at 21:31
  • Well, I'm just making sure that awk doesn't try to multiply M or K ... – tink Jul 27 '21 at 22:01
  • Apparently it doesn't bother awk if there are trailing alphas =} – tink Jul 27 '21 at 23:18
  • 1
    Right, when doing any numeric operation awk just ignores every char starting the first one it can recognize as not being part of a number. btw `def=def*def` = `def*=def` – Ed Morton Jul 28 '21 at 04:09
1

Get level 3 cache (L3) in bytes:

getconf LEVEL3_CACHE_SIZE
Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • getconf can't be used since it appears to pull it's info from `/sys/devices/system/cpu/cpu0/cache/` which is incomplete on some OS architectures (specifically RHEL s390x) so it just returns 0. lscpu pulls info from other sources so it is able to give values – TreeWater Jul 27 '21 at 21:14
1
$ cat tst.awk
BEGIN {
    mult["K"]   = 1000
    mult["KiB"] = 1024
    mult["M"]   = mult["K"]^2
    mult["MiB"] = mult["KiB"]^2
}
sub(/^L3 cache:/,"") {
    smbl = $NF
    sub(/[^[:alpha:]]+/,"",smbl)
    print $0 * mult[smbl]
}

$ awk -f tst.awk file
16384000
Ed Morton
  • 188,023
  • 17
  • 78
  • 185