为了加深对缓存算法的理解,特转此篇,又由于本文内容过多,故不做翻译,原文地址Working Set页面置换算法

In the purest form of paging, processes are started up with none of their pages in memory. As soon as the CPU tries to fetch the first instruction, it gets a page fault, causing the operating system to bring in the page containing the first instruction. Other page faults for global variables and the stack usually follow quickly. After a while, the process has most of the pages it needs and settles down to run with relatively few page faults. This strategy is called demand paging because pages are loaded only on demand, not in advance.

Of course, it is easy enough to write a test program that systematically reads all the pages in a large address space, causing so many page faults that there is not enough memory to hold them all. Fortunately, most processes do not work this way. They exhibit a locality of reference, meaning that during any phase of execution, the process references only a relatively small fraction of its pages. Each pass of a multipass compiler, for example, references only a fraction of all the pages, and a different fraction at that.

The set of pages that a process is currently using is called its working set (Denning, 1968a; Denning, 1980). If the entire working set is in memory, the process will run without causing many faults until it moves into another execution phase (e.g., the next pass of the compiler). If the available memory is too small to hold the entire working set, the process will cause many page faults and run slowly since executing an instruction takes a few nanoseconds and reading in a page from the disk typically takes 10 milliseconds. At a rate of one or two instructions per 10 milliseconds, it will take ages to finish. A program causing page faults every few instructions is said to be thrashing (Denning, 1968b).

In a multiprogramming system, processes are frequently moved to disk (i.e., all their pages are removed from memory) to let other processes have a turn at the CPU. The question arises of what to do when a process is brought back in again. Technically, nothing need be done. The process will just cause page faults until its working set has been loaded. The problem is that having 20, 100, or even 1000 page faults every time a process is loaded is slow, and it also wastes considerable CPU time, since it takes the operating system a few milliseconds of CPU time to process a page fault.

Therefore, many paging systems try to keep track of each process' working set and make sure that it is in memory before letting the process run. This approach is called the working set model (Denning, 1970). It is designed to greatly reduce the page fault rate. Loading the pages before letting processes run is also called prepaging. Note that the working set changes over time.

It has been long known that most programs do not reference their address space uniformly, but that the references tend to cluster on a small number of pages. A memory reference may fetch an instruction, it may fetch data, or it may store data. At any instant of time, t, there exists a set consisting of all the pages used by the most recent memory references. This set, w(kt), is the working set. Because the k= 1 most recent references must have used all the pages used by the k > 1 most recent references, and possibly others, w(kt) is a monotonically nondecreasing function of k. The limit of w(kt) as becomes large is finite because a program cannot reference more pages than its address space contains, and few programs will use every single page. Figure 4-5 depicts the size of the working set as a function of k.

Figure 4-5. The working set is the set of pages used by the k most recent memory references. The function w(k, t) is the size of the working set at time t.

The fact that most programs randomly access a small number of pages, but that this set changes slowly in time explains the initial rapid rise of the curve and then the slow rise for large k. For example, a program that is executing a loop occupying two pages using data on four pages, may reference all six pages every 1000 instructions, but the most recent reference to some other page may be a million instructions earlier, during the initialization phase. Due to this asymptotic behavior, the contents of the working set is not sensitive to the value of chosen. To put it differently, there exists a wide range of kvalues for which the working set is unchanged. Because the working set varies slowly with time, it is possible to make a reasonable guess as to which pages will be needed when the program is restarted on the basis of its working set when it was last stopped. Prepaging consists of loading these pages before the process is allowed to run again.

To implement the working set model, it is necessary for the operating system to keep track of which pages are in the working set. Having this information also immediately leads to a possible page replacement algorithm: when a page fault occurs, find a page not in the working set and evict it. To implement such an algorithm, we need a precise way of determining which pages are in the working set and which are not at any given moment in time.

As we mentioned above, the working set is the set of pages used in the most recent memory references (some authors use the most recent page references, but the choice is arbitrary). To implement any working set algorithm, some value of must be chosen in advance. Once some value has been selected, after every memory reference, the set of pages used by the previous memory references is uniquely determined.

Of course, having an operational definition of the working set does not mean that there is an efficient way to monitor it in real time, during program execution. One could imagine a shift register of length k, with every memory reference shifting the register left one position and inserting the most recently referenced page number on the right. The set of all page numbers in the shift register would be the working set. In theory, at a page fault, the contents of the shift register could be read out and sorted. Duplicate pages could then be removed. The result would be the working set. However, maintaining the shift register and processing it at a page fault would both be prohibitively expensive, so this technique is never used.

Instead, various approximations are used. One commonly used approximation is to drop the idea of counting back memory references and use execution time instead. For example, instead of defining the working set as those pages used during the previous 10 million memory references, we can define it as the set of pages used during the past 100 msec of execution time. In practice, such a definition is just as good and much easier to use. Note that for each process, only its own execution time counts. Thus if a process starts running at time and has had 40 msec of CPU time at real time + 100 msec, for working set purposes, its time is 40 msec. The amount of CPU time a process has actually used has since it started is often called its current virtual time. With this approximation, the working set of a process is the set of pages it has referenced during the past t seconds of virtual time.

Now let us look at a page replacement algorithm based on the working set. The basic idea is to find a page that is not in the working set and evict it. In Fig. 4-6 we see a portion of a page table for some machine. Because only pages that are in memory are considered as candidates for eviction, pages that are absent from memory are ignored by this algorithm. Each entry contains (at least) two items of information: the approximate time the page was last used and the (Referenced) bit. The empty white rectangle symbolizes the other fields not needed for this algorithm, such as the page frame number, the protection bits, and the (Modified) bit.

Figure 4-6. The working set algorithm.

The algorithm works as follows. The hardware is assumed to set the and bits, as we have discussed before. Similarly, a periodic clock interrupt is assumed to cause software to run that clears theReferenced bit on every clock tick. On every page fault, the page table is scanned to look for a suitable page to evict.

As each entry is processed, the bit is examined. If it is 1, the current virtual time is written into the Time of last use field in the page table, indicating that the page was in use at the time the fault occurred. Since the page has been referenced during the current clock tick, it is clearly in the working set and is not a candidate for removal (t is assumed to span multiple clock ticks).

If is 0, the page has not been referenced during the current clock tick and may be a candidate for removal. To see whether or not it should be removed, its age, that is, the current virtual time minus its Time of last use is computed and compared to t. If the age is greater than t, the page is no longer in the working set. It is reclaimed and the new page loaded here. The scan continues updating the remaining entries, however.

However, if is 0 but the age is less than or equal to t, the page is still in the working set. The page is temporarily spared, but the page with the greatest age (smallest value of Time of last use) is noted. If the entire table is scanned without finding a candidate to evict, that means that all pages are in the working set. In that case, if one or more pages with = 0 were found, the one with the greatest age is evicted. In the worst case, all pages have been referenced during the current clock tick (and thus all have = 1), so one is chosen at random for removal, preferably a clean page, if one exists.

Working Set缓存算法(转)的更多相关文章

  1. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  2. 缓存算法之belady现象

    前言 在使用FIFO算法作为缺页置换算法时,分配的缺页增多,但缺页率反而提高,这样的异常现象称为belady Anomaly. 虽然这种现象说明的场景是缺页置换,但在运用FIFO算法作为缓存算法时,同 ...

  3. android上的缓存、缓存算法和缓存框架

      1.使用缓存的目的 缓存是存取数据的临时地,因为取原始数据代价太大了,加了缓存,可以取得快些.缓存可以认为是原始数据的子集,它是从原始数据里复制出来的,并且为了能被取回,被加上了标志. 在andr ...

  4. java缓存算法【转】

    http://my.oschina.net/u/866190/blog/188712 提到缓存,不得不提就是缓存算法(淘汰算法),常见算法有LRU.LFU和FIFO等算法,每种算法各有各的优势和缺点及 ...

  5. 面试挂在了 LRU 缓存算法设计上

    好吧,有人可能觉得我标题党了,但我想告诉你们的是,前阵子面试确实挂在了 RLU 缓存算法的设计上了.当时做题的时候,自己想的太多了,感觉设计一个 LRU(Least recently used) 缓存 ...

  6. -实现 LFU 缓存算法

    -实现 LFU 缓存算法, 设计一个类 LFUCache,实现下面三个函数 + 构造函数: 传入 Cache 内最多能存储的 key 的数量 + get(key):如果 Cache 中存在该 key, ...

  7. 缓存算法(FIFO 、LRU、LFU三种算法的区别)

    FIFO算法 FIFO 算法是一种比较容易实现的算法.它的思想是先进先出(FIFO,队列),这是最简单.最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小.空间满的时 ...

  8. 算法进阶面试题06——实现LFU缓存算法、计算带括号的公式、介绍和实现跳表结构

    接着第四课的内容,主要讲LFU.表达式计算和跳表 第一题 上一题实现了LRU缓存算法,LFU也是一个著名的缓存算法 自行了解之后实现LFU中的set 和 get 要求:两个方法的时间复杂度都为O(1) ...

  9. 【转】Memcached之缓存雪崩,缓存穿透,缓存预热,缓存算法

    缓存雪崩 缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机. 解决思路: 1,采用加锁计数,或者使用合理的队列 ...

随机推荐

  1. GitHub Desktop 桌面工具,离线版本下载(无需考虑网络问题)

    http://pan.baidu.com/s/1qYq4X0C GitHub Desktop 桌面工具,离线版本下载 对于网络不好,不稳定,安装多次都不成功的,这是你们的最好的安装方法了.

  2. node模块的分类

    模块的分类 1.核心模块 2.文件模块 3.第三方模块(npm安装的) 模块的引用: 1.路径 2.模块名 模块的流程: 1.创建模块:teacher.js 2.导出模块:exports.add=fu ...

  3. yii2 GridView常见操作

    作者:白狼 出处:http://www.manks.top/article/yii2_gridview 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  4. jstack简单使用,定位死循环、线程阻塞、死锁等问题

    当我们运行java程序时,发现程序不动,但又不知道是哪里出问题时,可以使用JDK自带的jstack工具去定位: 废话不说,直接上例子吧,在window平台上的: 死循环 写个死循环的程序如下: pac ...

  5. git浅谈

    我们为什么要使用git 应用场景分析 1.使用svn,已经开发完一个需求,正在开发第二个需求,但是测试需要你立刻将你完成的第一个需求提交,请问现在你该怎么做: svn的解决方法大概是这样的:打开提交视 ...

  6. 优化SQLServer——表和分区索引(二)

    简介     之前一篇简单的介绍了语法和一些基本的概念,隔了一段时间,觉得有必要细致的通过实例来总结一下这部分内容.如之前所说,分区就是讲大型的对象(表)分成更小的块来管理,基本单位是行.这也就产生了 ...

  7. 烂泥:学习ubuntu之快速搭建LNMP环境

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 现在公司使用的都是ubuntu系统,这几天由于个别项目需要,需要搭建一个LNMP环境.为了快速搭建这个环境,我使用是apt-get方式进行安装.具体的操作 ...

  8. 010 使用netmap API接管网卡,接收数据包,回应ARP请求

    一.本文目的: 上一节中,我们已经在CentOS 6.7 上安装好了netmap,也能接收和发送包了,这节我们来调用netmap中的API,接管网卡,对网卡上收到的数据包做分析,并回应ARP请求. 二 ...

  9. 如何让django方法自动地定期执行

    实现思路:1.首先把需要自动执行的django method写成django command2.将自己定义的django command添加到cron中使用cron服务实现定期执行 Part1 在dj ...

  10. Solr初始化源码分析-Solr初始化与启动

    用solr做项目已经有一年有余,但都是使用层面,只是利用solr现有机制,修改参数,然后监控调优,从没有对solr进行源码级别的研究.但是,最近手头的一个项目,让我感觉必须把solrn内部原理和扩展机 ...