skip to content

Why does a store report 2.4 GB of data size for 10 million entries whose payloads total 800 MB?

level: middleimportance: must knowfreq 64%

answer

  1. divide the total by the count first
  2. charged per entry, not per byte
  3. payload arithmetic misses the fixed part
  4. data size is not resident size
  5. the multiple is measured, not known

basics

~20 s

Because the fixed per-entry cost is charged 10 million times. Data size over entry count is 240 bytes, of which 80 is payload and 160 is lookup slot, header, key bytes and allocator rounding. Overhead scales with count, not bytes.

solid answer

~50 s

Divide before you explain: 2.4 GB over 10 million entries is 240 bytes each, so 80 bytes of payload sits under 160 bytes of everything else — the lookup slot, the entry header and its references, the key bytes, a deadline if these entries carry one, and the allocator's rounding on each allocation. None of that scales with how big the values are; all of it is charged once per entry. That is why an estimate built from payload sizes is wrong by a **multiple** rather than by a percentage once entries get small. The 3x seen here is this store, this build and this entry shape — the multiple itself is not portable. Note also which number is being discussed: `data size` is the store's own accounting of what it attributes to entries, not what the operating system reports the process holding, which is a separate gap with a separate cause.

go deeper

for a junior

The move to remember is the division: total divided by entry count gives a cost per entry, and comparing that with the payload per entry shows how much is overhead. You do not need the component list to see that the fixed part was charged ten million times.

for a middle

Explain the components and, crucially, why none of them grows with value size. Then name which of the four numbers called memory you are discussing, because an answer that slides between data size and resident size is not checkable by anyone listening.

for a senior

Push past the explanation to the planning consequence: multiply the measured constant by the projected entry count and read it against the configured ceiling, and say plainly that the multiple you just derived belongs to this store and this entry shape only.

for a principal

The interesting failure is organisational: a plan sized on payload arithmetic passes review because the arithmetic is correct. Decide what makes a capacity number reviewable — a stated measurement procedure, a date, an entry shape — rather than arguing about a multiplier.

## Do the division first The fastest way into this question is arithmetic, not theory: - 2,400 MB reported as data size, over 10,000,000 entries, is **240 bytes per entry**. - The plan assumed 80 bytes per entry, because that is what the key and value bytes total. - The difference, **160 bytes per entry**, is the fixed cost of being an entry at all. Everything that follows is an explanation of that 160 bytes and of why it multiplied by ten million instead of scaling with the 800 MB of data. ## Why the cost scales with count, not with bytes The components that make up the fixed part are all charged once per entry: 1. **A slot in the lookup structure.** The store has to find the entry by key, and the structure that lets it do so is kept deliberately less than full, so each entry's share is its own slot plus some of the spare capacity held beside it. 2. **A header.** Lengths, flags and references to the key and the value. 3. **The key's own bytes.** The store keeps the key to confirm a match rather than guess at one, and payload estimates built from value sizes routinely forget this. 4. **A deadline, when the entry carries a lifetime.** On some stores this is a field that exists anyway; on others it is a record in a separate structure. 5. **Allocator rounding.** Each of the several allocations an entry needs is rounded up to a step the allocator serves, and each rounding is charged separately. Not one of those grows because the value is larger. They are the same for a 20-byte value and for a 2 KB value. That single fact is the whole of this subject: **when entries are small, you are mostly storing the cost of storing things.** ## Say which memory you are talking about Four different numbers get called memory in this conversation, and an answer that does not name which one it means is not answerable: | Number | What it is | Where it came from here | |---|---|---| | Payload bytes | The key and value bytes you decided to store | 800 MB, the plan's arithmetic | | Data size | What the store attributes to its entries | 2,400 MB, the observed figure | | Resident size | What the operating system reports the process holding | Not given, and not the same number | | The machine limit | What the box or container allows | Not given | This question is entirely about the first two. The gap between data size and resident size is real and has its own causes, but it is a different subject — you must not silently fold it into the per-entry constant, because doing so produces a constant that changes whenever the process's history changes. ## Turning it into a planning number The useful output of this exercise is not "overhead exists" but a constant you can multiply: - **Measured cost per entry** = data size delta divided by entries written, on a representative sample. - **Projected data size** = measured cost per entry x projected entry count. - **Compare against** the memory ceiling the store is configured with — not against the machine limit, and not against the payload total that started the conversation. In this scenario, growth to 25 million entries at the measured 240 bytes projects to 6,000 MB. If the store's ceiling is 5,000 MB, the growth does not fit, and no amount of reasoning about the 800 MB of payload would have revealed that. ## What the multiple is and is not The 3x here is a measurement of one store, one build and one entry shape. It is not a property of in-memory stores, and quoting it back in a different context is exactly the error this question exists to catch. Stores differ in: - how large the header is and what it contains; - how coarse the allocator's rounding step is; - whether a deadline costs anything extra; - how much spare capacity the lookup structure carries per entry; - whether small values are placed inside the descriptor or reached through a reference. A candidate who answers "about three times, that's the known overhead" has learned the wrong lesson from the right example. The right lesson is: **payload arithmetic is not a capacity estimate, and the correction factor is something you measure rather than something you know.** ## The common wrong turns - **Blaming fragmentation.** Data size is the store's own accounting; unreturned memory shows up in the gap between that figure and resident size, which is not the figure given here. - **Blaming the values being larger than believed.** They might be, which is why the first move after dividing is to confirm the real payload distribution rather than the assumed average. - **Reaching for a hit ratio.** Whether these entries are worth keeping is a different question entirely; this one is about what holding them costs. - **Assuming the 160 bytes is constant across entry shapes.** Measure each distinct shape in the workload and weight by the mix, rather than trusting one blended average. ## The whole method: divide the observed figure by the entry count to get a measured cost per entry, then multiply forward. The 240 bytes is a measurement of this store and this entry shape, never a figure to carry elsewhere ``` entries 10,000,000 key bytes (average) 24 value bytes (average) 56 payload per entry 80 bytes payload total 800 MB <- what the plan used observed data size 2,400 MB <- what the store attributes to its entries measured cost per entry 240 bytes (2,400 MB / 10,000,000) fixed cost per entry 160 bytes (240 - 80) projected entry count after growth 25,000,000 projected data size 6,000 MB (25,000,000 x 240 bytes) configured memory ceiling 5,000 MB <- reached before the growth lands ```

  • At what payload size does the fixed per-entry cost stop dominating?
    There is no universal crossover, because the fixed part differs by store and by entry shape. The usable version is a comparison: measure the fixed part, then compare it with your payload. When payload is several times the fixed part, payload arithmetic is roughly right; when they are comparable, it is wrong by a multiple. Anyone quoting a specific byte count as the crossover is quoting one store's measurement.
  • If the same 800 MB of payload were spread over 1 million entries instead of 10 million, what would the projected data size become?
    The fixed term falls tenfold: 1,000,000 entries at 160 bytes is 160 MB, so the projection is roughly 960 MB rather than 2,400 MB. Treat that as arithmetic only. The measured constant may itself differ at a different entry shape and would need re-measuring, and whether the workload should be structured with fewer, larger entries is a keyspace design question, not something this calculation decides.
  • The reported data size is 2.4 GB but the process is holding 3.6 GB. Does that change the per-entry constant?
    No. The constant is derived from what the store attributes to its entries, and that is the 2.4 GB figure. The extra 1.2 GB is the gap between the store's accounting and what the operating system reports the process holding, which has its own causes and its own diagnosis. Folding it into the per-entry constant produces a number that moves with the process's history rather than with your entries.

saying these in an interview costs you the question

  • Blames the gap on the values being larger than the estimate assumed.
  • Treats a 3x overhead multiple as a general property of in-memory stores.
  • Attributes the whole gap to memory freed but not returned.
  • Estimates capacity from value sizes and ignores key bytes entirely.
  • Assumes one blended average per-entry cost covers every entry shape in the workload.