Skip to content

Commit 3107155

Browse files
committed
Apply review comments
1 parent 6ca7232 commit 3107155

File tree

1 file changed

+33
-20
lines changed
  • content/develop/data-types/json

1 file changed

+33
-20
lines changed

content/develop/data-types/json/ram.md

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,40 @@ Every key in Redis takes memory and requires at least the amount of RAM to store
1919
well as some per-key overhead that Redis uses. On top of that, the value in the key also requires
2020
RAM.
2121

22-
Redis JSON stores JSON values as binary data after deserializing them. This representation is often more
23-
expensive, size-wise, than the serialized form. The JSON data type uses at least 8 bytes (on
24-
64-bit architectures) for every value, as can be seen by sampling an empty string with the
25-
[`JSON.DEBUG MEMORY`]({{< relref "commands/json.debug-memory/" >}}) command:
22+
Redis JSON stores JSON values as binary data after deserialization. This representation is often more
23+
expensive, size-wise, than the serialized form. All JSON values occupy at least 8 bytes (on 64-bit architectures) because each is represented as a thin wrapper around a pointer. The type information is stored in the lower bits of the pointer, which are guaranteed to be zero due to alignment restrictions. This allows those bits to be repurposed to store some auxiliary data.
24+
25+
For some types of JSON values, 8 bytes is all that’s needed. Nulls and booleans don’t require any additional storage. Small integers are stored in static memory because they’re frequently used, so they also use only the initial 8 bytes. Similarly, empty strings, arrays, and objects don’t require any bookkeeping. Instead, they point to static instances of a _null_ string, array, or object. Here are some examples that use the [JSON.DEBUG MEMORY]({{< relref "/commands/json.debug-memory >}}) command to report on memory consumption:
2626

2727
```
28+
127.0.0.1:6379> JSON.SET boolean . 'true'
29+
OK
30+
127.0.0.1:6379> JSON.DEBUG MEMORY boolean
31+
(integer) 8
32+
33+
127.0.0.1:6379> JSON.SET null . null
34+
OK
35+
127.0.0.1:6379> JSON.DEBUG MEMORY null
36+
(integer) 8
37+
2838
127.0.0.1:6379> JSON.SET emptystring . '""'
2939
OK
3040
127.0.0.1:6379> JSON.DEBUG MEMORY emptystring
3141
(integer) 8
42+
43+
127.0.0.1:6379> JSON.SET emptyarr . '[]'
44+
OK
45+
127.0.0.1:6379> JSON.DEBUG MEMORY emptyarr
46+
(integer) 8
47+
48+
127.0.0.1:6379> JSON.SET emptyobj . '{}'
49+
OK
50+
127.0.0.1:6379> JSON.DEBUG MEMORY emptyobj
51+
(integer) 8
3252
```
3353

3454
This RAM requirement is the same for all scalar values, but strings require additional space
35-
depending on their actual length. For example, a 3-character string will use 3 additional bytes:
55+
depending on their length. For example, a 3-character string will use 3 additional bytes:
3656

3757
```
3858
127.0.0.1:6379> JSON.SET foo . '"bar"'
@@ -41,20 +61,11 @@ OK
4161
(integer) 11
4262
```
4363

44-
Empty containers take up 8 bytes to set up:
64+
In the following four examples, each array requires 56 bytes. This breaks down as:
65+
- 8 bytes for the initial array value pointer
66+
- 16 bytes of metadata: 8 bytes for the allocated capacity and 8 bytes for the point-in-time size of the array
67+
- 32 bytes for the array. The initial capacity of an array is 4. Therefore, the calculation is `4 * 8` bytes
4568

46-
```
47-
127.0.0.1:6379> JSON.SET arr . '[]'
48-
OK
49-
127.0.0.1:6379> JSON.DEBUG MEMORY arr
50-
(integer) 8
51-
127.0.0.1:6379> JSON.SET obj . '{}'
52-
OK
53-
127.0.0.1:6379> JSON.DEBUG MEMORY obj
54-
(integer) 8
55-
```
56-
57-
In the following four examples, each array requires 56 bytes, because the array is created with a default capacity of 4.
5869
```
5970
127.0.0.1:6379> JSON.SET arr . '[""]'
6071
OK
@@ -83,7 +94,7 @@ OK
8394
(integer) 56
8495
```
8596

86-
An array with five elements will allocate four more bytes than the previous examples:
97+
Once the current capacity is insufficient to fit a new value, the array reallocates to double its capacity. An array with 5 elements will have a capacity of 8, therefore consuming `8 + 16 + 8 * 8 = 88` bytes.
8798

8899
```
89100
127.0.0.1:6379> JSON.SET arr . '["", "", "", "", ""]'
@@ -92,7 +103,9 @@ OK
92103
(integer) 88
93104
```
94105

95-
This table gives the size (in bytes) of a few of the test files from the [module repo](https://github.com/RedisJSON/RedisJSON), stored using
106+
Because reallocation operations can be expensive, Redis grows JSON arrays geometrically rather than linearly. This approach spreads the cost across many insertions.
107+
108+
This table gives the size (in bytes) of a few of the test files from the [module repo](https://github.com/RedisJSON/RedisJSON/tree/master/tests/files), stored using
96109
JSON. The _MessagePack_ column is for reference purposes and reflects the length of the value when stored using [MessagePack](https://msgpack.org/index.html).
97110

98111
| File | File size | Redis JSON | MessagePack |

0 commit comments

Comments
 (0)