관리-도구
편집 파일: packument-cache.js
const { LRUCache } = require('lru-cache') const { getHeapStatistics } = require('node:v8') const { log } = require('proc-log') // This is an in-memory cache that Pacote uses for packuments. // Packuments are usually cached on disk. This allows for rapid re-requests // of the same packument to bypass disk reads. The tradeoff here is memory // usage for disk reads. class PackumentCache extends LRUCache { static #heapLimit = Math.floor(getHeapStatistics().heap_size_limit) #sizeKey #disposed = new Set() #log (...args) { log.silly('packumentCache', ...args) } constructor ({ // How much of this.#heapLimit to take up heapFactor = 0.25, // How much of this.#maxSize we allow any one packument to take up // Anything over this is not cached maxEntryFactor = 0.5, sizeKey = '_contentLength', } = {}) { const maxSize = Math.floor(PackumentCache.#heapLimit * heapFactor) const maxEntrySize = Math.floor(maxSize * maxEntryFactor) super({ maxSize, maxEntrySize, sizeCalculation: (p) => { // Don't cache if we dont know the size // Some versions of pacote set this to `0`, newer versions set it to `null` if (!p[sizeKey]) { return maxEntrySize + 1 } if (p[sizeKey] < 10_000) { return p[sizeKey] * 2 } if (p[sizeKey] < 1_000_000) { return Math.floor(p[sizeKey] * 1.5) } // It is less beneficial to store a small amount of super large things // at the cost of all other packuments. return maxEntrySize + 1 }, dispose: (v, k) => { this.#disposed.add(k) this.#log(k, 'dispose') }, }) this.#sizeKey = sizeKey this.#log(`heap:${PackumentCache.#heapLimit} maxSize:${maxSize} maxEntrySize:${maxEntrySize}`) } set (k, v, ...args) { // we use disposed only for a logging signal if we are setting packuments that // have already been evicted from the cache previously. logging here could help // us tune this in the future. const disposed = this.#disposed.has(k) /* istanbul ignore next - this doesnt happen consistently so hard to test without resorting to unit tests */ if (disposed) { this.#disposed.delete(k) } this.#log(k, 'set', `size:${v[this.#sizeKey]} disposed:${disposed}`) return super.set(k, v, ...args) } has (k, ...args) { const has = super.has(k, ...args) this.#log(k, `cache-${has ? 'hit' : 'miss'}`) return has } } module.exports = PackumentCache