కోడ్ పనితీరును ఆప్టిమైజ్ చేయడానికి జావాస్క్రిప్ట్ మెమోయిజేషన్ టెక్నిక్లు, కాషింగ్ వ్యూహాలు మరియు ఆచరణాత్మక ఉదాహరణలను అన్వేషించండి. వేగవంతమైన అమలు కోసం మెమోయిజేషన్ నమూనాలను ఎలా అమలు చేయాలో తెలుసుకోండి.
జావాస్క్రిప్ట్ మెమోయిజేషన్ నమూనాలు: కాషింగ్ వ్యూహాలు మరియు పనితీరు లాభాలు
సాఫ్ట్వేర్ అభివృద్ధి రంగంలో, పనితీరు చాలా ముఖ్యం. జావాస్క్రిప్ట్, ఫ్రంట్-ఎండ్ వెబ్ డెవలప్మెంట్ నుండి Node.jsతో సర్వర్-సైడ్ అప్లికేషన్ల వరకు విభిన్న పరిసరాలలో ఉపయోగించే బహుముఖ భాష కాబట్టి, సున్నితమైన మరియు సమర్థవంతమైన అమలును నిర్ధారించడానికి తరచుగా ఆప్టిమైజేషన్ అవసరం. నిర్దిష్ట పరిస్థితులలో పనితీరును గణనీయంగా మెరుగుపరచగల ఒక శక్తివంతమైన సాంకేతికత మెమోయిజేషన్.
మెమోయిజేషన్ అనేది ఖరీదైన ఫంక్షన్ కాల్ల ఫలితాలను నిల్వ చేయడం ద్వారా మరియు అదే ఇన్పుట్లు మళ్లీ సంభవించినప్పుడు కాష్ చేసిన ఫలితాన్ని తిరిగి ఇవ్వడం ద్వారా కంప్యూటర్ ప్రోగ్రామ్లను వేగవంతం చేయడానికి ప్రధానంగా ఉపయోగించే ఆప్టిమైజేషన్ టెక్నిక్. సారాంశంలో, ఇది ప్రత్యేకంగా ఫంక్షన్లను లక్ష్యంగా చేసుకునే కాషింగ్ రూపం. ఈ విధానం ప్రత్యేకంగా క్రింది ఫంక్షన్లకు ప్రభావవంతంగా ఉంటుంది:
- స్వచ్ఛమైనవి: దుష్ప్రభావాలు లేకుండా, వాటి ఇన్పుట్ విలువలను బట్టి మాత్రమే తిరిగి వచ్చే విలువను కలిగి ఉండే ఫంక్షన్లు.
- నిర్ధారకమైనవి: ఒకే ఇన్పుట్ కోసం, ఫంక్షన్ ఎల్లప్పుడూ ఒకే అవుట్పుట్ను ఉత్పత్తి చేస్తుంది.
- ఖరీదైనవి: గణనపరంగా తీవ్రమైన లేదా సమయం తీసుకునే గణనలు చేసే ఫంక్షన్లు (ఉదా., పునరావృత ఫంక్షన్లు, సంక్లిష్ట గణనలు).
ఈ కథనం జావాస్క్రిప్ట్లో మెమోయిజేషన్ యొక్క భావనను విశ్లేషిస్తుంది, దాని అమలు ద్వారా సాధించగల వివిధ నమూనాలు, కాషింగ్ వ్యూహాలు మరియు పనితీరు లాభాలను పరిశీలిస్తుంది. విభిన్న పరిస్థితులలో మెమోయిజేషన్ను సమర్థవంతంగా ఎలా అన్వయించాలో వివరించడానికి మేము ఆచరణాత్మక ఉదాహరణలను పరిశీలిస్తాము.
మెమోయిజేషన్ను అర్థం చేసుకోవడం: ప్రధాన భావన
దాని ప్రధానాంశంలో, మెమోయిజేషన్ కాషింగ్ సూత్రాన్ని ఉపయోగించుకుంటుంది. ఒక నిర్దిష్ట ఆర్గ్యుమెంట్లతో మెమోయిజ్డ్ ఫంక్షన్ కాల్ చేసినప్పుడు, అది మొదట ఆ ఆర్గ్యుమెంట్ల కోసం ఫలితం ఇప్పటికే లెక్కించబడి, కాష్లో నిల్వ చేయబడిందో లేదో తనిఖీ చేస్తుంది (సాధారణంగా జావాస్క్రిప్ట్ ఆబ్జెక్ట్ లేదా మ్యాప్). ఫలితం కాష్లో కనుగొనబడితే, అది వెంటనే తిరిగి ఇవ్వబడుతుంది. లేకపోతే, ఫంక్షన్ గణనను అమలు చేస్తుంది, ఫలితాన్ని కాష్లో నిల్వ చేస్తుంది, ఆపై దానిని తిరిగి ఇస్తుంది.
పునరావృత గణనలను నివారించడంలో ప్రధాన ప్రయోజనం ఉంది. ఒక ఫంక్షన్ ఒకే ఇన్పుట్లతో చాలాసార్లు కాల్ చేయబడితే, మెమోయిజ్డ్ వెర్షన్ ఒకసారి మాత్రమే లెక్కిస్తుంది. తదుపరి కాల్లు నేరుగా కాష్ నుండి ఫలితాన్ని పొందుతాయి, ఫలితంగా గణనీయమైన పనితీరు మెరుగుదలలు వస్తాయి, ముఖ్యంగా గణనపరంగా ఖరీదైన కార్యకలాపాల కోసం.
జావాస్క్రిప్ట్లో మెమోయిజేషన్ నమూనాలు
జావాస్క్రిప్ట్లో మెమోయిజేషన్ను అమలు చేయడానికి అనేక నమూనాలను ఉపయోగించవచ్చు. అత్యంత సాధారణమైన మరియు ప్రభావవంతమైన వాటిని కొన్నింటిని పరిశీలిద్దాం:
1. క్లోజర్తో ప్రాథమిక మెమోయిజేషన్
మెమోయిజేషన్కు ఇది చాలా ప్రాథమిక విధానం. ఇది ఫంక్షన్ యొక్క పరిధిలో కాష్ను నిర్వహించడానికి క్లోజర్ను ఉపయోగిస్తుంది. కాష్ సాధారణంగా సాధారణ జావాస్క్రిప్ట్ ఆబ్జెక్ట్, ఇక్కడ కీలు ఫంక్షన్ ఆర్గ్యుమెంట్లను సూచిస్తాయి మరియు విలువలు సంబంధిత ఫలితాలను సూచిస్తాయి.
function memoize(func) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args); // ఆర్గ్యుమెంట్ల కోసం ప్రత్యేక కీని సృష్టించండి
if (cache[key]) {
return cache[key]; // కాష్ చేసిన ఫలితాన్ని తిరిగి ఇవ్వండి
} else {
const result = func.apply(this, args); // ఫలితాన్ని లెక్కించండి
cache[key] = result; // ఫలితాన్ని కాష్లో నిల్వ చేయండి
return result; // ఫలితాన్ని తిరిగి ఇవ్వండి
}
};
}
// ఉదాహరణ: ఫాక్టోరియల్ ఫంక్షన్ను మెమోయిజ్ చేయడం
function factorial(n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
const memoizedFactorial = memoize(factorial);
console.time('మొదటి కాల్');
console.log(memoizedFactorial(5)); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది
console.timeEnd('మొదటి కాల్');
console.time('రెండవ కాల్');
console.log(memoizedFactorial(5)); // కాష్ నుండి పొందుతుంది
console.timeEnd('రెండవ కాల్');
వివరణ:
- `memoize` ఫంక్షన్ `func`ను ఇన్పుట్గా తీసుకుంటుంది.
- ఇది దాని పరిధిలో (క్లోజర్ను ఉపయోగించి) `cache` ఆబ్జెక్ట్ను సృష్టిస్తుంది.
- ఇది అసలు ఫంక్షన్ను చుట్టే కొత్త ఫంక్షన్ను తిరిగి ఇస్తుంది.
- ఈ రేపర్ ఫంక్షన్ `JSON.stringify(args)`ను ఉపయోగించి ఫంక్షన్ ఆర్గ్యుమెంట్ల ఆధారంగా ప్రత్యేక కీని సృష్టిస్తుంది.
- `key` `cache`లో ఉందో లేదో తనిఖీ చేస్తుంది. ఉంటే, అది కాష్ చేసిన విలువను తిరిగి ఇస్తుంది.
- `key` లేకపోతే, అది అసలు ఫంక్షన్ను కాల్ చేస్తుంది, ఫలితాన్ని `cache`లో నిల్వ చేస్తుంది మరియు ఫలితాన్ని తిరిగి ఇస్తుంది.
పరిమితులు:
- సంక్లిష్ట ఆబ్జెక్ట్ల కోసం `JSON.stringify` నెమ్మదిగా ఉండవచ్చు.
- వేర్వేరు క్రమంలో ఆర్గ్యుమెంట్లను అంగీకరించే లేదా ఒకే కీలను కలిగి ఉన్న కానీ వేర్వేరు క్రమంలో ఉన్న ఆబ్జెక్ట్లతో కీ సృష్టి సమస్యాత్మకంగా ఉంటుంది.
- `JSON.stringify(NaN)` `null`ను తిరిగి ఇవ్వడం వలన `NaN`ను సరిగ్గా నిర్వహించదు.
2. అనుకూల కీ జనరేటర్తో మెమోయిజేషన్
`JSON.stringify` యొక్క పరిమితులను పరిష్కరించడానికి, మీరు ఫంక్షన్ ఆర్గ్యుమెంట్ల ఆధారంగా ప్రత్యేక కీని ఉత్పత్తి చేసే అనుకూల కీ జనరేటర్ ఫంక్షన్ను సృష్టించవచ్చు. ఇది కాష్ ఎలా సూచించబడుతుందో దానిపై మరింత నియంత్రణను అందిస్తుంది మరియు కొన్ని సందర్భాల్లో పనితీరును మెరుగుపరుస్తుంది.
function memoizeWithKey(func, keyGenerator) {
const cache = {};
return function(...args) {
const key = keyGenerator(...args);
if (cache[key]) {
return cache[key];
} else {
const result = func.apply(this, args);
cache[key] = result;
return result;
}
};
}
// ఉదాహరణ: రెండు సంఖ్యలను కలిపే ఫంక్షన్ను మెమోయిజ్ చేయడం
function add(a, b) {
console.log('లెక్కిస్తోంది...');
return a + b;
}
// add ఫంక్షన్ కోసం అనుకూల కీ జనరేటర్
function addKeyGenerator(a, b) {
return `${a}-${b}`;
}
const memoizedAdd = memoizeWithKey(add, addKeyGenerator);
console.log(memoizedAdd(2, 3)); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది
console.log(memoizedAdd(2, 3)); // కాష్ నుండి పొందుతుంది
console.log(memoizedAdd(3, 2)); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది (వేర్వేరు కీ)
వివరణ:
- ఈ నమూనా ప్రాథమిక మెమోయిజేషన్ను పోలి ఉంటుంది, కానీ ఇది అదనపు ఆర్గ్యుమెంట్ను అంగీకరిస్తుంది: `keyGenerator`.
- `keyGenerator` అనేది అసలు ఫంక్షన్తో సమానమైన ఆర్గ్యుమెంట్లను తీసుకునే మరియు ప్రత్యేక కీని తిరిగి ఇచ్చే ఫంక్షన్.
- ఇది మరింత సరళమైన మరియు సమర్థవంతమైన కీ సృష్టిని అనుమతిస్తుంది, ముఖ్యంగా సంక్లిష్ట డేటా నిర్మాణాలతో పని చేసే ఫంక్షన్ల కోసం.
3. మ్యాప్తో మెమోయిజేషన్
జావాస్క్రిప్ట్లోని `Map` ఆబ్జెక్ట్ కాష్ చేసిన ఫలితాలను నిల్వ చేయడానికి మరింత బలమైన మరియు బహుముఖ మార్గాన్ని అందిస్తుంది. సాధారణ జావాస్క్రిప్ట్ ఆబ్జెక్ట్ల వలె కాకుండా, `Map` ఆబ్జెక్ట్లు మరియు ఫంక్షన్లతో సహా ఏదైనా డేటా రకాన్ని కీలుగా ఉపయోగించడానికి మిమ్మల్ని అనుమతిస్తుంది. ఇది ఆర్గ్యుమెంట్లను స్ట్రింగ్గా మార్చవలసిన అవసరాన్ని తొలగిస్తుంది మరియు కీ సృష్టిని సులభతరం చేస్తుంది.
function memoizeWithMap(func) {
const cache = new Map();
return function(...args) {
const key = args.join('|'); // సాధారణ కీని సృష్టించండి (మరింత అధునాతనంగా ఉండవచ్చు)
if (cache.has(key)) {
return cache.get(key);
} else {
const result = func.apply(this, args);
cache.set(key, result);
return result;
}
};
}
// ఉదాహరణ: స్ట్రింగ్లను కలపడానికి ఫంక్షన్ను మెమోయిజ్ చేయడం
function concatenate(str1, str2) {
console.log('కలుపుతోంది...');
return str1 + str2;
}
const memoizedConcatenate = memoizeWithMap(concatenate);
console.log(memoizedConcatenate('hello', 'world')); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది
console.log(memoizedConcatenate('hello', 'world')); // కాష్ నుండి పొందుతుంది
వివరణ:
- ఈ నమూనా కాష్ను నిల్వ చేయడానికి `Map` ఆబ్జెక్ట్ను ఉపయోగిస్తుంది.
- `Map` ఆబ్జెక్ట్లు మరియు ఫంక్షన్లతో సహా ఏదైనా డేటా రకాన్ని కీలుగా ఉపయోగించడానికి మిమ్మల్ని అనుమతిస్తుంది, ఇది సాధారణ జావాస్క్రిప్ట్ ఆబ్జెక్ట్లతో పోలిస్తే ఎక్కువ సౌలభ్యాన్ని అందిస్తుంది.
- కాష్ చేసిన విలువలను తనిఖీ చేయడానికి మరియు తిరిగి పొందడానికి `Map` ఆబ్జెక్ట్ యొక్క `has` మరియు `get` పద్ధతులు ఉపయోగించబడతాయి.
4. పునరావృత మెమోయిజేషన్
పునరావృత ఫంక్షన్లను ఆప్టిమైజ్ చేయడానికి మెమోయిజేషన్ ప్రత్యేకంగా ప్రభావవంతంగా ఉంటుంది. మధ్యంతర గణనల ఫలితాలను కాష్ చేయడం ద్వారా, మీరు పునరావృత గణనలను నివారించవచ్చు మరియు అమలు సమయాన్ని గణనీయంగా తగ్గించవచ్చు.
function memoizeRecursive(func) {
const cache = {};
function memoized(...args) {
const key = String(args);
if (cache[key]) {
return cache[key];
} else {
cache[key] = func(memoized, ...args);
return cache[key];
}
}
return memoized;
}
// ఉదాహరణ: ఫైబొనాక్సీ సీక్వెన్స్ ఫంక్షన్ను మెమోయిజ్ చేయడం
function fibonacci(memoized, n) {
if (n <= 1) {
return n;
}
return memoized(n - 1) + memoized(n - 2);
}
const memoizedFibonacci = memoizeRecursive(fibonacci);
console.time('మొదటి కాల్');
console.log(memoizedFibonacci(10)); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది
console.timeEnd('మొదటి కాల్');
console.time('రెండవ కాల్');
console.log(memoizedFibonacci(10)); // కాష్ నుండి పొందుతుంది
console.timeEnd('రెండవ కాల్');
వివరణ:
- `memoizeRecursive` ఫంక్షన్ `func`ను ఇన్పుట్గా తీసుకుంటుంది.
- ఇది దాని పరిధిలో `cache` ఆబ్జెక్ట్ను సృష్టిస్తుంది.
- ఇది అసలు ఫంక్షన్ను చుట్టే కొత్త ఫంక్షన్ `memoized`ను తిరిగి ఇస్తుంది.
- ఇచ్చిన ఆర్గ్యుమెంట్ల కోసం ఫలితం ఇప్పటికే కాష్లో ఉందో లేదో `memoized` ఫంక్షన్ తనిఖీ చేస్తుంది. ఉంటే, అది కాష్ చేసిన విలువను తిరిగి ఇస్తుంది.
- ఫలితం కాష్లో లేకపోతే, అది `memoized` ఫంక్షన్ను మొదటి ఆర్గ్యుమెంట్గా అసలు ఫంక్షన్ను కాల్ చేస్తుంది. ఇది అసలు ఫంక్షన్ దాని యొక్క మెమోయిజ్డ్ వెర్షన్ను పునరావృతంగా కాల్ చేయడానికి అనుమతిస్తుంది.
- ఫలితం ఆపై కాష్లో నిల్వ చేయబడుతుంది మరియు తిరిగి ఇవ్వబడుతుంది.
5. క్లాస్-బేస్డ్ మెమోయిజేషన్
ఆబ్జెక్ట్-ఓరియెంటెడ్ ప్రోగ్రామింగ్ కోసం, పద్ధతుల ఫలితాలను కాష్ చేయడానికి మెమోయిజేషన్ను క్లాస్లో అమలు చేయవచ్చు. ఒకే ఆర్గ్యుమెంట్లతో తరచుగా పిలువబడే గణనపరంగా ఖరీదైన పద్ధతుల కోసం ఇది ఉపయోగకరంగా ఉంటుంది.
class MemoizedClass {
constructor() {
this.cache = {};
}
memoizeMethod(func) {
return (...args) => {
const key = JSON.stringify(args);
if (this.cache[key]) {
return this.cache[key];
} else {
const result = func.apply(this, args);
this.cache[key] = result;
return result;
}
};
}
// ఉదాహరణ: సంఖ్య యొక్క శక్తిని లెక్కించే పద్ధతిని మెమోయిజ్ చేయడం
power(base, exponent) {
console.log('శక్తిని లెక్కిస్తోంది...');
return Math.pow(base, exponent);
}
}
const memoizedInstance = new MemoizedClass();
const memoizedPower = memoizedInstance.memoizeMethod(memoizedInstance.power);
console.log(memoizedPower(2, 3)); // లెక్కిస్తుంది మరియు కాష్ చేస్తుంది
console.log(memoizedPower(2, 3)); // కాష్ నుండి పొందుతుంది
వివరణ:
- `MemoizedClass` దాని కన్స్ట్రక్టర్లో `cache` ప్రాపర్టీని నిర్వచిస్తుంది.
- `memoizeMethod` ఫంక్షన్ను ఇన్పుట్గా తీసుకుంటుంది మరియు ఆ ఫంక్షన్ యొక్క మెమోయిజ్డ్ వెర్షన్ను తిరిగి ఇస్తుంది, ఫలితాలను క్లాస్ యొక్క `cache`లో నిల్వ చేస్తుంది.
- ఇది క్లాస్ యొక్క నిర్దిష్ట పద్ధతులను ఎంచుకుని మెమోయిజ్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది.
కాషింగ్ వ్యూహాలు
ప్రాథమిక మెమోయిజేషన్ నమూనాలకు మించి, కాష్ ప్రవర్తనను ఆప్టిమైజ్ చేయడానికి మరియు దాని పరిమాణాన్ని నిర్వహించడానికి విభిన్న కాషింగ్ వ్యూహాలను ఉపయోగించవచ్చు. కాష్ సమర్థవంతంగా ఉందని మరియు అధిక మెమరీని వినియోగించదని ఈ వ్యూహాలు నిర్ధారించడంలో సహాయపడతాయి.
1. లీస్ట్ రీసెంట్లీ యూజ్డ్ (LRU) కాష్
కాష్ దాని గరిష్ట పరిమాణానికి చేరుకున్నప్పుడు LRU కాష్ కనీసం ఇటీవల ఉపయోగించిన అంశాలను తొలగిస్తుంది. ఈ వ్యూహం చాలా తరచుగా యాక్సెస్ చేయబడిన డేటా కాష్లో ఉంటుందని నిర్ధారిస్తుంది, అయితే తక్కువ తరచుగా ఉపయోగించే డేటా విస్మరించబడుతుంది.
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (this.cache.has(key)) {
const value = this.cache.get(key);
this.cache.delete(key); // ఇటీవల ఉపయోగించినట్లు గుర్తించడానికి తిరిగి చొప్పించండి
this.cache.set(key, value);
return value;
} else {
return undefined;
}
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
}
this.cache.set(key, value);
if (this.cache.size > this.capacity) {
// కనీసం ఇటీవల ఉపయోగించిన అంశాన్ని తీసివేయండి
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
}
}
// ఉదాహరణ వినియోగం:
const lruCache = new LRUCache(3); // 3 యొక్క సామర్థ్యం
lruCache.put('a', 1);
lruCache.put('b', 2);
lruCache.put('c', 3);
console.log(lruCache.get('a')); // 1 ('a' చివరికి కదులుతుంది)
lruCache.put('d', 4); // 'b' తొలగించబడుతుంది
console.log(lruCache.get('b')); // నిర్వచించబడలేదు
console.log(lruCache.get('a')); // 1
console.log(lruCache.get('c')); // 3
console.log(lruCache.get('d')); // 4
వివరణ:
- కాష్ను నిల్వ చేయడానికి `Map`ను ఉపయోగిస్తుంది, ఇది చొప్పించే క్రమాన్ని నిర్వహిస్తుంది.
- `get(key)` విలువను తిరిగి పొందుతుంది మరియు ఇటీవల ఉపయోగించినట్లు గుర్తించడానికి కీ-విలువ జతను తిరిగి చొప్పిస్తుంది.
- `put(key, value)` కీ-విలువ జతను చొప్పిస్తుంది. కాష్ నిండి ఉంటే, కనీసం ఇటీవల ఉపయోగించిన అంశం (`Map`లోని మొదటి అంశం) తీసివేయబడుతుంది.
2. లీస్ట్ ఫ్రీక్వెంట్లీ యూజ్డ్ (LFU) కాష్
కాష్ నిండినప్పుడు LFU కాష్ కనీసం తరచుగా ఉపయోగించే అంశాలను తొలగిస్తుంది. ఈ వ్యూహం తరచుగా యాక్సెస్ చేయబడే డేటాకు ప్రాధాన్యత ఇస్తుంది, అది కాష్లో ఉంటుందని నిర్ధారిస్తుంది.
class LFUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
this.frequencies = new Map();
this.minFrequency = 0;
}
get(key) {
if (!this.cache.has(key)) {
return undefined;
}
const frequency = this.frequencies.get(key);
this.frequencies.set(key, frequency + 1);
return this.cache.get(key);
}
put(key, value) {
if (this.capacity <= 0) {
return;
}
if (this.cache.has(key)) {
this.cache.set(key, value);
this.get(key);
return;
}
if (this.cache.size >= this.capacity) {
this.evict();
}
this.cache.set(key, value);
this.frequencies.set(key, 1);
this.minFrequency = 1;
}
evict() {
let minFreq = Infinity;
for (const frequency of this.frequencies.values()) {
minFreq = Math.min(minFreq, frequency);
}
const keysToRemove = [];
this.frequencies.forEach((freq, key) => {
if (freq === minFreq) {
keysToRemove.push(key);
}
});
const keyToRemove = keysToRemove[0];
this.cache.delete(keyToRemove);
this.frequencies.delete(keyToRemove);
}
}
// ఉదాహరణ వినియోగం:
const lfuCache = new LFUCache(2);
lfuCache.put('a', 1);
lfuCache.put('b', 2);
console.log(lfuCache.get('a')); // 1, frequency(a) = 2
lfuCache.put('c', 3); // 'b'ని తొలగిస్తుంది ఎందుకంటే frequency(b) = 1
console.log(lfuCache.get('b')); // నిర్వచించబడలేదు
console.log(lfuCache.get('a')); // 1, frequency(a) = 3
console.log(lfuCache.get('c')); // 3, frequency(c) = 2
వివరణ:
- రెండు `Map` ఆబ్జెక్ట్లను ఉపయోగిస్తుంది: కీ-విలువ జతల నిల్వ కోసం `cache` మరియు ప్రతి కీ యొక్క యాక్సెస్ ఫ్రీక్వెన్సీని నిల్వ చేయడానికి `frequencies`.
- `get(key)` విలువను తిరిగి పొందుతుంది మరియు ఫ్రీక్వెన్సీ గణనను పెంచుతుంది.
- `put(key, value)` కీ-విలువ జతను చొప్పిస్తుంది. కాష్ నిండి ఉంటే, అది కనీసం తరచుగా ఉపయోగించిన అంశాన్ని తొలగిస్తుంది.
- `evict()` కనిష్ట ఫ్రీక్వెన్సీ గణనను కనుగొంటుంది మరియు `cache` మరియు `frequencies` రెండింటి నుండి సంబంధిత కీ-విలువ జతను తీసివేస్తుంది.
3. సమయం-ఆధారిత గడువు
ఈ వ్యూహం ఒక నిర్దిష్ట కాలం తర్వాత కాష్ చేసిన అంశాలను చెల్లదని చేస్తుంది. కాలక్రమేణా పాతబడే లేదా అవుట్డేటెడ్ అయ్యే డేటా కోసం ఇది ఉపయోగపడుతుంది. ఉదాహరణకు, కొన్ని నిమిషాల పాటు మాత్రమే చెల్లుబాటు అయ్యే API ప్రతిస్పందనలను కాష్ చేయడం.
function memoizeWithExpiration(func, ttl) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
const cached = cache.get(key);
if (cached && cached.expiry > Date.now()) {
return cached.value;
} else {
const result = func.apply(this, args);
cache.set(key, { value: result, expiry: Date.now() + ttl });
return result;
}
};
}
// ఉదాహరణ: 5-సెకన్ల గడువు సమయంతో ఫంక్షన్ను మెమోయిజ్ చేయడం
function getDataFromAPI(endpoint) {
console.log(`డేటాను ${endpoint} నుండి పొందుతోంది...`);
// ఆలస్యంతో API కాల్ను అనుకరించండి
return new Promise(resolve => {
setTimeout(() => {
resolve(`డేటా ${endpoint} నుండి`);
}, 1000);
});
}
const memoizedGetData = memoizeWithExpiration(getDataFromAPI, 5000); // TTL: 5 సెకన్లు
async function testExpiration() {
console.log(await memoizedGetData('/users')); // పొందుతుంది మరియు కాష్ చేస్తుంది
console.log(await memoizedGetData('/users')); // కాష్ నుండి పొందుతుంది
setTimeout(async () => {
console.log(await memoizedGetData('/users')); // 5 సెకన్ల తర్వాత మళ్లీ పొందుతుంది
}, 6000);
}
testExpiration();
వివరణ:
- `memoizeWithExpiration` ఫంక్షన్ `func` ఫంక్షన్ను మరియు మిల్లీసెకన్లలో టైమ్-టు-లీవ్ (TTL) విలువను ఇన్పుట్గా తీసుకుంటుంది.
- ఇది గడువు ముగిసే టైమ్స్టాంప్తో పాటు కాష్ చేసిన విలువను నిల్వ చేస్తుంది.
- కాష్ చేసిన విలువను తిరిగి ఇచ్చే ముందు, అది గడువు ముగిసే టైమ్స్టాంప్ ఇంకా భవిష్యత్తులో ఉందో లేదో తనిఖీ చేస్తుంది. కాకపోతే, అది కాష్ను చెల్లదని చేస్తుంది మరియు డేటాను మళ్లీ పొందుతుంది.
పనితీరు లాభాలు మరియు పరిగణనలు
మెమోయిజేషన్ గణనీయంగా పనితీరును మెరుగుపరుస్తుంది, ప్రత్యేకించి ఒకే ఇన్పుట్లతో పదే పదే పిలువబడే గణనపరంగా ఖరీదైన ఫంక్షన్ల కోసం. కింది పరిస్థితులలో పనితీరు లాభాలు చాలా స్పష్టంగా కనిపిస్తాయి:
- పునరావృత ఫంక్షన్లు: మెమోయిజేషన్ పునరావృత కాల్ల సంఖ్యను నాటకీయంగా తగ్గిస్తుంది, దీని వలన పనితీరులో గుణకార మెరుగుదలలు ఉంటాయి.
- అతివ్యాప్తి చెందుతున్న ఉపసమస్యలతో ఫంక్షన్లు: ఉపసమస్యల ఫలితాలను నిల్వ చేయడం మరియు అవసరమైనప్పుడు వాటిని తిరిగి ఉపయోగించడం ద్వారా మెమోయిజేషన్ పునరావృత గణనలను నివారించగలదు.
- తరచుగా ఒకే విధమైన ఇన్పుట్లతో ఫంక్షన్లు: ప్రతి ప్రత్యేక ఇన్పుట్ సెట్ కోసం ఫంక్షన్ ఒకసారి మాత్రమే అమలు చేయబడుతుందని మెమోయిజేషన్ నిర్ధారిస్తుంది.
అయితే, మెమోయిజేషన్ను ఉపయోగిస్తున్నప్పుడు కింది ట్రేడ్-ఆఫ్లను పరిగణనలోకి తీసుకోవడం ముఖ్యం:
- మెమరీ వినియోగం: మెమోయిజేషన్ ఫంక్షన్ కాల్ల ఫలితాలను నిల్వ చేయడం వలన మెమరీ వినియోగాన్ని పెంచుతుంది. పెద్ద సంఖ్యలో సాధ్యమయ్యే ఇన్పుట్లతో ఫంక్షన్ల కోసం లేదా పరిమిత మెమరీ వనరులతో అప్లికేషన్ల కోసం ఇది ఆందోళన కలిగిస్తుంది.
- కాష్ చెల్లనిది: అంతర్లీన డేటా మారితే, కాష్ చేసిన ఫలితాలు పాతవి కావచ్చు. కాష్ డేటాతో స్థిరంగా ఉంటుందని నిర్ధారించడానికి కాష్ చెల్లని వ్యూహాన్ని అమలు చేయడం చాలా కీలకం.
- సంక్లిష్టత: మెమోయిజేషన్ను అమలు చేయడం కోడ్కు సంక్లిష్టతను జోడించగలదు, ప్రత్యేకించి సంక్లిష్ట కాషింగ్ వ్యూహాల కోసం. మెమోయిజేషన్ను ఉపయోగించే ముందు కోడ్ యొక్క సంక్లిష్టత మరియు నిర్వహణ సామర్థ్యాన్ని జాగ్రత్తగా పరిశీలించడం ముఖ్యం.
ఆచరణాత్మక ఉదాహరణలు మరియు వినియోగ సందర్భాలు
పనితీరును ఆప్టిమైజ్ చేయడానికి మెమోయిజేషన్ను అనేక సందర్భాల్లో అన్వయించవచ్చు. ఇక్కడ కొన్ని ఆచరణాత్మక ఉదాహరణలు ఉన్నాయి:
- ఫ్రంట్-ఎండ్ వెబ్ అభివృద్ధి: జావాస్క్రిప్ట్లో ఖరీదైన గణనలను మెమోయిజ్ చేయడం వెబ్ అప్లికేషన్ల ప్రతిస్పందనను మెరుగుపరుస్తుంది. ఉదాహరణకు, మీరు సంక్లిష్ట DOM తారుమారులను నిర్వహించే లేదా లేఅవుట్ లక్షణాలను లెక్కించే ఫంక్షన్లను మెమోయిజ్ చేయవచ్చు.
- సర్వర్-సైడ్ అప్లికేషన్లు: డేటాబేస్ ప్రశ్నలు లేదా API కాల్ల ఫలితాలను కాష్ చేయడానికి మెమోయిజేషన్ను ఉపయోగించవచ్చు, సర్వర్పై లోడ్ను తగ్గించడం మరియు ప్రతిస్పందన సమయాలను మెరుగుపరచడం.
- డేటా విశ్లేషణ: మధ్యంతర గణనల ఫలితాలను కాష్ చేయడం ద్వారా మెమోయిజేషన్ డేటా విశ్లేషణ పనులను వేగవంతం చేస్తుంది. ఉదాహరణకు, మీరు గణాంక విశ్లేషణ లేదా మెషిన్ లెర్నింగ్ అల్గారిథమ్లను నిర్వహించే ఫంక్షన్లను మెమోయిజ్ చేయవచ్చు.
- గేమ్ అభివృద్ధి: ఢీకొనడం గుర్తించడం లేదా పాత్ఫైండింగ్ వంటి తరచుగా ఉపయోగించే గణనల ఫలితాలను కాష్ చేయడం ద్వారా గేమ్ పనితీరును ఆప్టిమైజ్ చేయడానికి మెమోయిజేషన్ను ఉపయోగించవచ్చు.
ముగింపు
మెమోయిజేషన్ అనేది జావాస్క్రిప్ట్ అప్లికేషన్ల పనితీరును గణనీయంగా మెరుగుపరచగల శక్తివంతమైన ఆప్టిమైజేషన్ టెక్నిక్. ఖరీదైన ఫంక్షన్ కాల్ల ఫలితాలను కాష్ చేయడం ద్వారా, మీరు పునరావృత గణనలను నివారించవచ్చు మరియు అమలు సమయాన్ని తగ్గించవచ్చు. అయితే, పనితీరు లాభాలు మరియు మెమరీ వినియోగం, కాష్ చెల్లనిది మరియు కోడ్ సంక్లిష్టత మధ్య ట్రేడ్-ఆఫ్లను జాగ్రత్తగా పరిశీలించడం ముఖ్యం. వివిధ మెమోయిజేషన్ నమూనాలు మరియు కాషింగ్ వ్యూహాలను అర్థం చేసుకోవడం ద్వారా, మీరు మీ జావాస్క్రిప్ట్ కోడ్ను ఆప్టిమైజ్ చేయడానికి మరియు అధిక-పనితీరు అప్లికేషన్లను రూపొందించడానికి సమర్థవంతంగా మెమోయిజేషన్ను అన్వయించవచ్చు.