cpu缓存

利用CPU cache特性优化Go程序

本小妞迷上赌 提交于 2020-01-01 10:19:18
demo 如下Go语言伪代码,开启两个协程,分别对一个结构体变量中的两个相邻的数据成员进行n次原子自增操作,当打开 _ [56]byte 这个看似多余的代码后,程序运行速度加快了一倍!你知道是为什么吗? ... type Foo struct { a uint64 // _ [56]byte b uint64 // _ [56]byte } ... go func() { for i := 0; i < 1000 * 1000; i++ { atomic.AddUint64(&foo.a, 1) } }() go func() { for i := 0; i < 1000 * 1000; i++ { atomic.AddUint64(&foo.b, 1) } }() // 等待两个协程执行完毕,记录总执行时间 ... 完整可运行代码见: https://github.com/q191201771/naza/blob/master/playground/p3/p3.go CPU cache 大家都知道,内存的速度远快于磁盘的速度,但事实上,跟CPU的处理速度相比,内存还是太慢了。CPU不愿意老是等内存,于是就有了 CPU cache 。CPU cache的速度比内存快数十倍。 很多资料上都有关于不同存储硬件速度和容量的对比,但是有的数据随着硬件的发展已经过期了

对volatile不具有原子性的理解

随声附和 提交于 2019-12-29 20:34:56
在阅读多线程书籍的时候,对volatile的原子性产生了疑问,问题类似于这篇 文章 所阐述的那样。经过一番思考给出自己的理解。 我们知道对于可见性,Java提供了volatile关键字来保证 可见性 、 有序性 。 但不保证原子性 。 普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。   背景:为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,但操作完不知道何时会写到内存。 如果对声明了volatile的变量进行写操作 ,JVM就会向处理器发送一条指令,将这个变量所在缓存行的数据写回到系统内存。但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。 在多处理器下,为了保证各个处理器的缓存是一致的,就会 实现缓存一致性协议 ,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。 总结下来 : 第一:使用volatile关键字会强制将修改的值立即写入主存; 第二:使用volatile关键字的话,当线程2进行修改时

数据结构:链表讲解

拈花ヽ惹草 提交于 2019-12-28 15:12:11
数据结构:链表讲解 一、缓存淘汰策略: 缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去?哪些数据应该保留?这就需要缓存淘汰策略来决定。 简单理解: 就是当缓存被用满时清理数据的优先顺序 。 先进先出策略 FIFO(First In, First Out) 最少使用策略 LFU(Least Frequently Used) 最近最少使用策略 LRU(Least Recently Used) 以上策略举个栗子: 假如,你买了很多书,但有一天发现,书太多了,太占书房空间了,打算丢掉一些书籍; 丢到刚买的书:先进先出策略 丢到买完一直都没有读过的书:最少使用策略 丢到最近刚买的书,但是一直都没怎么读过:最近最少使用策略 二、数组与链表的区别: 1.底层存储的结构区别: 我们可以从 底层的存储结构 来看。数组需要一块 连续的内存空间 来存储,对内存的要求比较高。 如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。 链表恰恰相反,它并 不需要一块连续的内存空间 ,它通过 指针 将一组零散的内存块串联起来使用,其中,我们把内存块称为链表的 结点 。 为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的 下一个结点的地址 。结点地址的指针叫作 后继指针 next 。

浅淡缓存

会有一股神秘感。 提交于 2019-12-27 10:12:54
缓存作为常用的优化手段,是架构师必备技能之一,在面试时我也喜欢让候选人系统的介绍一下缓存知识,能把缓存体系说清楚的并不多。 单机硬件角度缓存 下图是经典的计算机组成原理的缓存结构图 速度从高到低依次是:L1 > L2 > L3 > 内存 > 磁盘(硬盘缓存+硬盘) 单位容量制造成本从高到低依次是:L1 > L2 > L3 > 内存 > 磁盘(硬盘缓存+硬盘) 对硬件来说,缓存是基于有限的成本下,介于相对高速和相对低速设备之间的缓冲,目的是尽可能的提升处理效率。 用户角度看缓存 DNS缓存 对终端用户而言,操作系统和浏览器都存在着DNS缓存 CDN CDN不是缓存,其核心思想是将用户的请求导向离用户最近的服务节点上,提高用户访问网站的响应速度。只是这里说的最近的服务节点一般是容量有限的缓存服务器。 浏览器缓存 最典型流程是浏览器第一次访问时,服务器返回当前时间Last-Modified值,记为t,当下一次访问时,If-Modified-Since取值t,配合Cache-Control,如果服务端资源未被修改,返回状态码304,浏览器直接从本地磁盘取缓存的网页文件。 对用户来说,缓存是为了从最近的地方取得所需内容,玩命减少等待时间,提升响应速度。 架构角度看缓存 接入层缓存:Nginx缓存 进程内缓存:JVM堆内缓存、堆外缓存 主机内缓存:Local Redis、本地磁盘

php缓存技术总结

青春壹個敷衍的年華 提交于 2019-12-27 09:15:02
缓存是指临时文件交换区,电脑把最常用的文件从存储器里提出来临时放在缓存里,就像把工具和材料搬上工作台一样,这样会比用时现去仓库取更方便。因为缓存往往使用的是RAM(断电即掉的非永久储存),所以在忙完后还是会把文件送到硬盘等存储器里永久存储。电脑里最大的缓存就是内存条了,最快的是CPU上镶的L1和L2缓存,显卡的显存是给GPU用的缓存,硬盘上也有16M或者32M的缓存。千万不能把缓存理解成一个东西,它是一种处理方式的统称! Cache 是“以空间换时间”策略的典型应用模式,是提高系统性能的一种重要方法。缓存的使用在大访问量的情况下能够极大的减少对数据库操作的次数,明显降低系统负荷提高系统性能。相比页面的缓存,结果集是一种“原始数据”不包含格式信息,数据量相对较小,而且可以再进行格式化,所以显得相当灵活。由于PHP是“一边编译一边执行”的脚本语言,某种程度上也提供了一种相当方便的结果集缓存使用方法——通过动态include相应的数据定义代码段的方式使用缓存。如果在RamDisk上建缓存的话,效率应该还可以得到进一步的提升。以下是一小段示例代码,供参考。 (参 考: PHP数据缓存技术 ) WEB程序获取信息的方式主要是查询数据库,当数据库不是很大的情况下不会有太大的问题.然而,随着网站的发展,数据库呈几何级数的方式增长的时候,就会出现瓶颈.于是PHP缓存技术诞生了。 PHP缓存包括

volatile

孤人 提交于 2019-12-27 05:21:35
  volatile的定义:Java编程语言允许线程访问共享变量,为了保证共享变量能被准确和一致性的更新,线程应该确保通过 排它锁 单独获得这个变量。   和volatile相关的术语: 术语 英语单词 术语描述 内存屏障 memory barriers 是一组处理器指令,用于实现对内存操作的顺序限制 缓冲行 cache line CPU高速缓存中可以分配的最小存储单位。 处理器填写缓存行时会加载整个缓存行,现在CPU需要执行几百次CPU指令 原子操作 atomic operations 不可终端的一个或一系列操作 缓存行填充 cache line fill 当处理器识别到从内存中读取操作数是可缓存的, 处理器读取整个高速缓存行到适当的缓存(L1,L2,L3或其他) 缓存命中 cache hit 如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是从内存读取 写命中 write hit 当处理器将操作数写回到一个内存缓存的区域时,它首先会检查这个缓存的内存地址是否在缓存行中 如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回内存,这个操作被称为写命中 写缺失 write misses the cache 一个有效的缓存行被写入到不存在的内存区域 那么,volatile是如何保证可见性呢? instance = new

[Java并发编程(五)] Java volatile 的实现原理

无人久伴 提交于 2019-12-27 05:20:59
[Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。它在某些情况下比synchronized 的开销更小,本文将深入分析在硬件层面上 Intel 处理器是如何实现 volatile 的,通过深入分析能帮助我们正确的使用 volatile 变量。 正文 术语定义 术语 英文单词 描述 共享变量 在多个线程之间能够被共享的变量被称为共享变量。共享变量包括所有的实例变量,静态变量和数组元素。他们都被存放在堆内存中,volatile只作用于共享变量。 内存屏障 Memory Barriers 是一组处理器指令,用于实现对内存操作的顺序限制。 缓冲行 Cache line 缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个缓存线,需要使用多个主内存读周期。 原子操作 Atomic operations 不可中断的一个或一系列操作。 缓存行填充 Cache line fill 当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个缓存行到适当的缓存(L1,L2,L3的或所有) 缓存命中 Cache

volatile的应用

白昼怎懂夜的黑 提交于 2019-12-27 05:20:22
volatile的应用 在多线程并发编程中synchronized和volatile都扮演者重要的角色,volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。 可见性的意思是当一个线程修改一个共享变量时,另外的线程能读到这个修改的值。 如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。 1. volatile的定义与实现原理 Java语言规范第3版对volatile的定义如下: Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排它锁单独获得这个变量。 Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。 在了解volatile实现原理之前,先看下与实现原理相关的CPU术语与说明 术语 英文单词 术语描述 内存屏障 memory barriers 是一组处理器指令,用户实现对内存操作的顺序限制 缓存行 cache line CPU高速缓存中可以分配的最小存储单位。处理器填写缓存行时会加载整个缓存行,现代CPU需要执行几百次CPU指令 原子操作 atomic operations 不可终端的一个或一系列操作

缓存一致性协议MESI

五迷三道 提交于 2019-12-27 01:34:50
1. 缓存一致性协议的由来: 计算机的存储设备速度与cpu的运算速度之间是数量级的差距,现代计算机不得不加入一层读写速度尽可能接近cpu运算速度的高速缓存来作为内存和cpu之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样cpu就无须等待缓慢的内存读写了。 基于高速缓存的存储交互很好地解决了cpu与内存的速度矛盾,但是也引入了新的问题:缓存一致性。在多cpu系统中,每个cpu都有自己的高速缓存,而它们又共享同一主内存,当多个cpu的运算任务都涉及同一块主内存区域时,将可能导致各自的缓存数据不一致的情况,如果真的发生这种情况,那同步回主内存时以谁的缓存数据为准呢?为了解决一致性的问题,需要各个cpu访问缓存时都遵循一些协议,在读写时根据协议来进行操作,这类协议有MSI、MESI、MOSI、Synapse、Firefly及Dragon Protocol等等。jvm内存模型中定义的内存访问操作与硬件的缓存访问操作具有可比性。 2. MESI协议: 来源: https://www.cnblogs.com/i-hard-working/p/12105304.html

编程语言的作用及与操作系统和硬件的关系

ぐ巨炮叔叔 提交于 2019-12-26 19:18:13
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 一、编程语言的作用及与操作系统和硬件的关系 作用:编程语言是计算机语言,是一种程序员与计算机之间沟通的介质,通过编程语言可以使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。 关系:编程语言会通过编译软件写成程序,程序是不能直接和硬件来进行交互的,而操作系统是用来管理计算机硬件设备的,所以我们可以就可以在操作系统上来运行程序,让操作系统去管理与配置内存、决定系统资源供需的优先次序、控制输入与输出、操作网络与管理文件系统等基本任务。 二、应用程序、操作系统、硬件之间的关系 硬件上运行操作系统,操作系统上运行应用程序,应用程序通过Windows API调用操作系统函数从而和计算机硬件交互。 三、 cpu 、内存、磁盘之间的关系 1.CPU即中央处理器,CPU从内存或缓存中取出指令,放入指令寄存器,并对指令进行解码,然后发出各种控制命令,从而完成一条指令的执行。 2.CPU并不能直接调用存储在硬盘上的系统、程序和数据,必须将硬盘的有关内容通过总线存储在内存中,才能被CPU读取运行。因而,内存可以理解为硬盘和CPU的“中转站”。 3.当运行数据大小超出物理内存的时候,这时系统就会将硬盘上的部分空间模拟成内存——虚拟内存,并将暂时不运行的程序或不使用的数据存放到这部分空间之中,等待需要的时候方便及时调用。 4