Пытаюсь использовать awk для анализа вывода lscpu, но не могу сделать это правильно

#linux #awk #s390x

Вопрос:

По сути, я хочу извлечь размер кэша L3 в байтах из lscpu. Сложность заключается в том, что единицы измерения, используемые lscpu, не согласованы между версиями, и то, что мне нужно, должно работать со всеми версиями (включая версии до того, как была доступна опция —bytes). lscpu из того, что я вижу, будет использовать либо K, KiB, M, либо MiB, так что это то, что я пытаюсь проанализировать.

Вот что выводит lscpu:

 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
 

И это то, что у меня есть до сих пор, но, похоже, я не могу с этим покончить.

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

Есть идеи, как настроить мою команду awk, чтобы это сработало?

Редактировать: Мой ожидаемый результат будет просто:

 16777216
 

Комментарии:

1. @anubhava обновленный вопрос

2. 16777216 был бы вывод, если бы вход был 16384KiB , но это не так, это 16384K так, и поэтому вывод должен быть 16384000 , так как 1 КБ равно 1000, а 1 КБ равно 1024. Видишь en.wikipedia.org/wiki/Binary_prefix .

Ответ №1:

На самом деле ответ Сайруса является оптимальным, но если вы настроены на awk, попробуйте это:

  awk -F: 'BEGIN{def=1024}/^L3/{if($2~/M/){def=def*def}; printf "%un", $2*def}'
 

Комментарии:

1. Похоже, это именно то, что мне нужно. Не смог использовать решение от Сайруса, оставил подробную информацию о том, почему в ответе на комментарий. Спасибо!

2. 1 вопрос, который у меня есть, заключается в том, какова цель использования gsub здесь? Быстрое тестирование без него, похоже, ничего не меняет, и я действительно не могу понять, что он делает

3. Ну, я просто хочу убедиться, что awk не пытается умножить M или K …

4. По — видимому, это не беспокоит awk, если есть конечные альфы =}

5. Правильно, при выполнении любой числовой операции awk просто игнорирует каждый символ, начиная с первого, который он может распознать как не являющийся частью числа. кстати def=def*def = def*=def

Ответ №2:

Получите кэш 3-го уровня (L3) в байтах:

 getconf LEVEL3_CACHE_SIZE
 

Комментарии:

1. getconf нельзя использовать, так как он, по-видимому, извлекает информацию, /sys/devices/system/cpu/cpu0/cache/ которая является неполной в некоторых архитектурах ОС (в частности, RHEL s390x), поэтому он просто возвращает 0. lscpu извлекает информацию из других источников, чтобы она могла давать значения

Ответ №3:

 $ 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