Challenge - Performance optimization
Build a search-suggestion function with memoization, debounce and performance measurement.
Fast search suggestions
In this challenge you will write a fast search-suggestion function. To avoid recomputing the same query you use memoization: results are stored in a Map and returned immediately if the key exists.
To coalesce input you write debounce(fn, ms); the returned function clears the previous timer on every call and sets a new setTimeout. The callback then runs only when typing settles.
To measure time you use performance.now(); it returns a millisecond-resolution timestamp.
Exercise Debounced memoized search suggestion
Write a memoize(fn) function: the returned function takes a key, returns the cached result if the Map has it, otherwise computes and stores it. Then write debounce(fn, ms): the returned function clears the previous timer with clearTimeout on every call and sets a setTimeout. Finally add a call to performance.now() to measure elapsed time.
Show example solution
Start with function memoize(fn) { const cache = new Map(); return function(key) { if (cache.has(key)) return cache.get(key); const r = fn(key); cache.set(key, r); return r; }; }. Then write function debounce(fn, ms) { let t; return function(...args) { clearTimeout(t); t = setTimeout(() => fn.apply(this, args), ms); }; }. Finally add const start = performance.now();.
Example solution:
function memoize(fn) {
const cache = new Map();
return function(key) {
if (cache.has(key)) return cache.get(key);
const result = fn(key);
cache.set(key, result);
return result;
};
}
function debounce(fn, ms) {
let timer;
return function(...args) {
clearTimeout(timer);
const start = performance.now();
timer = setTimeout(() => fn.apply(this, args), ms);
};
}
Test yourself
-
What is the difference between debounce and throttle?
function debounce(fn, ms) { let t; return function(...args) { clearTimeout(t); t = setTimeout(() => fn.apply(this, args), ms); }; }- debounce fires after settling, throttle fires at fixed intervals
- They do the same thing
- throttle cancels the callback immediately
- debounce fires the callback on every call
Show answer
debounce fires after settling, throttle fires at fixed intervals — Correct! debounce batches calls and runs once after settling; throttle runs at fixed intervals.
-
Memoization cache check
function memoize(fn) { const cache = new Map(); return function(key) { if (____) { return cache.get(key); } const result = fn(key); cache.set(key, result); return result; }; }Show answer
function memoize(fn) { const cache = new Map(); return function(key) { if (cache.has(key)) { return cache.get(key); } const result = fn(key); cache.set(key, result); return result; }; } -
Match the performance concepts
- memoization
- Cache results
- debounce
- Fire after settling
- performance.now()
- Measure time
- clearTimeout
- Cancel timer