Cache 浅学(一)

Cache 浅学

1 Cache基础

计算机系统一般都采用多级存储器结构,如寄存器、主存、磁盘、光盘、磁带等。这种多级存储器 的特点是从外存储器到CPU中的寄存器逐级向上,存储容量逐级减小,而存取速度逐级提高。由于上下两级存储器的速度可以相差l—2个数量级或者更高,因 此,上一级和下一级存储器的数据交换常常成为系统瓶颈,大大降低了系统的性能。为了解决这个问题,通常采用的办法是在两级存储器之间增加一个高速缓冲存储 器Cache。
所谓Cache是一个速度等于或者接近上一级存储器访问速度的小容量存储器,其中保存了下级存储器中部分当前所需的数据,因此CPU可以直接从 Cache中取得所需的数据,而不必访问下一级存储器。由于Cache的速度与上一级存储器相当,因此保证了系统效率不会降低。Cache的设计依据是程 序存取局部性原理,通常程序存取的一批数据总是存放在存储器相邻的单元中,只要把这一批数据同时调入cache中,即可保证近期内需要的数据都能在 Caclle中访问成功。为了实现上述目标,在设计Cache时必须做到以下两点:
1.保证访问Cache有较高的命中率;
2.访问Cache与访问下级存储器的方式不变、容量不减。因此对于编程人员来说,Cache是完全透明的,也就是说,他们感觉不到Cache的存在。

由于Cache的容量比下级存储器小l-2个数量级、要做到上述两点,则必须考虑以下问题:
1.如何组织Cache,使得下级存储器的每个部分都能够在需要时调入Cache
2.采用何种替换策略、使得访问cache的命中率最高;
3.采用什么方法使得Cache和下级存储器的数据具有—致性,即修改Cache后保证下级存储器的内容也随之修改(或者相反)。

2 CPU修改Cache后的处理方式

对于CPU修改了Cache的数据,如何使主存中相应单元的数据也随之修改的问题。通常有三种不同的处理方式。
第一种方式称为“直写式(write—through)”,其原理是在CPU向Cache写入的同时,也把数据写入主存储器,以保证Cache和主存中 相应单元数据的一致性。直写式系统简单可靠,但由于CPU每次更新Cache时都要对主存储器写入,因此速度受到了影响。

第二种方式称为“缓冲直写式(Posted Write)”,其原理是CPU在更新Cache时不直接更新主存中的数据,而是把更新的数据送入一个缓冲器中暂存,这样CPU就不必等待主存写入造成的 延时而直接进入下一周期的操作在适当的时候再把缓冲器中的内容写入主存中(例如在CPU读Cache的同时;把缓冲器的内容写入主存)。这种方式在一定程度上提高了速度,但由于缓冲器的容量有限,只能锁存—次写入的数据,如果发生连续的写操作则CPU仍需要等待。
上述的直写式或缓冲直写式不仅速度低,而且在很多时候向主存写入是不必要的。例如CPU可能多次对同一个Cache单元更新内容,实际上只需把最后更新结果写入主存即可,而不必更新一次 Cache,就向主存写入一次。

根据这种思想提出了第三种方式,称为“回写式(Write—back)”。有的资料中也称为“写回”。这种方式的原理是CPU修改了Cache的内容后并不立即修改主存中相应的单元,而在被修改的Cache单元的内容将从Cache中淘汰时(如更换页面)才把它写入主存储器的相应单元中。回写式系统速度快,避免了不必要的冗余写操作,但结构上比较复杂。当前的微机普遍采回写式系统。

3 SMP或DMA直接访问主存储器后的处理

多处理器或DMA直接访问主存储器造成主存和cache中的数据不一致发生在以下情形:当主存中某单元内容调入Cache后,又由其它处理器或DMA更新了主存储器该单元的内容。为了避免这种情况下的数据不一致,通常采用以下三种处理办法:
第一种方式称为“总线监视”,即由cache控制器随时监视系统的地址总线,若有其它部件向主存中写入了内容,则把Cache中相应单元的内容置为无效,CPU必须重新从主存中读人该单元的内容。

第二种方式称为“主存监视”、由Cache控制器监视所有主存储器的读写操作所有对主存的访问都必须通过Cache来完成。这样,凡对主存的写入也就对Cache中的相应单元进行拷贝从而保证了两者数据的一致性。

第三种方式是设置“不可Cache区(Non Cacheable Block)”,这种方式的基本思想是在主存中开辟一块区域,该区域中数据不受cache控制器的管理,不能调入Cache,CPU只能直接读写该区域的 内容。其它总线设备也只能把数据直接写入该区域中。由于该区域不与Cache发生关系,也就不存在数据不一致的问题。不可Cache区方式是微机中最主要 的方式,不少BIOS设置程序允许用户设置不可Cache区的首地址和尺寸、以及可Cache区的地址范围。

4 主存中的cache的映射方式

Xboot中定义了四种cache的映射类型分别如下:
enum {
MAP_TYPE_NCNB = 0x0,
MAP_TYPE_NCB = 0x1,
MAP_TYPE_CNB = 0x2,
MAP_TYPE_CB = 0x3,
};

MAP_TYPE_NCNB(Non-cached,Non-buffered),特点如下:
1) 读写数据时都是直接操作主存,并且可以被外设终止;
2) 写数据时不适用Write Buffer,CPU会等待写操作完成;
3) 不会出现cache 命中。

MAP_TYPE_NCB(Noc-Cached, buffered),特点如下:
1) 读数据时都是直接操作主存;
2) 不会出现cache命中;
3) 写数据时,数据线存入Write buffer,并在随后写入主存;
4) 数据存入Write buffer后,CPU立即执行;
5) 读数据时,可以被外设终止;
6) 写数据时,无法被外设终止。

MAP_TYPE_CNB(Cached,Non-buffered(write-through 直写模式)),特点如下:
1) 读数据时,如果cache命中则从cache中返回数据,不读取主存;
2) 读数据时,如果cache不命中则从主存中返回数据,并导致“cache miss”的动作;
3) 写数据时,数据线存入write-buffer,并在随后写入主存;
4) 数据存入write-buffer后,CPU立即继续执行;
5) 写数据时,如果cache命中则新数据写入cache中;
6) 写数据时,无法被外设终止。

MAP_TYPE_CB(Cached,Buffered(write-back 回写模式)),特点如下:
1)读数据时,如果Cache命中则从Cache中返回数据,不读取主存;
2)读数据时,如果Cache不命中则从读主存中返回数据,并导致“cache miss”的动作;
3)写数据时,如果Cache不命中则将数据先存入Write buffer,存储完毕后CPu立即继续执行,这些数据在随后写入主存;
4)写数据时,如果Cache命中则在Cache中更新数据,并设置这些数据为“脏的”,但是不会写入主存;
5)无论Cache命中与否,写数据都无法被外设中止

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、XML AJAX: Asynchronous Javascript And Xml 1、什么是XML eXtensible Markup Language 可扩展的 标记 语言 XML的标记没有预定义过,需要自行定义 XML的宗旨是做数据传递的,而非数据显示 2、XML的语法规范 XML可以保存成独立的 ***.xml 的文件,也可以以字符串的形式出现(服务器端生产) 1、XML的最顶端是XML的声明 <?xml version="1.0" encoding="utf-8" ?> 2、XML标记的语法 1、XML标记必须成对出现 2、xml标记是严格区分大小写,开始和结束必须一致 3、XML的标记也允许被嵌套,注意嵌套顺序 4、每个标记都允许自定义属性,格式与HTML一致,但属性值,必须用""括起来 5、每个XML文档中必须要有一个跟元素 3、使用AJAX 请求 XML 文档 1、要遵循AJAX的请求步骤 1、创建/获取 xhr 2、创建请求 xhr.open("get","***.xml",true); 3、设置回调函数 xhr.onreadystatechange=function(){ if(xhr.readyState==4&&xhr;.status==200){ } } 4、发送请求 xhr.send(); 2、在回调函数中,处理响应数据 使用 xhr.responseXML 来获取响应数据,返回的是XML文档对象 4、解析XML文档对象的内容 1、核心方法 elem.getElementsByTagName("标签的名字"); elem:表示的是获取范围的对象 返回值:返回一个包含指定元素们的类数组 5、在php中返回xml格式的字符串 1、必须增加响应消息头 header("Content-Tupe:application/xml"); 2、按照xml的语法结构,拼xml字符串,再响应给客户端 $xml="<?xml version='1.0' encoding='utf-8'?>"; $xml.="<...>"; ....
在静态方法中使用JdbcTemplate需要注意以下几点: 1. 静态方法中无法直接使用Spring容器中的Bean,因为静态方法是类级别的,而Bean是实例级别的。因此需要手动获取JdbcTemplate实例,可以通过ApplicationContext获取JdbcTemplate实例,或者通过静态变量保存JdbcTemplate实例。 2. 在使用JdbcTemplate时,需要先创建一个JdbcTemplate实例,并设置数据源。数据源可以通过Spring容器注入,或者手动创建。在静态方法中,可以通过静态变量保存JdbcTemplate实例,避免重复创建。 3. 在使用JdbcTemplate操作数据库时,需要注意线程安全问题。JdbcTemplate是线程安全的,但是需要保证JdbcTemplate实例的线程安全,即在多线程环境中需要保证同一JdbcTemplate实例不会被并发访问。 下面是一个示例代码: ``` public class JdbcUtils { private static JdbcTemplate jdbcTemplate; public static void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } public static void executeSql(String sql) { jdbcTemplate.execute(sql); } } ``` 在上面的代码中,我们通过静态变量保存了JdbcTemplate实例,并提供了一个静态方法setDataSource用于设置数据源。在使用JdbcTemplate时,我们可以直接调用静态方法executeSql执行SQL语句。需要注意的是,这里的executeSql方法是线程安全的,因为JdbcTemplate实例是共享的,并且JdbcTemplate本身是线程安全的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值