ReJSON RAM Usage
Every key in Redis takes memory and requires at least the amount of RAM to store the key name, as well as some per-key overhead that Redis uses. On top of that, the value in the key also requires RAM.
ReJSON stores JSON values as binary data after deserializing them. This representation is often more
expensive, size-wize, than the serialized form. The ReJSON data type uses at least 24 bytes (on
64-bit architectures) for every value, as can be seen by sampling an empty string with the
JSON.DEBUG MEMORY
command:
127.0.0.1:6379> JSON.SET emptystring . '""' OK 127.0.0.1:6379> JSON.DEBUG MEMORY emptystring (integer) 24
This RAM requirement is the same for all scalar values, but strings require additional space depending on their actual length. For example, a 3-character string will use 3 additional bytes:
127.0.0.1:6379> JSON.SET foo . '"bar"' OK 127.0.0.1:6379> JSON.DEBUG MEMORY foo (integer) 27
Empty containers take up 32 bytes to set up:
127.0.0.1:6379> JSON.SET arr . '[]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 32 127.0.0.1:6379> JSON.SET obj . '{}' OK 127.0.0.1:6379> JSON.DEBUG MEMORY obj (integer) 32
The actual size of a container is the sum of sizes of all items in it on top of its own overhead. To avoid expensive memory reallocations, containers' capacity is scaled by multiples of 2 until a treshold size is reached, from which they grow by fixed chunks.
A container with a single scalar is made up of 32 and 24 bytes, respectively:
127.0.0.1:6379> JSON.SET arr . '[""]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 56
A container with two scalars requires 40 bytes for the container (each pointer to an entry in the container is 8 bytes), and 2 * 24 bytes for the values themselves:
127.0.0.1:6379> JSON.SET arr . '["", ""]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 88
A 3-item (each 24 bytes) container will be allocated with capacity for 4 items, i.e. 56 bytes:
127.0.0.1:6379> JSON.SET arr . '["", "", ""]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 128
The next item will not require an allocation in the container, so usage will increase only by that scalar's requirement, but another value will scale the container again:
127.0.0.1:6379> JSON.SET arr . '["", "", "", ""]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 152 127.0.0.1:6379> JSON.SET arr . '["", "", "", "", ""]' OK 127.0.0.1:6379> JSON.DEBUG MEMORY arr (integer) 208
This table gives the size (in bytes) of a few of the test files on disk and when stored using ReJSON. The MessagePack column is for reference purposes and reflects the length of the value when stored using MessagePack.
File | Filesize | ReJSON | MessagePack |
---|---|---|---|
/test/files/pass-100.json | 380 | 1079 | 140 |
/test/files/pass-jsonsl-1.json | 1441 | 3666 | 753 |
/test/files/pass-json-parser-0000.json | 3468 | 7209 | 2393 |
/test/files/pass-jsonsl-yahoo2.json | 18446 | 37469 | 16869 |
/test/files/pass-jsonsl-yelp.json | 39491 | 75341 | 35469 |
Note: In the current version, deleting values from containers does not free the container's allocated memory.