-1

Problem

We've got highload app and use inmemory cache, we want to optimize it everywhere we could.

Question

How much weight of each variable type? I mean:

  • Boolean as value
  • Emty string is value
  • null I want to use something like that
cache.set(key, '') // emty string as value
// or
cache.set(key, true) // we don't need any value, we just need check keys 
  • 1
    "Weight" as in "memory footprint"? Try creating an array of a hundred million of each and find out. Each JavaScript runtime is free to behave entirely differently. – tadman Jul 25 '22 at 11:55
  • If you're left guessing as to what's best here, that's a sign you really need to up your instrumentation game. Chrome can be attached to a Node process to monitor memory usage, do debugging, and more. Worth checking out. – tadman Jul 25 '22 at 11:56
  • 2
    Does this answer your question: https://stackoverflow.com/questions/4905861/memory-usage-of-different-data-types-in-javascript – Bjop Jul 25 '22 at 11:58
  • "Weight" - is how much bytes reserved in RAM for each variable type – Филипп Павлик Jul 25 '22 at 12:49
  • @tadman Thanks I will try it and come back with results – Филипп Павлик Jul 25 '22 at 12:51
  • 1
    What is `cache`, a `Map` instance? But realistically, all those values (`null`, `''`, `true`) will take the same amount of memory – Bergi Jul 25 '22 at 13:12

1 Answers1

1

(V8 developer here.)

It doesn't matter which of these options you pick. null, true, false, and "" all exist anyway. Storing a reference to either of them always takes the same amount of memory (namely 4 bytes; or 8 on Node without pointer compression).

In fact, this principle goes even further. I assume you'll have many of these cache entries. So you could even define an object of your own (if that'd be useful in any way), and as long as you only have one of these objects and many references to it, the size of the object practically doesn't matter.

Example:

let big = new Array(1000);  // About 4000 bytes.
let small = {answer: 42};   // About 16 bytes. (Simplifying a bit.)

for (let i = 0; i < 1000; i++) cache1.set(i, big);
for (let i = 0; i < 1000; i++) cache2.set(i, small);
for (let i = 0; i < 1000; i++) cache3.set(i, "");
for (let i = 0; i < 1000; i++) cache4.set(i, null);
for (let i = 0; i < 1000; i++) cache5.set(i, true);

After doing this, all caches cache1 through cache5 will all have the exact same size: they're each storing 1000 references. It doesn't matter what these references are referring to. (I can't say how many bytes it'll be because I don't know what you're using as cache implementation. If it's a Map, then memory consumption is about 12-20 bytes per entry on average, fluctuating because the backing store is grown in rather large infrequent steps.)

jmrk
  • 34,271
  • 7
  • 59
  • 74
  • No idea why this was downvoted. Helpful as always! – Bergi Jul 25 '22 at 20:03
  • "*Storing a reference to either of them*" - are boolean/number/null/undefined primitives really *referenced* from a `Map`, instead of being stored inline? – Bergi Jul 25 '22 at 20:04
  • @Bergi: Only "Smis" (31-bit integers) can be stored inline, given V8's pointer tagging scheme; everything else is referenced. That said, I suppose a pointer to a well-known eternally-living global value is kind of blurring the lines a bit between what's a reference and what's inline storage... – jmrk Jul 25 '22 at 23:20