Last active
February 15, 2024 21:39
-
-
Save abhi5658/a02187ca33252c8b5ffd80f6960ed6db to your computer and use it in GitHub Desktop.
Implemeting LRU cache in Javascript via set and map and time complexity O(n x m) (entries x memory size) but m is constant hence complexity is O(n)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let pages = [7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2]; | |
let memorySize = 4; | |
function lruCache1() { | |
let memory = new Set(); | |
let recentUsedPageIndex = new Map(); | |
let pageFault = 0; | |
for (let i = 0; i < pages.length; i++) { | |
const currentPage = pages[i]; | |
const isPresentInMemory = memory.has(currentPage); | |
if (memory.size < memorySize) { | |
if (!isPresentInMemory) { | |
pageFault++ | |
memory.add(currentPage); | |
// recentlyUsedMap.set(index, currentPage) | |
} else { | |
// present in memory | |
// need to update index of that page | |
// recentUsedPageIndex.set(currentPage,i); | |
} | |
} else { // memory is full | |
if (!isPresentInMemory) { | |
pageFault++; | |
// find lru | |
let lruIndex = Number.MAX_VALUE, lruPage = null; | |
for (let [page, index] of recentUsedPageIndex.entries()) { | |
if (index < lruIndex) { | |
lruIndex = index; | |
lruPage = page; | |
} | |
} | |
// remove from recentlyUsedMap | |
memory.delete(lruPage) | |
recentUsedPageIndex.delete(lruPage); | |
// set new recentlyUsedMap | |
// recentUsedPageIndex.set(currentPage,i); | |
memory.add(currentPage) | |
} else { | |
// present in memory | |
// need to update index of that page | |
// recentUsedPageIndex.set(currentPage,i); | |
} | |
} | |
// updating index once as applicable for all cases | |
recentUsedPageIndex.set(currentPage, i); | |
printCurrentStatus(pageFault, currentPage, memory, recentUsedPageIndex); | |
} | |
return pageFault; | |
} | |
/** | |
* Just a refactor with different code flow but using same algorithm | |
* @returns pageFault | |
*/ | |
function lruCache2() { | |
let memory = new Set(); | |
let recentUsedPageIndex = new Map(); | |
let pageFault = 0; | |
for (let i = 0; i < pages.length; i++) { | |
const currentPage = pages[i]; | |
const isPresentInMemory = memory.has(currentPage); | |
if (isPresentInMemory) { | |
// update index of existing page | |
recentUsedPageIndex.set(currentPage, i); | |
} else { | |
// not present present in memory | |
pageFault++; | |
if (memory.size < memorySize) { // add | |
memory.add(currentPage); | |
// add index of new page | |
recentUsedPageIndex.set(currentPage, i); | |
} else { // remove and add | |
let lruIndex = Number.MAX_VALUE; // index of least recently used page | |
let lruPage = null; // least recently used page | |
for (let [page, index] of recentUsedPageIndex.entries()) { | |
if (index < lruIndex) { | |
lruIndex = index; | |
lruPage = page; | |
} | |
} | |
// remove from memory | |
memory.delete(lruPage) | |
recentUsedPageIndex.delete(lruPage); | |
// add in memory | |
memory.add(currentPage) | |
// add index of new page | |
recentUsedPageIndex.set(currentPage, i); | |
} | |
} | |
printCurrentStatus(pageFault, currentPage, memory, recentUsedPageIndex); | |
} | |
return pageFault; | |
} | |
console.log('pageFault | page | memory | recentUsedPageIndex') | |
console.log(lruCache1()); // 6 | |
// pageFault | page | memory | recentUsedPageIndex | |
// 1 7 Set(1) { 7 } [ '7->0' ] | |
// 2 0 Set(2) { 7, 0 } [ '7->0', '0->1' ] | |
// 3 1 Set(3) { 7, 0, 1 } [ '7->0', '0->1', '1->2' ] | |
// 4 2 Set(4) { 7, 0, 1, 2 } [ '7->0', '0->1', '1->2', '2->3' ] | |
// 4 0 Set(4) { 7, 0, 1, 2 } [ '7->0', '0->4', '1->2', '2->3' ] | |
// 5 3 Set(4) { 0, 1, 2, 3 } [ '0->4', '1->2', '2->3', '3->5' ] | |
// 5 0 Set(4) { 0, 1, 2, 3 } [ '0->6', '1->2', '2->3', '3->5' ] | |
// 6 4 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->3', '3->5', '4->7' ] | |
// 6 2 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->8', '3->5', '4->7' ] | |
// 6 3 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->8', '3->9', '4->7' ] | |
// 6 0 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->8', '3->9', '4->7' ] | |
// 6 3 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->8', '3->11', '4->7' ] | |
// 6 2 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->12', '3->11', '4->7' ] | |
console.log('========================='); | |
console.log('pageFault | page | memory | recentUsedPageIndex') | |
console.log(lruCache2()); // 6 | |
// pageFault | page | memory | recentUsedPageIndex | |
// 1 7 Set(1) { 7 } [ '7->0' ] | |
// 2 0 Set(2) { 7, 0 } [ '7->0', '0->1' ] | |
// 3 1 Set(3) { 7, 0, 1 } [ '7->0', '0->1', '1->2' ] | |
// 4 2 Set(4) { 7, 0, 1, 2 } [ '7->0', '0->1', '1->2', '2->3' ] | |
// 4 0 Set(4) { 7, 0, 1, 2 } [ '7->0', '0->4', '1->2', '2->3' ] | |
// 5 3 Set(4) { 0, 1, 2, 3 } [ '0->4', '1->2', '2->3', '3->5' ] | |
// 5 0 Set(4) { 0, 1, 2, 3 } [ '0->6', '1->2', '2->3', '3->5' ] | |
// 6 4 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->3', '3->5', '4->7' ] | |
// 6 2 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->8', '3->5', '4->7' ] | |
// 6 3 Set(4) { 0, 2, 3, 4 } [ '0->6', '2->8', '3->9', '4->7' ] | |
// 6 0 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->8', '3->9', '4->7' ] | |
// 6 3 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->8', '3->11', '4->7' ] | |
// 6 2 Set(4) { 0, 2, 3, 4 } [ '0->10', '2->12', '3->11', '4->7' ] | |
/** | |
* | |
* @param {Number} currentPage | |
* @param {Number} pageFault | |
* @param {Set} memory | |
* @param {Map} recentUsedPageIndex | |
*/ | |
function printCurrentStatus(pageFault, currentPage, memory, recentUsedPageIndex) { | |
// const memoryStatus = Array.from(memory.values()).map(p => p); | |
const recentUsedStatus = Array.from(recentUsedPageIndex.entries()).map(arr => { return `${arr[0]}->${arr[1]}` }) | |
console.log(pageFault, currentPage, memory, '\t', recentUsedStatus); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment