node-lru-cache icon indicating copy to clipboard operation
node-lru-cache copied to clipboard

Clarify correct size calculation

Open AntonPuko opened this issue 1 year ago • 1 comments

Hello. First of all thanks for the library.

My use case is that, using sizeCalculation, i want to be more or less strictly ensured that the LruCache instance is not consuming more memory then expected from sizeCalculation.

The problem is that i can't just do something like: sizeCalculation: (k,v) => Buffer.byteLength(k, 'utf8') + Buffer.byteLength(v, 'utf-8'). because internally LruCache instance doesnt keep only one Map or Object for the key-values, It also save the data in bunch of arrays for indexing, like those ones from internals:

      'starts',          'ttls',
      'sizes',           'keyMap',
      'keyList',         'valList',
      'next',            'prev',
      'head',            'tail',
      'free',            'isBackgroundFetch',
      'backgroundFetch', 'moveToTail',
      'indexes',         'rindexes',
      'isStale'
    ]

My question is: is there any correct and verified way to write the correct sizeCalculation implementation, to be more or less in sync with real memory consumption?

I tried something like this:

export const calcSize =
  (hasTtl: boolean) =>
  (val: any, key: string): number => {
    let sum = 0;
    const keySize = Buffer.byteLength(key, 'utf8');

    let valSize;
    if (val === undefined) {
      valSize = 0;
    } else {
      valSize =
        typeof val === 'string'
          ? Buffer.byteLength(val, 'utf8')
          : Buffer.byteLength(JSON.stringify(val), 'utf-8');
    }

    // calc KeysMap key + index(int)
    sum += keySize + INT_SIZE_BYTES;
    // calc keyList key size
    sum += keySize;
    // cacl valList val size
    sum += valSize;

    // calc ttl start + ttl
    // next arr
    sum += INT_SIZE_BYTES;
    // prev arr
    sum += INSPECT_MAX_BYTES;

    // size of the size itself
    sum += INT_SIZE_BYTES;

    // ttl start arr
    if (hasTtl) {
      sum += INT_SIZE_BYTES;
    }

    return sum;
  };

but with the calculation it still shows me around 1.5x unsync with real memory

AntonPuko avatar Oct 24 '24 16:10 AntonPuko

This would be an important feature to be able to limit the memory usage for like a % of the total memory of the instance/pod.

ricardovf avatar Dec 17 '24 19:12 ricardovf