Reputation: 351
I have executed the following query:
free -m
And output of this command is:
total used free shared buffers cached
Mem: 2048 2018 29 5 0 595
I want to get the size of the CPU cache. Is it possible to get the size of the cache and also what is the use of the cache here?
Upvotes: 18
Views: 29281
Reputation: 3476
First, there are several kinds/levels of caches, e.g. level 1 data, level 1 instruction, level 2, and level 3. In short, L3 cache is generally completely shared, and the other ones may be partly shared (e.g. L1 cache being private to each physical cores, but shared between the associated virtual cores when hyper-threading is used).
I'm going to complete myaut's answer (the lscpu
utility giving the total cache sizes for each kind of caches, /sys/devices/system/cpu/cpu*/cache/index*
giving per-cpu details). If you want to see the size of each individual cache and how the caches are shared, the best utility to my knownledge is lstopo
(for X11) or lstopo-no-graphics
(text output) from the hwloc project. The cpu-x
utility also gives information about the CPU caches.
For the per-cpu sizes, I use the following zsh script:
#!/usr/bin/env zsh
setopt EXTENDED_GLOB
for i in /sys/devices/system/cpu/cpu[0-9]#(n)
do
c=()
for j in $i/cache/index*
do
c+=("$(<$j/size) $(<$j/type)")
done
printf "%-6s %s\n" $i:t "${(j: / :)c}"
done
For instance, on my laptop, I get:
cpu0 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu1 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu2 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu3 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu4 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu5 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu6 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu7 48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu8 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu9 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu10 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu11 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu12 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu13 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu14 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu15 32K Data / 64K Instruction / 2048K Unified / 18432K Unified
Note that getconf
outputs non-deterministic values on heterogeneous x86 like the above one (at least with glibc 2.40). Do not use it on such a system.
Upvotes: 0
Reputation: 383170
getconf
getconf -a | grep CACHE
gives:
LEVEL1_ICACHE_SIZE 32768
LEVEL1_ICACHE_ASSOC 8
LEVEL1_ICACHE_LINESIZE 64
LEVEL1_DCACHE_SIZE 32768
LEVEL1_DCACHE_ASSOC 8
LEVEL1_DCACHE_LINESIZE 64
LEVEL2_CACHE_SIZE 262144
LEVEL2_CACHE_ASSOC 8
LEVEL2_CACHE_LINESIZE 64
LEVEL3_CACHE_SIZE 20971520
LEVEL3_CACHE_ASSOC 20
LEVEL3_CACHE_LINESIZE 64
LEVEL4_CACHE_SIZE 0
LEVEL4_CACHE_ASSOC 0
LEVEL4_CACHE_LINESIZE 0
Or for a single level:
getconf LEVEL2_CACHE_SIZE
The cool thing about this interface is that it is just a wrapper around the POSIX sysconf
C function (cache arguments are non-POSIX extensions), and so it can be used from C code as well:
long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);
Tested on Ubuntu 16.04 (Xenial Xerus).
x86 CPUID instruction
The CPUID x86 instruction also offers cache information, and can be directly accessed by userland.
glibc seems to use that method for x86. I haven't confirmed by step debugging / instruction tracing, but the source for 2.28 sysdeps/x86/cacheinfo.c
does that:
__cpuid (2, eax, ebx, ecx, edx);
TODO: Create a minimal C example, lazy now, asked at: How to receive L1, L2 & L3 cache size using CPUID instruction in x86
ARM also has an architecture-defined mechanism to find cache sizes through registers such as the Cache Size ID Register (CCSIDR), see the ARMv8 Programmers' Manual 11.6 "Cache discovery" for an overview.
Upvotes: 34
Reputation: 41
For ARM CPUs running Linux (tested on Raspberry Pi 3B+ with Raspbian (32 bit)):
In the "Arm® Cortex®-A53 MPCore Processor Technical Reference Manual" is a chapter, "Cache Size Selection Register" and "Cache Size ID Register", including assembler instructions.
These assembler instructions are already available as functions in the Linux kernel headers asm/cachetype.h: set_csselr(...) and read_ccsidr(), but these function can not be called in user mode, so we need to build a kernel module to get/print the values:
Makefile:
obj-m += cachesize.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
File cachesize.c:
#include <asm/cachetype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Abc defg");
MODULE_DESCRIPTION("Find out ARM cache sizes");
MODULE_VERSION("0.01");
static int __init lkm_example_init(void) {
// Must run in kernel mode
// Assumptions: L1 (instructions + data), L2 (check your CPU manual)
set_csselr(0);
printk(KERN_INFO "ccsidr L1 data cache = %08x\n", read_ccsidr());
set_csselr(1);
printk(KERN_INFO "ccsidr L1 instruction cache = %08x\n", read_ccsidr());
set_csselr(2);
printk(KERN_INFO "ccsidr L2 unified = %08x\n", read_ccsidr());
return 0;
}
static void __exit lkm_example_exit(void) {
printk(KERN_INFO "Goodbye, World!\n");
}
module_init(lkm_example_init);
module_exit(lkm_example_exit);
then:
make
insmode cachesize.ko
rmmod cachesize
dmesg | tail
# Compare numbers to the table "CCSIDR encodings" in the "ARM ... Technical Reference Manual"
Upvotes: 3
Reputation: 21
In my virtual machine (Linux dhcppc4 2.6.32-71.el6.i686 #1 SMP Wed Sep 1 01:26:34 EDT 2010 i686 i686 i386 GNU/Linux), I couldn't find /sys/devices/system/node, but lscpu certainly gives the details.
I see some more information in /sys/devices/system/cpu/cpu0/cache/*
:
cat /sys/devices/system/cpu/cpu0/cache/index0/size
32K
Upvotes: -1
Reputation: 11504
If you want to get the size of the CPU caches in Linux, the easiest way to do that is lscpu
:
$ lscpu | grep cache
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 15360K
If you want to get detailed information on each cache, check the sysfs file system:
$ SYSNODE=/sys/devices/system/node
$ grep '.*' $SYSNODE/node*/cpu*/cache/index*/* 2>/dev/null |
awk '-F[:/]' '{ printf "%6s %6s %24s %s\n" $6, $7, $9, $10, $11 ; }'
node0 cpu0 index0 level 1
node0 cpu0 index0 number_of_sets 64
node0 cpu0 index0 physical_line_partition 1
node0 cpu0 index0 shared_cpu_list 0,12
node0 cpu0 index0 shared_cpu_map 0000,00001001
node0 cpu0 index0 size 32K
node0 cpu0 index0 type Data
node0 cpu0 index0 ways_of_associativity 8
node0 cpu0 index1 coherency_line_size 64
Some cache instances will be seen multiple times (per each hardware thread), but you can check that in the shared_cpu_list
field.
Upvotes: 30