aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl65
-rw-r--r--lib/kernel/src/erts_debug.erl20
2 files changed, 75 insertions, 10 deletions
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 4dc2fbaae2..76667772c7 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -23,13 +23,13 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
- flat_size/1,flat_size_big/1,df/1,
+ test_size/1,flat_size_big/1,df/1,
instructions/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [flat_size, flat_size_big, df, instructions].
+ [test_size, flat_size_big, df, instructions].
groups() ->
[].
@@ -55,16 +55,58 @@ end_per_testcase(_Func, Config) ->
Dog=?config(watchdog, Config),
?t:timetrap_cancel(Dog).
-flat_size(Config) when is_list(Config) ->
- 0 = erts_debug:flat_size([]),
- 0 = erts_debug:flat_size(42),
- 2 = erts_debug:flat_size([a|b]),
- 1 = erts_debug:flat_size({}),
- 2 = erts_debug:flat_size({[]}),
- 3 = erts_debug:flat_size({a,b}),
- 7 = erts_debug:flat_size({a,[b,c]}),
+test_size(Config) when is_list(Config) ->
+ ConsCell1 = id([a|b]),
+ ConsCell2 = id(ConsCell1),
+ ConsCellSz = 2,
+
+ 0 = do_test_size([]),
+ 0 = do_test_size(42),
+ ConsCellSz = do_test_size(ConsCell1),
+ 1 = do_test_size({}),
+ 2 = do_test_size({[]}),
+ 3 = do_test_size({a,b}),
+ 7 = do_test_size({a,[b,c]}),
+
+ %% Test internal consistency of sizes, but without testing
+ %% exact sizes.
+ Const = id(42),
+ AnotherConst = id(7),
+
+ %% Fun environment size = 0 (the smallest fun possible)
+ SimplestFun = fun() -> ok end,
+ FunSz0 = do_test_size(SimplestFun),
+
+ %% Fun environment size = 1
+ FunSz1 = do_test_size(fun() -> Const end),
+ FunSz1 = FunSz0 + 1,
+
+ %% Fun environment size = 2
+ FunSz2 = do_test_size(fun() -> Const+AnotherConst end),
+ FunSz2 = FunSz1 + 1,
+
+ FunSz1 = do_test_size(fun() -> ConsCell1 end) - do_test_size(ConsCell1),
+
+ %% Test shared data structures.
+ do_test_size([ConsCell1|ConsCell1],
+ 3*ConsCellSz,
+ 2*ConsCellSz),
+ do_test_size(fun() -> {ConsCell1,ConsCell2} end,
+ FunSz2 + 2*ConsCellSz,
+ FunSz2 + ConsCellSz),
+ do_test_size({SimplestFun,SimplestFun},
+ 2*FunSz0+do_test_size({a,b}),
+ FunSz0+do_test_size({a,b})),
ok.
+do_test_size(Term) ->
+ Sz = erts_debug:flat_size(Term),
+ Sz = erts_debug:size(Term).
+
+do_test_size(Term, FlatSz, Sz) ->
+ FlatSz = erts_debug:flat_size(Term),
+ Sz = erts_debug:size(Term).
+
flat_size_big(Config) when is_list(Config) ->
%% Build a term whose external size only fits in a big num (on 32-bit CPU).
flat_size_big_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF).
@@ -96,3 +138,6 @@ instructions(Config) when is_list(Config) ->
?line Is = erts_debug:instructions(),
?line _ = [list_to_atom(I) || I <- Is],
ok.
+
+id(I) ->
+ I.
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index b3d54ddc1d..6654cd9ee7 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -182,6 +182,11 @@ size(Tuple, Seen0, Sum0) when is_tuple(Tuple) ->
Sum = Sum0 + 1 + tuple_size(Tuple),
tuple_size(1, tuple_size(Tuple), Tuple, Seen, Sum)
end;
+size(Fun, Seen0, Sum) when is_function(Fun) ->
+ case remember_term(Fun, Seen0) of
+ seen -> {Sum,Seen0};
+ Seen -> fun_size(Fun, Seen, Sum)
+ end;
size(Term, Seen0, Sum) ->
case erts_debug:flat_size(Term) of
0 -> {Sum,Seen0};
@@ -197,6 +202,21 @@ tuple_size(I, Sz, _, Seen, Sum) when I > Sz ->
tuple_size(I, Sz, Tuple, Seen0, Sum0) ->
{Sum,Seen} = size(element(I, Tuple), Seen0, Sum0),
tuple_size(I+1, Sz, Tuple, Seen, Sum).
+
+fun_size(Fun, Seen, Sum) ->
+ case erlang:fun_info(Fun, type) of
+ {type,external} ->
+ {Sum + erts_debug:flat_size(Fun),Seen};
+ {type,local} ->
+ Sz = erts_debug:flat_size(fun() -> ok end),
+ {env,Env} = erlang:fun_info(Fun, env),
+ fun_size_1(Env, Seen, Sum+Sz+length(Env))
+ end.
+
+fun_size_1([H|T], Seen0, Sum0) ->
+ {Sum,Seen} = size(H, Seen0, Sum0),
+ fun_size_1(T, Seen, Sum);
+fun_size_1([], Seen, Sum) -> {Sum,Seen}.
remember_term(Term, Seen) ->
case gb_trees:lookup(Term, Seen) of