Open In App
Related Articles

Page Faults in LRU | Implementation

Improve Article
Improve
Save Article
Save
Like Article
Like

LRU uses the concept of paging for memory management, a page replacement algorithm is needed to decide which page needs to be replaced when the new page comes in. Whenever a new page is referred to and is not present in memory, the page fault occurs and the Operating System replaces one of the existing pages with a newly needed page. LRU is one such page replacement policy in which the least recently used pages are replaced.

For example:
Given a sequence of pages in an array of pages[] of length N and memory capacity C, find the number of page faults using the Least Recently Used (LRU) Algorithm.

Example-1 :

Input : N = 7, C = 3
pages = {1, 2, 1, 4, 2, 3, 5}
Output : 5

Explanation :

Capacity is 3, thus, we can store maximum 3 pages at a time.
Page 1 is required, since it is not present, 
it is a page fault: page fault = 1

Page 2 is required, since it is not present, 
it is a page fault: page fault = 1 + 1 = 2

Page 1 is required, since it is present, 
it is not a page fault: page fault = 2 + 0 = 2

Page 4 is required, since it is not present, 
it is a page fault: page fault = 2 + 1 = 3

Page 2 is required, since it is present, 
it is not a page fault: page fault = 3 + 0 = 3

Page 3 is required, since it is not present, 
it replaces LRU page 2: page fault = 3 + 1 = 4

Page 5 is required, since it is not present, 
it replaces LRU page 1: page fault = 4 + 1 = 5

Example-2 :

Input : N = 9, C = 4
Pages = {5, 0, 1, 3, 2, 4, 1, 0, 5}
Output : 8

Explanation :

Capacity is 4, thus, we can store maximum 4 pages at a time.
Page 5 is required, since it is not present, 
it is a page fault: page fault = 1

Page 0 is required, since it is not present, 
it is a page fault: page fault = 1 + 1 = 2

Page 1 is required, since it is not present, 
it is a page fault: page fault = 2 + 1 = 3

Page 3 is required, since it is not present, 
it is a page fault: page fault = 3 + 1 = 4

Page 2 is required, since it is not present, 
it replaces LRU page 5: page fault = 4 + 1 = 5

Page 4 is required, since it is not present, 
it replaces LRU page 0: page fault = 5 + 1 = 6

Page 1 is required, since it is present, 
it is not a page fault: page fault = 6 + 0 = 6

Page 0 is required, since it is not present, 
it replaces LRU page 3: page fault = 6 + 1 = 7

Page 5 is required, since it is not present, 
it replaces LRU page 2: page fault = 7 + 1 = 8

Algorithm :

step-1 : Initialize count as 0.
step-2 : Create a vector / array of size equal to memory capacity.
step-3 : Traverse elements of pages[]
step-4 : In each traversal:
        if(element is present in memory):
            remove the element and push the element at the end  
        else:
            if(memory is full) remove the first element
            Increment count 
            push the element at the end       

Implementation of the algorithm :

Following is the implementation of the algorithm in C++ as follows.

C++




// C++ program to illustrate
// page faults in LRU
 
#include <bits/stdc++.h>
using namespace std;
 
/* Counts no. of page faults */
int pageFaults(int n, int c, int pages[])
{
    // Initialise count to 0
    int count = 0;
 
    // To store elements in memory of size c
    vector<int> v;
    int i;
    for (i = 0; i <= n - 1; i++) {
 
        // Find if element is present in memory or not
        auto it = find(v.begin(), v.end(), pages[i]);
 
        // If element is not present
        if (it == v.end()) {
 
            // If memory is full
            if (v.size() == c) {
               
                // Remove the first element
                // As it is least recently used
                v.erase(v.begin());
            }
 
            // Add the recent element into memory
            v.push_back(pages[i]);
 
            // Increment the count
            count++;
        }
        else {
 
            // If element is present
            // Remove the element
            // And add it at the end as it is
            // the most recent element
            v.erase(it);
            v.push_back(pages[i]);
        }
    }
 
    // Return total page faults
    return count;
}
 
/* Driver program to test pageFaults function*/
int main()
{
 
    int pages[] = { 1, 2, 1, 4, 2, 3, 5 };
    int n = 7, c = 3;
 
    cout << "Page Faults = " << pageFaults(n, c, pages);
    return 0;
}
 
// This code is contributed by rajsanghavi9.

Java




// Java program to illustrate
// page faults in LRU
import java.util.*;
class GFG {
  public static void main(String[] args)
  {
    int pages[] = new int[] { 1, 2, 1, 4, 2, 3, 5 };
    int n = 7, c = 3;
 
    System.out.println("Page Faults = "
                       + pageFaults(n, c, pages));
  }
  static int pageFaults(int N, int C, int pages[])
  {
    // a queue to maintain page frames
    Queue<Integer> q = new LinkedList<>();
 
    // starting with 0 page faults
    int i = 0, c = 0;
    while (i < N)
    {
 
      // if queue is empty or the current page is
      // absent in the page frame then page fault
      // occurs
      if (q.isEmpty() || !q.contains(pages[i]))
      {
        if (q.size()== C) // if frame is full we remove the
          // least recently used page
          q.poll(); // removing the front element
        // which is not replaced for
        // long time
 
        q.add(pages[i]); // now we add the page to
        // frame
        c++; // incrementing page faults
      }
      else
      {
        q.remove(pages[i]); // if the page already exists
        // we'll remove it from
        // previous position and add
        // it to the end of the queue
        q.add(pages[i]);
      }
 
      i++;
    }
    return c;
  }
}
// This code is contributed by tharunmadishetti1.

Python3




# Python program to illustrate
# page faults in LRU
 
# Counts no. of page faults
def pageFaults(n, c, pages):
 
    # Initialise count to 0
    count = 0
 
    # To store elements in memory of size c
    v = []
 
    # Iterate through all elements of pages
    for i in range(n):
 
        # Find if element is present in memory or not
        if pages[i] not in v:
 
            # If memory is full
            if len(v) == c:
 
                # Remove the first element
                # As it is least recently used
                v.pop(0)
 
            # Add the recent element into memory
            v.append(pages[i])
 
            # Increment the count
            count += 1
        else:
 
            # If element is present
            # Remove the element
            # And add it at the end as it is
            # the most recent element
            v.remove(pages[i])
            v.append(pages[i])
 
    # Return total page faults
    return count
 
 
# Driver program to test pageFaults function
pages = [1, 2, 1, 4, 2, 3, 5]
n = 7
c = 3
 
print("Page Faults =", pageFaults(n, c, pages))
 
# This code is contributed by ishankhandelwals.

C#




using System;
using System.Collections.Generic;
 
namespace pageFaults {
  class Program
  {
 
    /* Counts no. of page faults */
    static int pageFaults(int n, int c, int[] pages)
    {
      // Initialise count to 0
      int count = 0;
 
      // To store elements in memory of size c
      List<int> v = new List<int>();
      int i;
      for (i = 0; i <= n - 1; i++) {
 
        // Find if element is present in memory or not
        int it = v.IndexOf(pages[i]);
 
        // If element is not present
        if (it == -1) {
 
          // If memory is full
          if (v.Count == c) {
 
            // Remove the first element
            // As it is least recently used
            v.RemoveAt(0);
          }
 
          // Add the recent element into memory
          v.Add(pages[i]);
 
          // Increment the count
          count++;
        }
        else {
 
          // If element is present
          // Remove the element
          // And add it at the end as it is
          // the most recent element
          v.RemoveAt(it);
          v.Add(pages[i]);
        }
      }
 
      // Return total page faults
      return count;
    }
 
    /* Driver program to test pageFaults function*/
    static void Main(string[] args)
    {
 
      int[] pages = { 1, 2, 1, 4, 2, 3, 5 };
      int n = 7, c = 3;
 
      Console.WriteLine("Page Faults = "
                        + pageFaults(n, c, pages));
    }
  }
}

Javascript




function pageFaults(n, c, pages) {
    // Initialize count to 0
    let count = 0;
 
    // To store elements in memory of size c
    let memory = [];
    for (let i = 0; i < n; i++) {
 
        // Find if element is present in memory or not
        let index = memory.indexOf(pages[i]);
 
        // If element is not present
        if (index === -1) {
 
            // If memory is full
            if (memory.length === c) {
 
                // Remove the first element
                // As it is least recently used
                memory.shift();
            }
 
            // Add the recent element into memory
            memory.push(pages[i]);
 
            // Increment the count
            count++;
        } else {
 
            // If element is present
            // Remove the element
            // And add it at the end as it is
            // the most recent element
            memory.splice(index, 1);
            memory.push(pages[i]);
        }
    }
 
    // Return total page faults
    return count;
}
 
let pages = [1, 2, 1, 4, 2, 3, 5];
let n = 7;
let c = 3;
console.log(`Page Faults = ${pageFaults(n, c, pages)}`);
 
// This code is contributed by ishankhandelwals.

Output

Page Faults = 5

Output :

Page Faults = 5

Time Complexity: O(N*C)
Auxiliary Space:  O(C)

Approach using Doubly Linked List and Maps

We can use an unordered map and a doubly linked list to solve this problem efficiently. This is done by maintaining a map of nodes in memory. For each recently used node we can push it at the back of our doubly linked list, it consumes O(1) time. Searching in the map also takes O(1) time (NO HASH COLLISIONS ASSUMED). When we hit full capacity in memory, shift the head of the linked list and erase its occurrence from the map. This also can be done in O(1) time. Thus, giving the algorithm a runtime of O(N) in the worst case.

Follow the following steps to implement the idea

1) Construct the structure of the node of the doubly linked list. This contains data, previous and next pointers. 

2) Start iterating in the array/stream of inputs. If the data is already in the map, this means its in memory. Find the pointer which is against the data and place it at the end of the linked list, signifying it was recently accessed with necessary linkages.

3) If the data is not in the map, place it at the end of the linked list with necessary linkages. And insert the data in the map with its node pointer. Also increment the page fault, since its not in the memory

4) Return the number of page faults.

C++




// Author: RainX (ABHIJIT ROY, NIT AGARTALA)
 
#include <bits/stdc++.h>
using namespace std;
 
struct Node {
    int data;
    Node* next = nullptr;
    Node* prev = nullptr;
    Node(int data) {
      this->data = data;
    }
};
 
unordered_map<int, Node*> mpp;
int size = 0;
Node* head = nullptr;
Node* tail = nullptr;
 
int pageFaults(int N, int C, int pages[]) {
    int faults = 0;
    for (int i = 0; i < N; i++) {
        if (mpp.find(pages[i]) == mpp.end()) {  // O(1)
            faults++;
            if (size == C) {
                mpp.erase(head->data);
                head = head->next;
                size--;
            }
            Node* newNode = new Node(pages[i]);
            if (head == nullptr) {
                head = newNode;
                tail = head;
            }
           
            newNode->prev = tail;
            tail->next = newNode;
            tail = tail->next;
           
            size++;
            mpp[pages[i]] = newNode;
        }
        else {
            Node* ptr = mpp[pages[i]];
            if (ptr == head) {   // O(1) linkage time
                head = head->next;
                ptr->prev = tail;
                tail->next = ptr;
                tail = tail->next;
            }
            else if (tail != ptr) {  // O(1) linkage time
                ptr->prev->next = ptr->next;
                ptr->next->prev = ptr->prev;
                ptr->prev = tail;
                tail->next = ptr;
                tail = tail->next;
            }
        }
    }
    return faults;
}
 
int main(){
 
    int pages[] = { 1, 2, 1, 4, 2, 3, 5 };
    int n = 7, c = 3;
 
    cout << "Page Faults = " << pageFaults(n, c, pages);
    return 0;
}
 
// Author: RainX (ABHIJIT ROY, NIT AGARTALA)

Output

Page Faults = 5
  • Time Complexity: O(N)

                       Explanation: Node linkages in linked list takes O(1) constant time

                                              Accessing elements from map takes O(1) time on average

  • Auxiliary Space:  O(C)  

                      Explanation: Linked list size is of C nodes. 


Last Updated : 27 Mar, 2023
Like Article
Save Article
Similar Reads