cpu缓存

原子操作

元气小坏坏 提交于 2020-03-09 04:21:18
CPU术语 缓存行(Cache line):缓存的最小单位 比较并交换(Compare and Swap):CAS操作需要输入两个数值,一个旧值,一个新值,在操作期间先比较旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换 CPU流水线(CPU pipeline):在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5~6步后再由这些电路单元分别执行,这样就能实现在一个CUP时钟周期完成一条指令,从而提高CPU的运算速度 内存顺序冲突(Memory order violation):内存顺序冲突一般是由假共享引起的,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现内存顺序冲突时,CPU必须清空流水线 处理器实现原子操作 1.使用总线锁保证原子性:    如果多个处理器同时对共享变量进行读写操作(i++),那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一致。 总线锁其实就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。 2.使用缓存锁保证原子性:    在同一时刻,只需保证对某个内存地址的操作是原子性即可,但总线锁把CPU和内存之间的通信锁住了

CPU缓存和内存屏障

好久不见. 提交于 2020-03-08 02:41:17
目录 CPU性能优化手段 - 缓存 多级缓存 缓存同步协议 CPU性能优化手段 - 运行时指令重排 两个问题 解决方法 - 内存屏障 CPU性能优化手段 - 缓存 为了提高程序的运行性能, 现代CPU在很多方面对程序进行了优化 例如: CPU高速缓存, 尽可能的避免处理器访问主内存的时间开销, 处理器大多会利用缓存以提高性能 多级缓存 L1 Cache (一级缓存)是CPU第一层高速缓存, 分为数据缓存和指令缓存, 一般服务器CPU的L1缓存的容量通常在32-4096kb L2 Cache (二级缓存) 由于L1高速缓存的容量限制, 为了再次提高CPU的运算速度, 在CPU外部放置一高速缓存存储器, 即二级缓存 L3 Cache (三级缓存)现在都是内置的, 而它的实际作用既是, L3缓存的应用可以进一步降低内存延迟, 同时提升大数据量计算时处理器的性能. 具有较大L3缓存的处理器更有效的文件系统缓存行为及较短消息和处理器队列长度. 一般是多核共享一个L3缓存 CPU在读取数据时, 先在L1中寻找, 再从L2中寻找, 再从L3中寻找, 然后是内存, 最后是外存储器 缓存同步协议 多CPU读取同样的数据进行缓存, 进行不同运算之后, 最终写入主内存以那个CPU为准? 在这种高速缓存回写的场景下, 有一个缓存一致性协议, 多数CPU厂商对它进行了实现. 即MESI协议,

生产要不要开启MySQL查询缓存

一笑奈何 提交于 2020-03-07 18:51:54
一、前言 在当今的各种系统中,缓存是对系统性能优化的重要手段。MySQL Query Cache(MySQL查询缓存)在MySQL Server中是默认打开的,但是网上各种资料以及有经验的DBA都建议生产环境中把MySQL Query Cache关闭。按道理,MySQL Server默认打开,是鼓励用户使用缓存,但是大拿们却建议关闭此功能,并且国内各个云厂商提供的MySQL云服务中默认都是关闭这个功能,这是为什么?他们在使用中遇到了什么坑?本文将会从以下几方面来详解MySQL Query Cache。 1.MySQL查询缓存是什么? MySQL缓存规则是什么? 如何配置和缓存MySQL缓存 MySQL缓存的优缺点 生产要不要开启MySQL缓存 二、 MySQL查询缓存简介 MySQL查询缓存是MySQL中比较独特的一个缓存区域,用来缓存特定Query的整个结果集信息,且共享给所有客户端。为了提高完全相同的Query语句的响应速度,MySQL Server会对查询语句进行Hash计算后,把得到的hash值与Query查询的结果集对应存放在Query Cache中。当MySQL Server打开Query Cache之后,MySQL Server会对接收到的每一个SELECT 语句通过特定的Hash算法计算该Query的Hash值,然后通过该hashi值到Query Cache中去匹配

什么是伪共享问题?

本小妞迷上赌 提交于 2020-03-05 21:08:58
伪共享指的是多线程在对不同变量进行修改操作时,如果变量位于同一个缓存行,当多线程竞争缓存行所有权时,每个核都同时对缓存行进行修改,缓存子系统将会使其他核的缓存行失效导致cache miss,最后升级到L3缓存进行修改,最后大大影响程序的执行效率,如果竞争的核不在同一个cpu插槽即不共享L3缓存,那就会去内存中进行修改,这样引起的问题就是伪共享问题。 参考资料: 伪共享(False Sharing) 图1 图1说明了伪共享的问题。在核心1上运行的线程想更新变量X,同时核心2上的线程想要更新变量Y。不幸的是,这两个变量在同一个缓存行中。每个线程都要去竞争缓存行的所有权来更新变量。如果核心1获得了所有权,缓存子系统将会使核心2中对应的缓存行失效。当核心2获得了所有权然后执行更新操作,核心1就要使自己对应的缓存行失效。这会来来回回的经过L3缓存,大大影响了性能。如果互相竞争的核心位于不同的插槽,就要额外横跨插槽连接,问题可能更加严重。 对于HotSpot JVM,所有对象都有两个字长的对象头。第一个字是由24位哈希码和8位标志位(如锁的状态或作为锁对象)组成的Mark Word。第二个字是对象所属类的引用。如果是数组对象还需要一个额外的字来存储数组的长度。每个对象的起始地址都对齐于8字节以提高性能。因此当封装对象的时候为了高效率,对象字段声明的顺序会被重排序成下列基于字节大小的顺序:

JSE-1.1.4 内存屏障和CPU缓存

痞子三分冷 提交于 2020-03-03 15:21:35
内存屏障和CPU缓存 【信息】 CPU性能优化手段-缓存 为了提高程序运行的性能 例如:CPU高速缓存。尽可能地避免处理器访问主内存的时间开销,处理器大多会利用缓存以提高性能。 CPU有三级缓存:L1-L3 多级缓存 L1 Cache(一级缓存):CPU第一层高速缓存,分为数据缓存和指令缓存。一般容量在32-4096KB。 L2:由于L1高速缓存容量的限制,为了提高CPU的运算速度,在CPU外部放置一高速存储器,即二级缓存。 L3:现在都是内置的。可以进一步降低内存延迟,同时提升大数据量计算时处理器的性能。具有较大L3缓存的处理器提供更有效的文件系统缓存行为及较短消息和处理器队列长度。 一般多核共享一个L3缓存 ! CPU读数据时,读取顺序:L1-L2-L3-内存-外存储器 缓存同步协议 多CPU读取同样的数据进行缓存,进行不同运算之后,最终写入主内存以哪个CPU为准? MESI协议 ,规定每条缓存有一条状态位,4个状态: 修改态(Modified):此cache行已被修改过(脏行),内容已不同于主存,为此cache专有。 专有态(Exclusive):此cache行内存同于主内存,但不出现与其他cache中。 共享态(Shared):此cache行内容同于主内存,但也出现于其他cache中。 无效态(Invalid):此cache行内容无效(空行) 多处理器时

多线程与并发编程

风格不统一 提交于 2020-03-03 15:14:15
单线程。 cpu核心的缓存只被一个线程访问。缓存独占,不会出现访问冲突等问题。 单核CPU,多线程。 进程中的多个线程会同时访问进程中的共享数据,CPU将某块内存加载到缓存后,不同线程在访问相同的物理地址的时候,都会映射到相同的缓存位置,这样即使发生线程的切换,缓存仍然不会失效。但由于任何时刻只能有一个线程在执行,因此不会出现缓存访问冲突。 多核CPU、多线程情况下存在缓存不一致的情况 每个核都至少有一个L1 缓存。多个线程访问进程中的某个共享内存,且这多个线程分别在不同的核心上执行,则每个核心都会在各自的caehe中保留一份共享内存的缓冲。由于多核是可以并行的,可能会出现多个线程同时写各自的缓存的情况,而各自的cache之间的数据就有可能不同。 在CPU和主存之间增加缓存,在多线程场景下就可能存在 缓存一致性问题 ,也就是说,在多核CPU中,每个核的自己的缓存中,关于同一个数据的缓存内容可能不一致。 理解为: 如果这家公司的命令都是串行下发的话,那么就没有任何问题。 如果这家公司的命令都是并行下发的话,并且这些命令都是由同一个CEO下发的,这种机制是也没有什么问题。因为他的命令执行者只有一套管理体系。 如果这家公司的命令都是并行下发的话,并且这些命令是由多个合伙人下发的,这就有问题了。因为每个合伙人只会把命令下达给自己直属的管理人员,而多个管理人员管理的底层员工可能是公用的。

Java并发机制的底层实现--volatile

Deadly 提交于 2020-03-03 05:59:40
Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,JAVA中所使用的并发机制依赖于JVM的实现和CPU的指令。 volatile的应用 在线程并发编程中sychronized和volatile都扮演者重要的角色,volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性“。可见性的意思是当一个线程修改一个共享变量时,另一个线程能读到这个修改的值。如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。 1.volatile的定义与实现原理 Java语言规范第三版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被唯一和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明为volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。 在了解volatile的实现原理之前,我们先来看下与其实现原理相关的CPU术语与说明。 volatile是如何来保证可见性的呢?让我们在X86处理器下通过工具获取JIT编译器生成的汇编指令来查看对volatile进行写操作时

volatile 对可见性的保证并不是那么简单

寵の児 提交于 2020-03-02 19:43:56
  数据一致性部分借用大神“耗叔”的博客: https://coolshell.cn/articles/20793.html 。   总结:volatile 关键字通过内存屏障禁止了指令的重排序,并在单个核心中,强制数据的更新及时更新到缓存。在此基础上,依靠多核心处理器的缓存一致性协议等机制,保证了变量的可见性。   在学习 volatile 关键字时总是绕不开两点,保证数据及时更新到内存和禁止指令重排序,基于上述两点 volatile 关键字保证了共享变量在多个线程间的可见性。   虽然说起来知识点不多,但实际上 volatile 的实现是及其复杂的。在 java5 之前 volatile 关键字会经常造成一些无法预料的错误,导致其保守诟病。直到 5 版本对 volatile 进行改进之后才重获新生,官方版本经历的这些波折足以证明其底层实现逻辑的复杂。   我们重温一下 volatile 关键字实现涉及到的知识点。从大的分类来说,其涉及两个知识点:多核心中数据的一致性,禁止指令的乱序执行。我们一个一个来看。    多核心中数据的一致性   现代处理器为了提高内存数据的访问速度,都会有自带的多级缓存,其位置在内存与处理器之间。   老的CPU会有两级内存(L1和L2),新的CPU会有三级内存(L1,L2,L3 )。其中: L1缓分成两种,一种是指令缓存,一种是数据缓存

swShareMemory_mmap_create:mmap(248000096) failed / Error: Cannot allocate memory[12]

℡╲_俬逩灬. 提交于 2020-03-01 07:33:04
启用swoole时报的错误,可以确定是内存问题 [2019-04-09 09:04:32 @220.0] WARNING swShareMemory_mmap_create: mmap(260046944) failed. Error: Cannot allocate memory[12] [2019-04-09 09:04:32 @220.0] ERROR calloc[1] failed 我们查看下内存: [root@VM_0_17_centos docker]# free -m total used free shared buff/cache available Mem: 992 495 85 116 412 216 Swap: 0 0 0 swap全都是0明显有问题,那就加点swap: sudo dd if=/dev/zero of=/swapfile bs=1M count=1024 #增加1G的 sudo mkswap /swapfile sudo swapon /swapfile [root@VM_0_17_centos docker]# free -m total used free shared buff/cache available Mem: 992 494 72 116 426 217 Swap: 1023 419 604 然后就顺利启用swoole了。

分布式缓存的基本原理

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-29 22:57:24
随着互联网的发展,用户规模和数据规模越来越大,对系统的性能提出了更高的要求,缓存就是其中一个非常关键的组件,从简单的商品秒杀,到全民投入的双十一,我们都能见到它的身影。 分布式缓存首先也是缓存,一种性能很好但是相对稀缺的资源,和我们在课本上学习的CPU缓存原理基本相同,CPU是用性能更好的静态RAM来为性能一般的DRAM加速,分布式缓存则是通过内存或者其他高速存储来加速,但是由于用到了分布式环境中,涉及到并发和网络的问题,所以会更加复杂一些,但是有很多方面的共性,比如缓存淘汰策略。计算机行业有一句鼎鼎大名的格言就指出了缓存失效的复杂性。 There are only two hard things in Computer Science: cache invalidation and naming things (计算科学中最难的两件事是命名和缓存失效) – Phil Karlton 本文包括四个部分,分布式缓存的更新模式、失效机制、淘汰策略和常见问题及解决方案,重点是围绕缓存的通用原理和实现来说明,不针对某个具体的系统,算法部分主要采用伪代码说明。 缓存的更新模式 Cache Aside模式 读取失效:cache数据没有命中,查询DB,成功后把数据写入缓存 读取命中:读取cache数据 更新:把数据更新到DB,失效缓存 图示 // Read data = cache.get(id