Skip to content

Commit 22b7220

Browse files
committed
Reduce memory usage in json stack
Avoid additional cons on objects and arrays by using tuples for objects (uses 3 words instead of 4 words) and avoiding a double cons on arrays (uses 2 words).
1 parent 50d69f7 commit 22b7220

1 file changed

Lines changed: 11 additions & 13 deletions

File tree

lib/stdlib/src/json.erl

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -806,9 +806,6 @@ steps(N) -> ["\n", lists:duplicate(N, " ")].
806806
%% Decoding implementation
807807
%%
808808

809-
-define(ARRAY, array).
810-
-define(OBJECT, object).
811-
812809
-type from_binary_fun() :: fun((binary()) -> dynamic()).
813810
-type array_start_fun() :: fun((Acc :: dynamic()) -> ArrayAcc :: dynamic()).
814811
-type array_push_fun() :: fun((Value :: dynamic(), Acc :: dynamic()) -> NewAcc :: dynamic()).
@@ -844,7 +841,7 @@ steps(N) -> ["\n", lists:duplicate(N, " ")].
844841
}).
845842

846843
-type acc() :: dynamic().
847-
-type stack() :: [?ARRAY | ?OBJECT | binary() | acc()].
844+
-type stack() :: [] | {acc(), stack()} | nonempty_improper_list(acc(), stack()).
848845
-type decode() :: #decode{}.
849846

850847
-opaque continuation_state() :: tuple().
@@ -1359,8 +1356,8 @@ array_start(<<>>, Original, Skip, Acc, Stack, Decode, Len) ->
13591356
unexpected(Original, Skip, Acc, Stack, Decode, Len, 0, value);
13601357
array_start(Rest, Original, Skip, OldAcc, Stack, Decode, Len) ->
13611358
case Decode#decode.array_start of
1362-
undefined -> value(Rest, Original, Skip+Len, [], [?ARRAY, OldAcc | Stack], Decode);
1363-
Fun -> value(Rest, Original, Skip+Len, Fun(OldAcc), [?ARRAY, OldAcc | Stack], Decode)
1359+
undefined -> value(Rest, Original, Skip+Len, [], [OldAcc | Stack], Decode);
1360+
Fun -> value(Rest, Original, Skip+Len, Fun(OldAcc), [OldAcc | Stack], Decode)
13641361
end.
13651362

13661363
array_push(<<Byte, Rest/bits>>, Original, Skip, Acc, Stack, Decode, Value) when ?is_ws(Byte) ->
@@ -1371,7 +1368,7 @@ array_push(<<"]", Rest/bits>>, Original, Skip, Acc0, Stack0, Decode, Value) ->
13711368
undefined -> [Value | Acc0];
13721369
Push -> Push(Value, Acc0)
13731370
end,
1374-
[_, OldAcc | Stack] = Stack0,
1371+
[OldAcc | Stack] = Stack0,
13751372
{ArrayValue, NewAcc} =
13761373
case Decode#decode.array_finish of
13771374
undefined -> {lists:reverse(Acc), OldAcc};
@@ -1387,7 +1384,6 @@ array_push(<<$,, Rest/bits>>, Original, Skip0, Acc, Stack, Decode, Value) ->
13871384
array_push(_, Original, Skip, Acc, Stack, Decode, Value) ->
13881385
unexpected(Original, Skip, Acc, Stack, Decode, 0, 0, {?FUNCTION_NAME, Value}).
13891386

1390-
13911387
object_start(<<Byte, Rest/bits>>, Original, Skip, Acc, Stack, Decode, Len) when ?is_ws(Byte) ->
13921388
object_start(Rest, Original, Skip, Acc, Stack, Decode, Len+1);
13931389
object_start(<<"}", Rest/bits>>, Original, Skip, Acc, Stack, Decode, Len) ->
@@ -1400,7 +1396,7 @@ object_start(<<"}", Rest/bits>>, Original, Skip, Acc, Stack, Decode, Len) ->
14001396
end,
14011397
continue(Rest, Original, Skip+Len+1, NewAcc, Stack, Decode, Value);
14021398
object_start(<<$", Rest/bits>>, Original, Skip0, OldAcc, Stack0, Decode, Len) ->
1403-
Stack = [?OBJECT, OldAcc | Stack0],
1399+
Stack = {OldAcc, Stack0},
14041400
Skip = Skip0 + Len + 1,
14051401
case Decode#decode.object_start of
14061402
undefined ->
@@ -1427,7 +1423,7 @@ object_push(<<"}", Rest/bits>>, Original, Skip, Acc0, Stack0, Decode, Value, Key
14271423
undefined -> [{Key, Value} | Acc0];
14281424
Fun -> Fun(Key, Value, Acc0)
14291425
end,
1430-
[_, OldAcc | Stack] = Stack0,
1426+
{OldAcc, Stack} = Stack0,
14311427
{ObjectValue, NewAcc} =
14321428
case Decode#decode.object_finish of
14331429
undefined -> {maps:from_list(Acc), OldAcc};
@@ -1452,9 +1448,11 @@ object_key(_, Original, Skip, Acc, Stack, Decode) ->
14521448
continue(<<Rest/bits>>, Original, Skip, Acc, Stack0, Decode, Value) ->
14531449
case Stack0 of
14541450
[] -> terminate(Rest, Original, Skip, Acc, Value);
1455-
[?ARRAY | _] -> array_push(Rest, Original, Skip, Acc, Stack0, Decode, Value);
1456-
[?OBJECT | _] -> object_value(Rest, Original, Skip, Acc, Stack0, Decode, Value);
1457-
[Key | Stack] -> object_push(Rest, Original, Skip, Acc, Stack, Decode, Value, Key)
1451+
[_ | Stack] when is_list(Stack) ->
1452+
array_push(Rest, Original, Skip, Acc, Stack0, Decode, Value);
1453+
[Key | Stack] ->
1454+
object_push(Rest, Original, Skip, Acc, Stack, Decode, Value, Key);
1455+
{_, _} -> object_value(Rest, Original, Skip, Acc, Stack0, Decode, Value)
14581456
end.
14591457

14601458
terminate(<<Byte, Rest/bits>>, Original, Skip, Acc, Value) when ?is_ws(Byte) ->

0 commit comments

Comments
 (0)