1. cpu
多级缓存,32k -> 256k -> 20m
cat /sys/devices/system/cpu/cpu0/cache/index0/size
...
cat /sys/devices/system/cpu/cpu0/cache/index3/size
CPU Cache Line定义了缓存一次载入数据的大小
cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size 64
yum install perf
课程例子,按照内存顺序的访问利用缓存行可以带来性能的大幅提升
public class Test { public static void main(String args[]) { int TESTN = 4096; boolean slowMode = false; for (String arg : args) { if ("-f".equals(arg)) { slowMode = false; break; } else if ("-s".equals(arg)) { slowMode = true; break; } } char[][] arr = new char[TESTN][TESTN]; Date start = new Date(); if (!slowMode) { for (int i = 0; i < TESTN; i++) { for (int j = 0; j < TESTN; j++) { //arr[i][j]是连续访问的 arr[i][j] = 0; } } } else { for (int i = 0; i < TESTN; i++) { for (int j = 0; j < TESTN; j++) { //arr[j][i]是不连续访问的 arr[j][i] = 0; } } } System.out.println(new Date().getTime() - start.getTime()); } }
64 位操作系统的地址占用 8 个字节(32 位操作系统是 4 个字节),因此,每批 Cache Line 最多也就能载入不到 8 个二维数组元素,所以性能差距大约接近 8 倍
先排序的遍历时间只有后排序的三分之一,循环中有大量的 if 条件分支,而 CPU含有分支预测器,提前把这些指令放在缓存中,CPU 执行时就会很快。当数组中的元素完全随机时,分支预测器无法有效工作,而当 array 数组有序时,分支预测器会动态地根据历史命中数据对未来进行预测,命中率就会非常高
多线程并行访问不同的变量,这些变量在内存布局是相邻的(比如类中的多个变量),此时 CPU 缓存就会失效,java针对伪共享也做了填充等解决方案