Created
February 7, 2024 21:55
-
-
Save mhawksey/37b1399f064de3559bdc8e35b1944a42 to your computer and use it in GitHub Desktop.
Examples of Memoization in Apps Script with Cache Service
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
function main(){ | |
console.log("Run in memory tests") | |
inMemory(); | |
console.log("Run in cache tests") | |
withCache(); | |
} | |
// From https://medium.com/@saravanaeswari22/memorization-in-javascript-f312d66402b2 | |
const memoize = (func) => { | |
const results = {}; | |
return (...args) => { | |
const argsKey = JSON.stringify(args); | |
if (!results[argsKey]) { | |
results[argsKey] = func(...args); | |
} | |
return results[argsKey]; | |
}; | |
}; | |
const clumsysquare = memoize((num) => { | |
let result = 0; | |
for (let i = 1; i <= num; i++) { | |
for (let j = 1; j <= num; j++) { | |
result++; | |
} | |
} | |
return result; | |
}); | |
// From https://justin.poehnelt.com/posts/apps-script-memoization/ | |
/** | |
* A generic hash function that takes a string and computes a hash using the | |
* specified algorithm. | |
* | |
* @param {string} str - The string to hash. | |
* @param {Utilities.DigestAlgorithm} algorithm - The algorithm to use to | |
* compute the hash. Defaults to MD5. | |
* @returns {string} The base64 encoded hash of the string. | |
*/ | |
function hash(str, algorithm = Utilities.DigestAlgorithm.MD5) { | |
const digest = Utilities.computeDigest(algorithm, str); | |
return Utilities.base64Encode(digest); | |
} | |
/** | |
* Memoizes a function by caching its results based on the arguments passed. | |
* | |
* @param {Function} func - The function to be memoized. | |
* @param {number} [ttl=600] - The time to live in seconds for the cached | |
* result. The maximum value is 600. | |
* @param {Cache} [cache=CacheService.getScriptCache()] - The cache to store the | |
* memoized results. | |
* @returns {Function} - The memoized function. | |
* | |
* @example | |
* | |
* const cached = memoize(myFunction); | |
* cached(1, 2, 3); // The result will be cached | |
* cached(1, 2, 3); // The cached result will be returned | |
* cached(4, 5, 6); // A new result will be calculated and cached | |
*/ | |
function memoizeWithCache(func, ttl = 600, cache = CacheService.getScriptCache()) { | |
return (...args) => { | |
// consider a more robust input to the hash function to handler complex | |
// types such as functions, dates, and regex | |
const key = hash(JSON.stringify([func.toString(), ...args])); | |
//const key = JSON.stringify([func.toString(), ...args]); | |
const cached = cache.get(key); | |
if (cached != null) { | |
return JSON.parse(cached); | |
} else { | |
const result = func(...args); | |
cache.put(key, JSON.stringify(result), ttl); | |
return result; | |
} | |
}; | |
} | |
const clumsysquareWithCache = memoizeWithCache((num) => { | |
let result = 0; | |
for (let i = 1; i <= num; i++) { | |
for (let j = 1; j <= num; j++) { | |
result++; | |
} | |
} | |
return result; | |
}, 3600, CacheService.getUserCache()); | |
// Tests to compare different speeds | |
function inMemory() { | |
console.time("First call"); | |
console.log(clumsysquare(9467)); | |
console.timeEnd("First call"); | |
// use the same value two times | |
console.time("Second call"); | |
console.log(clumsysquare(9467)); | |
console.timeEnd("Second call"); | |
console.time("Third call"); | |
console.log(clumsysquare(9467)); | |
console.timeEnd("Third call"); | |
} | |
function withCache() { | |
console.time("First call"); | |
console.log(clumsysquareWithCache(9467)); | |
console.timeEnd("First call"); | |
// use the same value two times | |
console.time("Second call"); | |
console.log(clumsysquareWithCache(9467)); | |
console.timeEnd("Second call"); | |
console.time("Third call"); | |
console.log(clumsysquareWithCache(9467)); | |
console.timeEnd("Third call"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment