日期:
来源:阿里开发者收集编辑:王再军(曦峰)
阿里妹导读
本文用实际用例阐述了用心组织的代码也能让性能提升百倍,我们不应该停留在CRUD的漩涡中。下面来看看这个神奇的现象。
一、震惊,这代码居然有差别!
二、为什么会有性能差别?
首先,我们需要知道Java二维数组的存储结构是什么样子的。 其次,我们需要知道CPU在计算的时候它L1、L2、L3的缓存机制。
2.1 知识点
2.1.1 知识点一 -- Java二维数组的存储结构
2.1.2 知识点二 -- CPU的缓存机制
L1 、L2、L3、主存 的大小是逐渐增大,速度是逐渐减小的。
2.2 性能损失的原因 -- 缓存命中率
2.2.1 友好的遍历方式
2.2.2 不友好的遍历方式
三、总结
四、附件
4.1 运行的环境
系统参数: JMH version: 1.36VM version: JDK 11.0.13, Java HotSpot(TM) 64-Bit Server VM, 11.0.13+10-LTS-370型号名称:MacBook Pro型号标识符:MacBookPro15,2处理器名称:四核Intel Core i5处理器速度:2.4 GHz处理器数目:1核总数:4L2缓存(每个核):256 KBL3缓存:6 MB超线程技术:已启用内存:16 GB系统固件版本:1715.60.5.0.0 (iBridge: 19.16.10647.0.0,0)
ArrayTestBenchmark import org.openjdk.jmh.annotations.*;/*** 矩阵 C = AB 的计算** @author wzj* @date 2023/02/09*/@BenchmarkMode(Mode.AverageTime)@State(value = Scope.Benchmark)// 预热3次@Warmup(iterations = 3, time = 1)// 循环 10 次@Measurement(iterations = 10, time = 1)public class ArrayTestBenchmark {private final int N = 1000;private final int[][] arrays_A = new int[N][N];private final int[][] arrays_B = new int[N][N];@Setuppublic void setUp() {for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {arrays_A[i][j] = i + j;arrays_B[i][j] = i + j;}}}@Benchmarkpublic void ijk() {final int[][] arrays_C = new int[N][N];for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {int sum = 0;for (int k = 0; k < N; k++) {sum += arrays_A[i][k] * arrays_B[k][j];}arrays_C[i][j] += sum;}}assert arrays_C.length > 0;}@Benchmarkpublic void jik() {final int[][] arrays_C = new int[N][N];for (int j = 0; j < N; j++) {for (int i = 0; i < N; i++) {int sum = 0;for (int k = 0; k < N; k++) {sum += arrays_A[i][k] * arrays_B[k][j];}arrays_C[i][j] += sum;}}assert arrays_C.length > 0;}@Benchmarkpublic void jki() {final int[][] arrays_C = new int[N][N];for (int j = 0; j < N; j++) {for (int k = 0; k < N; k++) {int r_B = arrays_B[k][j];for (int i = 0; i < N; i++) {arrays_C[i][j] += arrays_A[i][k] * r_B;}}}assert arrays_C.length > 0;}@Benchmarkpublic void kji() {final int[][] arrays_C = new int[N][N];for (int k = 0; k < N; k++) {for (int j = 0; j < N; j++) {int r_B = arrays_B[k][j];for (int i = 0; i < N; i++) {arrays_C[i][j] += arrays_A[i][k] * r_B;}}}assert arrays_C.length > 0;}@Benchmarkpublic void kij() {final int[][] arrays_C = new int[N][N];for (int k = 0; k < N; k++) {for (int i = 0; i < N; i++) {int r_A = arrays_A[k][i];for (int j = 0; j < N; j++) {arrays_C[i][j] += r_A * arrays_B[k][j];}}}assert arrays_C.length > 0;}@Benchmarkpublic void ikj() {final int[][] arrays_C = new int[N][N];for (int i = 0; i < N; i++) {for (int k = 0; k < N; k++) {int r_A = arrays_A[k][i];for (int j = 0; j < N; j++) {arrays_C[i][j] += r_A * arrays_B[k][j];}}}assert arrays_C.length > 0;}}
4.3 多次运行benchmark的结果
引用:
《深入理解计算机操作系统》 《深入理解Java虚拟机》