`

java cpu-cpu缓存行

    博客分类:
  • java
 
阅读更多

写Java也得了解CPU–CPU缓存

<iframe id="aswift_0" style="left: 0px; position: absolute; top: 0px;" name="aswift_0" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>
更多1
CPU,一般认为写C/C++的才需要了解,写高级语言的(Java/C#/pathon…)并不需要了解那么底层的东西。我一开始也是这么想的,但直到碰到LMAX的 Disruptor ,以及 马丁的博文 ,才发现写Java的,更加不能忽视CPU。经过一段时间的阅读,希望总结一下自己的阅读后的感悟。本文主要谈谈CPU缓存对Java编程的影响,不涉及具体CPU缓存的机制和实现。

现代CPU的缓存结构一般分三层,L1,L2和L3。如下图所示:

级别越小的缓存,越接近CPU, 意味着速度越快且容量越少。

L1是最接近CPU的,它容量最小,速度最快,每个核上都有一个L1 Cache(准确地说每个核上有两个L1 Cache, 一个存数据 L1d Cache, 一个存指令 L1i Cache);

L2 Cache 更大一些,例如256K,速度要慢一些,一般情况下每个核上都有一个独立的L2 Cache;

L3 Cache是三级缓存中最大的一级,例如12MB,同时也是最慢的一级,在同一个CPU插槽之间的核共享一个L3 Cache。

当CPU运作时,它首先去L1寻找它所需要的数据,然后去L2,然后去L3。如果三级缓存都没找到它需要的数据,则从内存里获取数据。寻找的路径越长,耗时越长。所以如果要非常频繁的获取某些数据,保证这些数据在L1缓存里。这样速度将非常快。下表表示了CPU到各缓存和内存之间的大概速度:

从CPU到       大约需要的CPU周期         大约需要的时间(单位ns) 
寄存器          1 cycle 
L1 Cache      ~3-4 cycles                        ~0.5-1 ns 
L2 Cache      ~10-20 cycles               ~3-7 ns 
L3 Cache      ~40-45 cycles               ~15 ns 
跨槽传输                    ~20 ns 
内存      ~120-240 cycles                ~60-120ns

利用CPU-Z可以查看CPU缓存的信息:

在linux下可以使用下列命令查看:

有了上面对CPU的大概了解,我们来看看 缓存行(Cache line) 。缓存,是由缓存行组成的。一般一行缓存行有64字节(由上图”64-byte line size”可知)。所以使用缓存时,并不是一个一个字节使用,而是一行缓存行、一行缓存行这样使用;换句话说,CPU存取缓存都是按照一行,为最小单位操作的。

这意味着,如果没有好好利用缓存行的话,程序可能会遇到性能的问题。可看下面的程序:

publicclass L1CacheMiss {privatestaticfinalint RUNS =10;privatestaticfinalint DIMENSION_1 =1024*1024;privatestaticfinalint DIMENSION_2 =6;privatestaticlong[][] longs;publicstaticvoid main(String[] args)throwsException{Thread.sleep(10000);
        longs =newlong[DIMENSION_1][];for(int i =0; i < DIMENSION_1; i++){
            longs[i]=newlong[DIMENSION_2];for(int j =0; j < DIMENSION_2; j++){
                longs[i][j]=0L;}}System.out.println("starting....");long sum =0L;for(int r =0; r < RUNS; r++){finallong start =System.nanoTime();//slow//            for (int j = 0; j < DIMENSION_2; j++) {//                for (int i = 0; i < DIMENSION_1; i++) {//                    sum += longs[i][j];//                }//            }//fastfor(int i =0; i < DIMENSION_1; i++){for(int j =0; j < DIMENSION_2; j++){
                    sum += longs[i][j];}}System.out.println((System.nanoTime()- start));}}}

以我所使用的Xeon E3 CPU和64位操作系统和64位JVM为例,如 这里 所说,假设编译器采用行主序存储数组。

64位系统,Java数组对象头固定占16字节(未证实),而long类型占8个字节。所以16+8*6=64字节,刚好等于一条缓存行的长度:

如32-36行代码所示,每次开始内循环时,从内存抓取的数据块实际上覆盖了longs[i][0]到longs[i][5]的全部数据(刚好64字节)。因此,内循环时所有的数据都在L1缓存可以命中,遍历将非常快。

假如,将32-36行代码注释而用25-29行代码代替,那么将会造成大量的缓存失效。因为每次从内存抓取的都是同行不同列的数据块(如longs[i][0]到longs[i][5]的全部数据),但循环下一个的目标,却是同列不同行(如longs[0][0]下一个是longs[1][0],造成了longs[0][1]-longs[0][5]无法重复利用)。运行时间的差距如下图,单位是微秒(us):

最后,我们都希望需要的数据都在L1缓存里,但事实上经常事与愿违,所以缓存失效 (Cache Miss)是常有的事,也是我们需要避免的事。

一般来说,缓存失效有三种情况:

1. 第一次访问数据, 在cache中根本不存在这条数据, 所以cache miss, 可以通过 prefetch 解决。

2. cache冲突, 需要通过补齐来解决(伪共享的产生)。

3. cache满, 一般情况下我们需要减少操作的数据大小, 尽量按数据的物理顺序访问数据。

分享到:
评论

相关推荐

    cpu-z_1.89-en_java_

    1. **CPU信息**:CPU-Z能够提供关于处理器的详细信息,如制造商、型号、核心名称、频率、线程数、缓存大小等。这对于识别和优化硬件性能至关重要。 2. **内存信息**:该工具可以显示内存类型(DDR3/DDR4等)、速度、...

    javamelody-javamelody-core-1.67.0.zip

    5. **数据可视化**:JavaMelody提供了直观的Web界面,展示各项监控指标的图表,如线程数、数据库查询性能、缓存状态等。这种可视化方式便于用户理解应用的运行状态,并且支持自定义报告和警报设置。 6. **数据库...

    JavaMelody javamelody-core-1.52.0.jar jrobin-1.5.9.jar

    4. **缓存监控**:如果应用使用了缓存(如Ehcache或Hazelcast),JavaMelody能监控其命中率和大小。 5. **会话监控**:查看活跃会话数量,了解会话超时和失效情况。 6. **线程监控**:展示应用中的活动线程,有助于...

    JAVA-缓存行对齐测试方法

    缓存行(Cache Line)是CPU缓存存储数据的基本单位,通常包含几十到几百个字节的数据。当多个线程同时访问不同但相邻的数据时,可能会引发竞争条件,导致性能下降,这种现象被称为缓存冲突或缓存不命中。在Java中,...

    CPU-Info.rar_cpu_java 硬件

    此外,CPU的缓存大小也会影响性能,L1、L2和L3缓存分别位于不同层次,用于存储常用数据,减少内存访问延迟。 Java是一种广泛使用的编程语言,它具有跨平台的能力,可以在各种操作系统上运行。在硬件信息获取方面,...

    javamelody-javamelody-core-src-1.68.1.zip

    6. **缓存监控**:如果应用使用了缓存,JavaMelody可以监控缓存的命中率和大小。 7. **会话监控**:追踪用户的会话,查看会话中的数据和会话超时情况。 8. **安全性**:提供对敏感数据的隐藏,保护用户隐私。 ...

    cpu-test.rar_cpu_cpu TE_cpu test

    4. **缓存测试**:CPU缓存的大小和速度对整体性能有很大影响,测试会评估CPU如何利用各级缓存。 5. **指令集测试**:不同的CPU支持不同的指令集,如SSE, AVX等,测试会验证这些扩展指令集的效率。 6. **稳定性测试...

    cpu-.circ.zip

    JVM的性能优化往往涉及到如何更高效地与CPU交互,例如通过即时编译(JIT)将字节码转化为机器码,利用CPU缓存优化内存访问等。 2. **并行与并发处理**:Java提供了丰富的多线程支持,允许开发者编写能够充分利用...

    java管理windows系统内存_java释放内存缓存_java获得CPU使用率_系统内存_硬盘_进程源代码

    "java管理windows系统内存_java释放内存缓存_java获得CPU使用率_系统内存_硬盘_进程源代码" 在Windows操作系统中,内存管理是一个非常重要的方面。Windows实现按需调页的虚拟内存机制,使得应用程序可以使用超过...

    javamelody-1.43.0

    - **缓存监控**:监控缓存的命中率和大小,优化缓存性能。 2. **文件列表详解**: - `.checkstyle`:包含代码风格检查的配置文件,用于确保代码的规范性。 - `.classpath`:Eclipse项目类路径文件,定义了项目中...

    java线程-Java内存模型

    1. 可见性问题:在多核CPU环境中,每个核心都有自己的高速缓存(L1、L2、L3等)。当一个线程修改了共享变量,并写回缓存,但其他线程可能无法立即感知到这一变化,因为它们可能还在使用旧的缓存值。Java内存模型通过...

    java 绘制CPU使用率图形 源代码

    在Java编程语言中,开发一个绘制CPU使用率图形的程序是一项技术挑战,它涉及到系统监控、图形用户界面(GUI)以及实时数据处理等多方面的知识。这个程序的主要目的是模拟任务管理器的部分功能,显示计算机的CPU使用...

    框架->java语言->jvm->os->汇编->硬件

    在博客链接中,可能包含的是关于大型电子商务平台如淘宝的技术架构介绍,通过“淘宝架构图”我们可以期待看到以下内容:系统分层设计、服务拆分、微服务架构、数据库设计、缓存策略、负载均衡、高可用性设计、容灾...

    新版CPU-Z 1.29版(免费版).pdf

    该软件提供了详细的CPU识别功能,包括CPU的名称、制造商、性能参数、当前电压、核心频率、缓存信息以及多线程和超线程状态等。支持多种CPU系列,例如Intel和AMD的产品。CPU-Z的安装和使用都非常简便,用户可以轻松...

    Java-Thread-Affinity:将Java线程绑定到给定的内核

    Java线程亲和性(Thread Affinity)是操作系统层面的一个概念,它允许我们将特定的线程绑定到CPU的特定核心上,以优化性能和减少线程间的上下文切换。在高并发、低延迟的系统中,如金融交易、实时数据分析等场景,...

    cpu 内存模型和java内存模型

    Java程序员了解CPU以及相关的内存模型,对于深入理解...通过分析具体的编程问题,比如Java锁的不同实现方式、CPU缓存的工作机制等,可以帮助程序员更好地理解Java内存模型,在多线程环境下写出更加健壮和高效的代码。

    Java 多线程与并发(1-26)-Java 并发 - 理论基础.pdf

    多线程的出现是为了解决 CPU、内存、I/O 设备速度差异的问题,通过分时复用 CPU、缓存和进程、线程机制来平衡速度差异。 Java 中的多线程机制的主要目标是解决并发问题,包括可见性、原子性和有序性三个方面。可见...

    java写的用仪表盘读CPU

    在Java编程环境中,读取系统资源如CPU使用率和内存状态是常见的需求,尤其是在系统监控、性能分析或者优化场景中。下面将详细讲解如何利用Java实现这个功能,并介绍相关的技术点。 首先,Java提供了一个名为`java....

    java 缓存系统实战(安装和实例代码)

    Java 缓存系统实战主要涉及的是使用 Memcached 这一开源缓存框架,它是一个高性能、分布式的内存对象缓存系统。Memcached 提供了 key-value 存储,旨在优化速度差异较大的硬件或软件之间的数据交互。以下是关于 ...

Global site tag (gtag.js) - Google Analytics