cpu缓存

SQLSERVER预读逻辑读物理读

痴心易碎 提交于 2019-12-05 17:39:19
  预读:用估计信息,去硬盘读取数据到缓存。预读 100次,也就是估计将要从硬盘中读取了100页数据到缓存。   物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存再次去读硬盘。物理读 10页,从硬盘中读取10页数据到缓存。   逻辑读:从缓存中取出所有数据。逻辑读 100次,也就是从缓存里取到100页数据。 lob逻辑读:从缓存读取的text,ntext,image或大值类型(varchar(max),nvarchar(max),varbinary(max))的页的数目 SQL Server存储的最小单位是页,每一页大小为8K,SQL Server对于页的读取是原子性的,要么读完一页,要么完全不读。即使是仅仅要获得一条数据,也要读完一页。而页之间的数据组织结构为B树结构。 所以SQL Server对于逻辑读、预读、物理读的单位是页。 基本上,逻辑读、物理读、预读都等于是扫描了多少个页。 当遇到一个查询语句时, SQL SERVER会走第一步,分别为生成执行计划(占用CPU和内存资源),同步的用估计的数据去磁盘中取得需要取的数据(占用IO资源,这就是预读), 注意,两个第一步是并行的,SQL SERVER通过这种方式来提高查询性能. 然后查询计划生成好了以后去缓存读取数据.当发现缓存缺少所需要的数据后让缓存再次去读硬盘(物理读) 最后从缓存中取出所有数据(逻辑读)。 来源

【并发那些事】可见性问题的万恶之源

删除回忆录丶 提交于 2019-12-05 15:18:36
【并发那些事】可见性问题的万恶之源 硬件工程师为均衡 CPU 与 缓存之间的速度差异,特意加的 CPU 缓存,竟然在多核的场景下阴差阳错的成为了并发可见性问题的万恶之源!( 本文过长,如果不是特别无聊,看到这里就可以了 ) 前言 还记得那些年,你写的那些多线程 BUG 吗?明明只想得到个 1 + 1 = 2 的预期,结果他有时候得到 1,有时候得到 3,但偏偏有时候他也会返回正确的 2。明明在本地运行的好好的,一上线一堆诡异的 BUG。你一遍一遍的检查代码,一行一行 debug,结果无功而返。 变量为何突然变异?代码为何乱序运行?条件为何形同虚设?欢迎收看今天的《走进科学》之半夜。。。哦,不对,欢迎阅读今天的《并发那些事》之可见性问题的万恶之源。就像上面说的,我们在写并发程序时,经常会出现超出我们认识与直觉的问题,而按我们的以往的经验,很难去察觉到他的问题所在。而又因为我们不了解他发生的诱因,即使我们按照书上的方案解决了,但是下次还是会出现。所以本文的主旨并不是解决问题的术,而是解决问题的道。一起来探究多线程问题的根源。 首先揭开谜底,大多数并发问题的发生都是这三个问题导致的, 可见性问题、原子性问题、有序性问题 。那么又是什么导致这三个问题的出现呢?本文将一步步解析可见性问题出现的原因。 核心矛盾 众所周知,电脑由很多的部件组成。其中最最最重要的有三个,它们分别是 CPU 、内存

数据库优化方案整理

有些话、适合烂在心里 提交于 2019-12-04 23:05:13
一:优化说明 A:有数据表明,用户可以承受的最大等待时间为8秒。数据库优化策略有很多,设计初期,建立好的数据结构对于后期性能优化至关重要。因为数据库结构是系统的基石,基础打不好,使用各种优化策略,也不能达到很完美的效果。 B:数据库优化的几个方面 ​​ 可以看出来,数据结构、SQL、索引是成本最低,且效果最好的优化手段。 C:性能优化是无止境的,当性能可以满足需求时即可,不要过度优化。 二:优化方向 1. SQL以及索引的优化 首先要根据需求写出结构良好的SQL,然后根据SQL在表中建立有效的索引。但是如果索引太多,不但会影响写入的效率,对查询也有一定的影响。 2. 合理的数据库是设计 根据数据库三范式来进行表结构的设计。设计表结构时,就需要考虑如何设计才能更有效的查询。 数据库三范式: 第一范式:数据表中每个字段都必须是不可拆分的最小单元,也就是确保每一列的原子性; 第二范式:满足一范式后,表中每一列必须有唯一性,都必须依赖于主键; 第三范式:满足二范式后,表中的每一列只与主键直接相关而不是间接相关(外键也是直接相关),字段没有冗余。 注意:没有最好的设计,只有最合适的设计,所以不要过分注重理论。三范式可以作为一个基本依据,不要生搬硬套。 有时候可以根据场景合理地反规范化: A:分割表。 B:保留冗余字段。当两个或多个表在查询中经常需要连接时,可以在其中一个表上增加若干冗余的字段

一起来学习Java的Volatile关键字

我是研究僧i 提交于 2019-12-04 07:52:22
前言 在Java并发编程中,volatile关键字有着至关重要的作用,在面试中也常常会是必备的一个问题。本文将会介绍volatile关键字的作用以及其实现原理。 volatile作用 volatile在并发编程中扮演着重要的角色,volatile是轻量级的synchronized,volatile关键字有两个作用: 1)保证共享变量的可见性 可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。笔者此前一篇文章Java并发编程:Java内存模型JMM中有说到,Java内存模型中有主内存和本地内存之分,本地内存持有共享变量的一份副本,线程对共享变量的修改是先修改本地内存的副本,然后再回写到主内存中去。 可能存在这样的情况,线程A和线程B同时去修改一个共享变量C,假设线程A先对共享变量C做了修改,而此时线程B却没能及时感知到共享变量C已经发生了改变,紧接着B对本地过期的副本数据进行了修改,这造成了共享变量的不可见问题。 而使用了volatile关键字修改的共享变量,当线程修改了共享变量之后,会立马刷新到主内存中,并且会使其他线程缓存了该地址的数据失效,这就保证了线程之间共享变量的可见性。 2)防止指令重排序 volatile关键字的另外一个作用就是防止指令重排序。代码在实际执行过程中,并不全是按照编写的顺序进行执行的,在保证单线程执行结果不变的情况下

多线程学习之多线程的可见性

喜欢而已 提交于 2019-12-04 07:06:05
多线程的可见性   一、深入探究多线程的不确定性因素 1 1、cpu高速缓存导致的极短时间内获取不到想要数据 2 2、cpu指令重排导致之后的自行优化导致数据混乱;当然,这种情况值存在于多线程的基础上,单个线程是不会出现这种问题的。 3 3、JIT会把多次方法区中多调用或者多次循环的数据进行换存,然后自行优化;这里缓存也会导致后来改变的数据无法被正常的获取。   首先来说cpu的高速缓存,它是介于我们物理内存与程序之间。   CPU高速缓存(英语:CPU Cache,在本文中简称缓存)是用于减少 处理器 访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。   其容量远小于 内存 ,但速度却可以接近处理器的频率。   当处理器发出内存访问请求时,会先查看缓存内是否有请求数据。如果存在(命中),则不经访问内存直接返回该数据;如果不存在(失效), 则要先把内存中的相应数据载入缓存,再将其返回处理器。   缓存之所以有效,主要是因为程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。   有效利用这种局部性,缓存可以达到极高的命中率。   在处理器看来,缓存是一个透明部件。因此,程序员通常无法直接干预对缓存的操作。但是

jmeter性能测试分析结果

旧巷老猫 提交于 2019-12-04 06:26:31
在进行性能测试之前,需要跟开发问清楚性能测试的目的,是为了找到系统能支撑的最大负载还是为了检查在一定负载下系统的运行情况。如果是后者的话,还需要问一下服务器端设置的最大并发线程数,这样测试时才能设置出合适的负载量。我之前做过的几次http请求的压测,都是为了找系统能支持的最大负载。本次压测,我先在本地测试,给了50个线程并循环100次,结果在测试运行一段时间后就会出现需要等待很长时间的情况,一开始以为是本地网络状况不佳,将脚本放在服务器上跑依然会出现这个情况,后来跟开发沟通知道服务端设置了最大并发量的限制,并且只需要测试一下特定线程下系统的性能情况即可。有了这次经验之后,在之后的性能测试前就知道要尽量问清楚测试需求了。 还有一点需要注意的是缓存对于性能的影响,有无缓存对性能的影响通常是很大的,需要跟开发确认好重点关注的是有缓存还时没有缓存的情况。本次压测,有一个测试类是查询文章subject(话题)属性的,话题属性是实时计算出来的,如果传入的docid是第一次调用该方法,返回话题属性耗时会比较长,之后再对同一个docid查询话题属性时是直接从缓存中取数据返回,耗时大大减少。对获取话题属性的方法进行性能测试,在40个线程、重复100次的压力下,没有缓存和有缓存时的TPS分别为70/s和2200/s,可见两种情况下的差距之大。 一般性能测试的时候还需要关注其他的一些信息

网络存储——智能存储系统

北城以北 提交于 2019-12-03 05:08:58
智能存储系统(待续...) 组成部分 前端 由前端端口和前端控制器组成。 前端端口 使得主机能连接到智能存储系统,每个前端端口拥有相应传输协议的处理逻辑(SCSI、光纤通道、iSCSI等)。 前端控制器 通过数据总线在主机和缓存间传输数据。通过命令队列算法来优化IO处理。 前端命令队列 通过队列存储IO命令,调整执行顺序,减少不必要的驱动器磁头移动,改善磁盘性能。 常见算法: 先进先出算法FIFO:按顺序执行,性能最差 寻道时间优化算法:根据寻道时间优化 访问时间优化:综合考虑寻道时间和旋转延迟进行优化 注 :命令缓存也可以在磁盘控制器上实现。 高速缓存 基本单位是页。 物理磁盘访问最慢。因为寻道时间与旋转延迟,通常要几毫秒。过慢导致请求被排队,带来响应延迟。 缓存访问数据只需不到1ms,数据先被存入缓存随后再写入磁盘。数据存入缓存后,主机会立即得到响应。 缓存由数据存储和标签RAM组成。 标签RAM 每个条目记录数据保存在缓存哪个位置以及数据属于磁盘中的哪个位置。 脏标志位:记录是否已保存到磁盘 时间信息:如最后访问时间,淘汰很久没访问的数据 带有缓存的读操作 主机发送读请求,前端控制器通过标签RAM查询数据是否在缓存中。 如果找到了(读命中),数据直接送入主机,不发生磁盘操作。 否则(缓存未命中),后端控制器访问磁盘,读取数据,数据被存入缓存,在通过前端控制器传入主机。 预读

SpringBoot:一二级分布式缓存

梦想的初衷 提交于 2019-12-03 04:03:24
前言 缓存系统的用来代替直接访问数据库,用来提升系统性能,减小数据库负载。早期缓存跟系统在一个虚拟机里,这样内存访问,速度最快。 后来应用系统水平扩展,缓存作为一个独立系统存在,如redis,但是每次从缓存获取数据,都还是要通过网络访问才能获取,效率相对于早先从内存里获取,还是不够逆天快。如果一个应用,比如传统的企业应用,一次页面显示,要访问数次redis,那效果就不是特别好,性能不够快不说,还容易使得Reids负载过高,Redis的主机出现各种物理故障。因此,现在有人提出了一二级缓存。即一级缓存跟系统在一个虚拟机内,这样速度最快。二级缓存位于redis里,当一级缓存没有数据的时候,再从redis里获取,并同步到一级缓存里。这跟CPU的一级缓存,二级缓存是一个道理。当然也面对同样的问题。 缓存概念 Cache 通常有如下组件构成 CacheManager:用来创建,管理,管理多个命名唯一的Cache。如可以有组织机构缓存,菜单项的缓存,菜单树的缓存等 Cache:类似Map那样的Key—Value存储结构,Value部分 通常包含了缓存的对象,通过Key来取得缓存对象 缓存项:存放在缓存里的对象,常常需要实现序列化接口,以支持分布式缓存。 Cache存储方式:缓存组件的可以将对象放到内存,也可以是其他缓存服务器,Spring Boot 提供了一个基于ConcurrentMap的缓存

缓存一致性(MESI)

匿名 (未验证) 提交于 2019-12-03 00:22:01
所以就出现了缓存一致性协议。最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。 Cache一致性协议之MESI 处理器上有一套完整的协议,来保证Cache一致性。比较经典的Cache一致性协议当属MESI协议,奔腾处理器有使用它,很多其他的处理器都是使用它的变种。 单核Cache中每个Cache line有2个标志:dirty和valid标志,它们很好的描述了Cache和Memory(内存)之间的数据关系(数据是否有效,数据是否被修改),而在多核处理器中,多个核会共享一些数据,MESI协议就包含了描述共享的状态。 在MESI协议中,每个Cache line有4个状态,可用2个bit表示,它们分别是: MESI״̬ M(Modified)和E(Exclusive)状态的Cache line,数据是独有的,不同点在于M状态的数据是dirty的(和内存的不一致),E状态的数据是clean的(和内存的一致)。 S(Shared)状态的Cache line,数据和其他Core的Cache共享

Volatile详解

匿名 (未验证) 提交于 2019-12-03 00:21:02
之前研究了一下内存模型,java内存模型中很关键的一点就是Volatile,现在跟大家探讨一下Volatile的知识吧 1.volatile关键字的两层语义   一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:   1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。   2)禁止进行指令重排序。   先看一段代码,假如线程1先执行,线程2后执行: 这段代码是很典型的一段代码,很多人在中断线程时可能都会采用这种标记办法。但是事实上,这段代码会完全运行正确么?即一定会将线程中断么?不一定,也许在大多数时候,这个代码能够把线程中断,但是也有可能会导致无法中断线程(虽然这个可能性很小,但是只要一旦发生这种情况就会造成死循环了)。   下面解释一下这段代码为何有可能导致无法中断线程。在前面已经解释过,每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。   那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。   但是用volatile修饰之后就变得不一样了:   第一