diff --git a/homeassistant/helpers/json.py b/homeassistant/helpers/json.py index 0589490d2748..6a0792383cb6 100644 --- a/homeassistant/helpers/json.py +++ b/homeassistant/helpers/json.py @@ -122,10 +122,11 @@ def cached_json_bytes(data: Any) -> bytes: orjson over-allocates the returned bytes buffer and does not shrink it: the logical length is set but the capacity is rounded up to a power of two (at least a few KiB), so bytes cached for the lifetime of a long-lived object - retain several KiB of unused buffer. + retain several KiB of unused buffer. Copy them into a right-sized buffer. """ - # Drop orjson's over-allocated slack with help of a memoryview. - return bytes(memoryview(json_bytes(data))) + # The empty second join item is load-bearing: it forces a copy into a + # right-sized buffer; a single-item join returns the input unchanged. + return b"".join((json_bytes(data), b"")) def cached_json_fragment(data: Any) -> orjson.Fragment: @@ -134,8 +135,9 @@ def cached_json_fragment(data: Any) -> orjson.Fragment: Wraps the same right-sized bytes as cached_json_bytes; the body is inlined rather than calling it to avoid an extra function call on this hot path. """ - # Drop orjson's over-allocated slack with help of a memoryview. - return orjson.Fragment(bytes(memoryview(json_bytes(data)))) + # The empty second join item is load-bearing: it forces a copy into a + # right-sized buffer; a single-item join returns the input unchanged. + return orjson.Fragment(b"".join((json_bytes(data), b""))) def json_dumps(data: Any) -> str: