• cache和buffer区别探讨


    一.
    1、Buffer(缓冲区)是系统两端处理速度平衡(从长时间尺度上看)时使用的。它的引入是为了减小短期内突发I/O的影响,起到流量整形的作用。比如生产者——消费者问题,他们产生和消耗资源的速度大体接近,加一个buffer可以抵消掉资源刚产生/消耗时的突然变化。
    2、Cache(缓存)则是系统两端处理速度不匹配时的一种折衷策略。因为CPU和memory之间的速度差异越来越大,所以人们充分利用数据的局部性(locality)特征,通过使用存储系统分级(memory hierarchy)的策略来减小这种差异带来的影响。
    3、假定以后存储器访问变得跟CPU做计算一样快,cache就可以消失,但是buffer依然存在。比如从网络上下载东西,瞬时速率可能会有较大变化,但从长期来看却是稳定的,这样就能通过引入一个buffer使得OS接收数据的速率更稳定,进一步减少对磁盘的伤害。
    4、TLB(Translation Lookaside Buffer,翻译后备缓冲器)名字起错了,其实它是一个cache.
    二.

    是这样的,其实Cache和Buffer,物理上讲都是RAM。逻辑上讲,你把Cache叫成Buffer,或者把Buffer叫成Cache,都没有错。

    不过Buffer多用于编程方面,Cache多用于非编程方面的叫法。比如为某程序分配一段Buffer,而一般没有说为某程序分配一段Cache的,但是你可以说这个程序有Cache,或者说Cache是泛指,Buffer是特指。见仁见智。而对于磁盘阵列来讲,Buffer=Cache。

    另外,从本质上讲,Buffer是“缓冲”,而Cache是“缓存”,即Buffer中的数据是一定要在短时间内被处理的,而Cache则可以作为一个数据的长期的容器而其中的数据不一定非要被立刻处理。
    三.

    假设某地发生了自然灾害(比如地震),居民缺衣少食,于是派救火车去给若干个居民点送水。
    救火车到达第一个居民点,开闸放水,老百姓就拿着盆盆罐罐来接水。
    假如说救火车在一个居民点停留1个小时放完了水,然后重新储水花半个小时,再开往下一个居民点。这样一个白天来来来回回的,也就是5-6个居民点。
    但我们想想,救火车是何等存在,如果把水龙头完全打开,其强大的水压能轻易冲上10层楼以上, 10分钟就可以把水全部放完。但因为居民是拿盆罐接水,100%打开水龙头那就是给人洗澡了,所以只能打开一小部分(比如10%的流量)。但这样就降低了放水的效率(只有原来的10%了),10分钟变100分钟。
    那么,我们是否能改进这个放水的过程,让救火车以最高效率放完水、尽快赶往下一个居民点呢?
    方法就是:在居民点建蓄水池。
    救火车把水放到蓄水池里,因为是以100%的效率放水,10分钟结束然后走人。居民再从蓄水池里一点一点的接水。
    我们分析一下这个例子,就可以知道Cache的含义了。
    救火车要给居民送水,居民要从救火车接水,就是说居民和救火车之间有交互,有联系。
    但救火车是“高速设备”,居民是“低速设备”,低速的居民跟不上高速的救火车,所以救火车被迫降低了放水速度以适应居民。
    为了避免这种情况,在救火车和居民之间多了一层“蓄水池(也就是Cache)”,它一方面以100%的高效和救火车打交道,另一方面以10%的低效和居民打交道,这就解放了救火车,让其以最高的效率运行,而不被低速的居民拖后腿,于是救火车只需要在一个居民点停留10分钟就可以了。
    所以说,蓄水池是“活雷锋”,把高效留给别人,把低效留给自己。把10分钟留给救火车,把100分钟留给自己。

    从以上例子可以看出,所谓Cache,就是“为了弥补高速设备和低速设备之间的矛盾”而设立的一个中间层。因为在现实里经常出现高速设备要和低速设备打交道,结果被低速设备拖后腿的情况。

    以PC为例。CPU速度很快,但CPU执行的指令是从内存取出的,计算的结果也要写回内存,但内存的响应速度跟不上CPU。
    CPU跟内存说:你把某某地址的指令发给我。内存听到了,但因为速度慢,迟迟不见指令返回,这段时间,CPU只能无所事事的等待了。这样一来,再快的CPU也发挥不了效率。
    怎么办呢?在CPU和内存之间加一块“蓄水池”,也就是Cache(片上缓存),这个Cache速度比内存快,从Cache取指令不需要等待。
    当CPU要读内存的指令的时候先读Cache再读内存,但一开始Cache是空着的,只能从内存取,这时候的确是很慢,CPU需要等待。
    但从内存取回的不仅仅是CPU所需要的指令,还有其它的、当前不需要的指令,然后把这些指令存在Cache里备用。
    CPU再取指令的时候还是先读Cache,看看里面有没有所需指令,如果碰巧有就直接从Cache取,不用等待即可返回(命中),这就解放了CPU,提高了效率。(当然也不会是100%命中,因为Cache的容量比内存小)

    CPU的Cache,可以有好几层

    磁盘缓存也是一样,刚才说内存是慢速设备,所以需要片上缓存,但这个“慢”是相对于CPU而言的,相对于机械硬盘HDD,内存的速度可快多了。
    对于磁盘的读写操作,在很久以前,读写过程需要CPU参与,后来出现了“DMA/直接内存访问"就不再需要CPU了,但即使如此,高负荷、长时间的磁盘读写也非常的耗时,因为磁盘是机械旋转部件,其读写速度相比CPU和内存条的二进制电压变化速度,那就是蒸汽机和火箭速度的差别。
    为了加快数据的读写速度,在磁盘和内存之间也插入一层Cache(Windows在内存里划分出一块区域作为Cache,硬盘也有板载Cache。)
    写入数据的时候先写入到Cache里;因为Cache很快,所以数据很快就写入。
    比方说,1G的数据,如果直接写入硬盘需要10秒,但写入Cache(也就是系统内存)只需要1秒。
    这样一来用户就有了系统速度很快的“幻觉”。但这只是障眼法,数据暂存在Cache里并没有被真正写入磁盘,等系统空闲的时候再慢慢写入。
    同理,在读数据的时候,除了所需的数据,还有一堆目前不需要的数据也都被读出来放到内存的Cache里。下次再读的时候,如果恰巧Cache里有所需的数据就可直接读入(命中),这就避免了从慢速的HDD读数据的尴尬。用户的体验同样也是速度很快。(同样不会100%命中,因为RAM的容量远小于硬盘容量)

    PC有16G的内存,Cahce占用了3.59G,这是动态的,会自动调整大小

    硬盘也内置了Cache。某品牌硬盘的广告强调了大缓存的优势

    那么buffer呢? 请允许我再次举起栗子。
    比如说吐鲁番的葡萄熟了,要用大卡车装葡萄运出去卖
    果园的姑娘采摘葡萄,当然不是前手把葡萄摘下来,后手就放到卡车上,而是需要一个中间过程“箩筐”:摘葡萄→放到箩筐里→把箩筐里的葡萄倒入卡车。
    也就是说,虽然最终目的是“把葡萄倒入卡车”,但中间必须要经过“箩筐”的转手,这里的箩筐就是Buffer。是“暂时存放物品的空间”。
    注意2个关键词:暂时,空间
    再换句话说,为了完成最终目标:把葡萄放入卡车的空间,需要暂时把葡萄放入箩筐的空间。

    以BT为例,BT下载需要长时间的挂机,电脑就有可能24小时连轴转,但BT下载的数据是碎片化的,体现在硬盘写入上也是碎片化的,因为硬盘是机械寻址器件,这种碎片化的写入会造成硬盘长时间高负荷的机械运动,造成硬盘过早老化损坏,当年有大量的硬盘因为BT下载而损坏。
    于是新出的BT软件在内存里开辟了Buffer,数据暂时写入Buffer,攒到一定的大小(比如512M)再一次性写入硬盘,这种“化零为整”的写入方式大大降低了硬盘的负荷。
    这就是:为了完成最终目标:把数据写入硬盘空间,需要暂时写入Buffer的空间

    再以编程为例,假设要实现一个功能:接受用户键入的字符串,并赋值给一个字符串变量
    其过程如下:
    1:在内存中开辟一个”键盘缓冲区“接受用户键入的字符串
    2:把该字符串赋值给变量
    也就是说,虽然最终目的是”“把用户键入的字符串赋值给字符串变量”,但中间要经过“键盘缓冲区”的转手,这个键盘缓冲区就是Buffer,也就是“暂时存放字符串的空间”
    换句话说,为了完成最终目标:把字符串放入字符串变量指向的空间,需要暂时把字符串放入“键盘缓冲区”的空间

    总结:
    Cache和Buffer的相同点:都是2个层面之间的中间层,都是内存。
    Cache和Buffer的不同点:Cache解决的是时间问题,Buffer解决的是空间问题。
    为了提高速度,引入了Cache这个中间层。
    为了给信息找到一个暂存空间,引入了Buffer这个中间层。
    为了解决2个不同维度的问题(时间、空间),恰巧取了同一种方法:加入一个中间层,先把数据写到这个中间层上,然后再写入目标。
    这个中间层就是内存“RAM”,既然是存储器就有2个参数:写入的速度有多块(速度),能装多少东西(容量)
    Cache利用的是RAM提供的高读写速度,Buffer利用的是RAM提供的存储容量。
    四:
    一个是哈希,一个是队列
    一个是二八法则,一个是速度匹配
    一个是冷热置换,一个随用随清

     

  • 相关阅读:
    wireshark 抓包rtp over tcp分析PS/H264负载的过程
    C++虚函数表
    MonoForAndroid 第一章 Android、移动设备和Marketplace 简介
    MonoForAndroid 分享用C#开发Android应用程序
    MonoForAndroid 第二章 Mono For Android 简介
    Java的垃圾回收机制及算法
    如何观测MySQL DDL的进度
    如何开启MySQL coredump
    MongoDB对日志文件进行归档的方法
    winform多线程修改界面lable
  • 原文地址:https://www.cnblogs.com/mikeluwen/p/6385605.html
Copyright © 2020-2023  润新知