-
Notifications
You must be signed in to change notification settings - Fork 364
/
LRUCacheDesign.c
213 lines (193 loc) · 5.51 KB
/
LRUCacheDesign.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
Problem Statement
LRU Cache Design:-
Cache is the memory very close to CPU and has less access time. Cache is fast but also has less Space compared to RAM. Since it is small we need to have efficient utilization of small size memory. LRU(Least Recently Used) is one of the techniques for this purpose.
In LRU Cache we keep the recently accessed item least recently used item. This can be implemented using Doubly Linked List and Hash Set
Algorithm:-
=> Look for the page number in Set
=> If found(page hit) then find the node with this page number and move it to the front of the linked list
=> If not found(page miss) then:
=> Insert a new node with this page number at the front of the linked list
=> Insert an entry to the Set
=> If there are no empty frames left then remove the last node from the linked list
=> If there are empty frames left then increase the number of pages by 1
Example:-
We have the frame size of 4
and we want to add the pages: 10, 20, 30, 10, 40, 50, 30
Initially the Cache will be empty
Page Miss -> If the page which is being added is not present in the cache
Page Hit -> If the page which is being added is present in the cache
For adding each page:-
10 -> Page Miss
Cache: | 10 |
20 -> Page Miss
Cache: | 20 | 10 |
30 -> Page Miss
Cache: | 30 | 20 | 10 |
10 -> Page Hit
Cache: | 10 | 30 | 20 |
40 -> Page Miss
Cache: | 40 | 10 | 30 | 20 |
50 -> Page Miss
Cache: | 50 | 40 | 10 | 30 |
30 -> Page Hit
Cache: | 30 | 50 | 40 | 10 |
*/
#include <stdio.h>
#include <stdlib.h>
#define SET_SIZE 100
#define FRAME_SIZE 4 // Size of the Cache
int set[SET_SIZE];
int pages = 0; // To keep track of number of pages present in LRU cache
// Hash table for Set
int hash_function(int x)
{
return x % SET_SIZE;
}
// Inserting into hash table
void set_insert(int x)
{
int index = hash_function(x);
while (set[index] != 0)
index = (index + 1) % SET_SIZE;
set[index] = x;
}
// Removing from hash table
void set_remove(int x)
{
int index = hash_function(x);
while (set[index] != x)
index = (index + 1) % SET_SIZE;
set[index] = 0;
}
// Search for an element in hash table
int set_contains(int x)
{
int index = hash_function(x);
while (set[index] != x)
{
index = (index + 1) % SET_SIZE;
if (set[index] == 0)
return 0;
}
return 1;
}
// A Doubly Linked List Node
struct DllNode
{
int pageNo;
struct DllNode *next;
struct DllNode *prev;
};
typedef struct DllNode *Node;
Node newNode(int x)
{
Node temp = (Node)malloc(sizeof(struct DllNode));
temp->pageNo = x;
temp->next = NULL;
temp->prev = NULL;
return temp;
}
// Creating LRU cache with appropriate methods
Node mainConstructor()
{
Node head = newNode(0); // Head for the Linked list
Node tail = newNode(0); // Tail for the Linked list
head->next = tail;
tail->prev = head;
return head;
}
// Method for adding a page number to the cache
void addPage(Node head, Node tail, int pageNo)
{
if (set_contains(pageNo))
{
// Page Hit condition -> the page number is already present in the cache
printf("%d -> Page Hit\n", pageNo);
Node curr = head->next;
Node start = curr;
while (curr != tail)
{
if (curr->pageNo == pageNo)
{
// Remove the page from the cache from its initial position and add it to
// the staring of the list
start = curr;
curr->prev->next = curr->next;
curr->next->prev = curr->prev;
Node nextCurr = curr->next;
curr->next = NULL;
curr->prev = NULL;
curr = nextCurr;
}
else
curr = curr->next;
}
start->next = head->next;
start->prev = head;
head->next = start;
start->next->prev = start;
}
else
{
// Page Miss condition -> the page number is not present in the cache
printf("%d -> Page Miss\n", pageNo);
set_insert(pageNo);
// Add the new page number to the head of the List
Node pg = newNode(pageNo);
pg->next = head->next;
pg->prev = head;
head->next = pg;
pg->next->prev = pg;
if (pages == FRAME_SIZE)
{
// If there is no frames left for the new frame then remove the least recently
// used page(last page from the list)
Node rem = tail->prev;
rem->prev->next = tail;
tail->prev = rem->prev;
rem->next = NULL;
rem->prev = NULL;
set_remove(pageNo);
}
else
// If there are frames left then increase the number of pages in the cache
pages++;
}
}
void displayCache(Node head, Node tail)
{
if (head->next == tail)
{
printf("Empty cache\n");
return;
}
Node curr = head->next;
printf("\tLRU Cache: | ");
while (curr != tail)
{
printf("%d | ", curr->pageNo);
curr = curr->next;
}
printf("\n\n");
}
int main()
{
Node head = mainConstructor();
Node tail = head->next;
int pageNo;
printf("\n ----- LRU CACHE -----\n");
printf("\nEnter -1 to quit process\n\n");
while (1)
{
printf("Enter page number: ");
scanf("%d", &pageNo);
if (pageNo == -1)
{
printf("Terminating...");
exit(0);
}
addPage(head, tail, pageNo);
displayCache(head, tail);
}
}