Skip to content

Commit 3a28c90

Browse files
authored
DEV: update examples on two JSON pages (#1305)
* DEV: update examples on two JSON pages * Update values based on latest version * Apply review comments * Bug fix
1 parent 1c88344 commit 3a28c90

File tree

2 files changed

+54
-51
lines changed
  • content

2 files changed

+54
-51
lines changed

content/commands/json.debug-memory/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Get the values' memory usage in bytes.
7272

7373
{{< highlight bash >}}
7474
redis> JSON.DEBUG MEMORY item:2
75-
(integer) 253
75+
(integer) 573
7676
{{< / highlight >}}
7777
</details>
7878

@@ -84,4 +84,3 @@ redis> JSON.DEBUG MEMORY item:2
8484

8585
* [RedisJSON]({{< relref "/develop/data-types/json/" >}})
8686
* [Index and search JSON documents]({{< relref "/develop/interact/search-and-query/indexing/" >}})
87-

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

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ categories:
99
- oss
1010
- kubernetes
1111
- clients
12-
description: 'Debugging memory consumption
13-
14-
'
12+
description: Debugging memory consumption
1513
linkTitle: Memory Usage
1614
title: Redis JSON RAM Usage
1715
weight: 6
@@ -21,96 +19,102 @@ Every key in Redis takes memory and requires at least the amount of RAM to store
2119
well as some per-key overhead that Redis uses. On top of that, the value in the key also requires
2220
RAM.
2321

24-
Redis JSON stores JSON values as binary data after deserializing them. This representation is often more
25-
expensive, size-wise, than the serialized form. The JSON data type uses at least 24 bytes (on
26-
64-bit architectures) for every value, as can be seen by sampling an empty string with the
27-
[`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:
2826

2927
```
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+
3038
127.0.0.1:6379> JSON.SET emptystring . '""'
3139
OK
3240
127.0.0.1:6379> JSON.DEBUG MEMORY emptystring
33-
(integer) 24
34-
```
41+
(integer) 8
3542
36-
This RAM requirement is the same for all scalar values, but strings require additional space
37-
depending on their actual length. For example, a 3-character string will use 3 additional bytes:
43+
127.0.0.1:6379> JSON.SET emptyarr . '[]'
44+
OK
45+
127.0.0.1:6379> JSON.DEBUG MEMORY emptyarr
46+
(integer) 8
3847
39-
```
40-
127.0.0.1:6379> JSON.SET foo . '"bar"'
48+
127.0.0.1:6379> JSON.SET emptyobj . '{}'
4149
OK
42-
127.0.0.1:6379> JSON.DEBUG MEMORY foo
43-
(integer) 27
50+
127.0.0.1:6379> JSON.DEBUG MEMORY emptyobj
51+
(integer) 8
4452
```
4553

46-
Empty containers take up 32 bytes to set up:
54+
This RAM requirement is the same for all scalar values, but strings require additional space
55+
depending on their length. For example, a 3-character string will use 3 additional bytes:
4756

4857
```
49-
127.0.0.1:6379> JSON.SET arr . '[]'
50-
OK
51-
127.0.0.1:6379> JSON.DEBUG MEMORY arr
52-
(integer) 32
53-
127.0.0.1:6379> JSON.SET obj . '{}'
58+
127.0.0.1:6379> JSON.SET foo . '"bar"'
5459
OK
55-
127.0.0.1:6379> JSON.DEBUG MEMORY obj
56-
(integer) 32
60+
127.0.0.1:6379> JSON.DEBUG MEMORY foo
61+
(integer) 11
5762
```
5863

59-
The actual size of a container is the sum of sizes of all items in it on top of its own
60-
overhead. To avoid expensive memory reallocations, containers' capacity is scaled by multiples of 2
61-
until a treshold size is reached, from which they grow by fixed chunks.
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
6268

63-
A container with a single scalar is made up of 32 and 24 bytes, respectively:
6469
```
6570
127.0.0.1:6379> JSON.SET arr . '[""]'
6671
OK
6772
127.0.0.1:6379> JSON.DEBUG MEMORY arr
6873
(integer) 56
6974
```
7075

71-
A container with two scalars requires 40 bytes for the container (each pointer to an entry in the
72-
container is 8 bytes), and 2 * 24 bytes for the values themselves:
7376
```
7477
127.0.0.1:6379> JSON.SET arr . '["", ""]'
7578
OK
7679
127.0.0.1:6379> JSON.DEBUG MEMORY arr
77-
(integer) 88
80+
(integer) 56
7881
```
7982

80-
A 3-item (each 24 bytes) container will be allocated with capacity for 4 items, i.e. 56 bytes:
81-
8283
```
8384
127.0.0.1:6379> JSON.SET arr . '["", "", ""]'
8485
OK
8586
127.0.0.1:6379> JSON.DEBUG MEMORY arr
86-
(integer) 128
87+
(integer) 56
8788
```
8889

89-
The next item will not require an allocation in the container, so usage will increase only by that
90-
scalar's requirement, but another value will scale the container again:
91-
9290
```
9391
127.0.0.1:6379> JSON.SET arr . '["", "", "", ""]'
9492
OK
9593
127.0.0.1:6379> JSON.DEBUG MEMORY arr
96-
(integer) 152
94+
(integer) 56
95+
```
96+
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.
98+
99+
```
97100
127.0.0.1:6379> JSON.SET arr . '["", "", "", "", ""]'
98101
OK
99102
127.0.0.1:6379> JSON.DEBUG MEMORY arr
100-
(integer) 208
103+
(integer) 88
101104
```
102105

103-
This table gives the size (in bytes) of a few of the test files on disk and when stored using
104-
JSON. The _MessagePack_ column is for reference purposes and reflects the length of the value
105-
when stored using MessagePack.
106-
107-
| File | Filesize | Redis JSON | MessagePack |
108-
| -------------------------------------- | --------- | ------ | ----------- |
109-
| /tests/files/pass-100.json | 380 | 1079 | 140 |
110-
| /tests/files/pass-jsonsl-1.json | 1441 | 3666 | 753 |
111-
| /tests/files/pass-json-parser-0000.json | 3468 | 7209 | 2393 |
112-
| /tests/files/pass-jsonsl-yahoo2.json | 18446 | 37469 | 16869 |
113-
| /tests/files/pass-jsonsl-yelp.json | 39491 | 75341 | 35469 |
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
109+
JSON. The _MessagePack_ column is for reference purposes and reflects the length of the value when stored using [MessagePack](https://msgpack.org/index.html).
110+
111+
| File | File size | Redis JSON | MessagePack |
112+
| --------------------------------------- | --------- | ---------- | ----------- |
113+
| /tests/files/pass-100.json | 381 | 1069 | 140 |
114+
| /tests/files/pass-jsonsl-1.json | 1387 | 2190 | 757 |
115+
| /tests/files/pass-json-parser-0000.json | 3718 | 5469 | 2393 |
116+
| /tests/files/pass-jsonsl-yahoo2.json | 22466 | 26901 | 16869 |
117+
| /tests/files/pass-jsonsl-yelp.json | 46333 | 57513 | 35529 |
114118

115119
> Note: In the current version, deleting values from containers **does not** free the container's
116120
allocated memory.

0 commit comments

Comments
 (0)