diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/stdlib/test/ets_SUITE.erl | 100 |
1 files changed, 77 insertions, 23 deletions
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index b1813052d2..e992397519 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -44,7 +44,7 @@ t_delete_all_objects/1, t_insert_list/1, t_test_ms/1, t_select_delete/1,t_select_replace/1,t_select_replace_next_bug/1,t_ets_dets/1]). -export([test_table_size_concurrency/1,test_table_memory_concurrency/1, - test_delete_table_while_size_snapshot/1, test_delete_table_while_size_snapshot_helper/0]). + test_delete_table_while_size_snapshot/1, test_delete_table_while_size_snapshot_helper/1]). -export([ordered/1, ordered_match/1, interface_equality/1, fixtable_next/1, fixtable_iter_bag/1, @@ -2692,8 +2692,14 @@ write_concurrency(Config) when is_list(Config) -> true = YesMem > NoHashMem, true = YesMem > NoTreeMem, true = YesMem > YesTreeMem, - true = YesTreeMem < NoTreeMem, - + %% The amount of memory used by ordered_set with write_concurrency + %% enabled depend on the number of schedulers due its use of + %% decentralized counters + case erlang:system_info(schedulers) of + N when N =< 4 -> + true = YesTreeMem < NoTreeMem; + _ -> ok + end, {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])), {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency}])), {'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,true,foo}])), @@ -4696,7 +4702,10 @@ size_loop(_T, 0, _, _) -> size_loop(T, I, PrevSize, WhatToTest) -> Size = ets:info(T, WhatToTest), case Size < PrevSize of - true -> ct:fail("Bad ets:info/2"); + true -> + io:format("Bad ets:info/2 (got ~p expected >=~p)", + [Size, PrevSize]), + ct:fail("Bad ets:info/2)"); _ -> ok end, size_loop(T, I -1, Size, WhatToTest). @@ -4708,13 +4717,17 @@ add_loop(T, I) -> add_loop(T, I -1). -test_table_counter_concurrency(WhatToTest) -> +test_table_counter_concurrency(WhatToTest, TableOptions) -> IntStatePrevOn = erts_debug:set_internal_state(available_internal_state, true), ItemsToAdd = 1000000, SizeLoopSize = 1000, - T = ets:new(k, [public, ordered_set, {write_concurrency, true}]), - erts_debug:set_internal_state(ets_debug_random_split_join, {T, false}), + T = ets:new(k, TableOptions), + case lists:member(ordered_set, TableOptions) of + true -> + erts_debug:set_internal_state(ets_debug_random_split_join, {T, false}); + false -> ok + end, 0 = ets:info(T, size), P = self(), SpawnedSizeProcs = @@ -4742,10 +4755,14 @@ test_table_counter_concurrency(WhatToTest) -> ok. test_table_size_concurrency(Config) when is_list(Config) -> - test_table_counter_concurrency(size). + BaseOptions = [public, {write_concurrency, true}], + test_table_counter_concurrency(size, [set | BaseOptions]), + test_table_counter_concurrency(size, [ordered_set | BaseOptions]). test_table_memory_concurrency(Config) when is_list(Config) -> - test_table_counter_concurrency(memory). + BaseOptions = [public, {write_concurrency, true}], + test_table_counter_concurrency(memory, [set | BaseOptions]), + test_table_counter_concurrency(memory, [ordered_set | BaseOptions]). %% Tests that calling the ets:delete operation on a table T with %% decentralized counters works while ets:info(T, size) operations are @@ -4755,15 +4772,19 @@ test_delete_table_while_size_snapshot(Config) when is_list(Config) -> %% depend on that pids are ordered in creation order which is no %% longer the case when many processes have been started before Node = start_slave(), - ok = rpc:call(Node, ?MODULE, test_delete_table_while_size_snapshot_helper, []), + [ok = rpc:call(Node, + ?MODULE, + test_delete_table_while_size_snapshot_helper, + [TableType]) + || TableType <- [set, ordered_set]], test_server:stop_node(Node), ok. -test_delete_table_while_size_snapshot_helper()-> +test_delete_table_while_size_snapshot_helper(TableType) -> TopParent = self(), repeat_par( fun() -> - Table = ets:new(t, [public, ordered_set, + Table = ets:new(t, [public, TableType, {write_concurrency, true}]), Parent = self(), NrOfSizeProcs = 100, @@ -4771,7 +4792,7 @@ test_delete_table_while_size_snapshot_helper()-> || _ <- lists:seq(1, NrOfSizeProcs)], timer:sleep(1), ets:delete(Table), - [receive + [receive table_gone -> ok; Problem -> TopParent ! Problem end || _ <- Pids] @@ -7676,6 +7697,7 @@ my_tab_to_list(Ts,Key, Acc) -> wait_for_memory_deallocations() -> try + erts_debug:set_internal_state(wait, thread_progress), erts_debug:set_internal_state(wait, deallocations) catch error:undef -> @@ -7687,20 +7709,52 @@ etsmem() -> % The following is done twice to avoid an inconsistent memory % "snapshot" (see verify_etsmem/2). lists:foldl( - fun(_,_) -> + fun(AttemptNr, PrevEtsMem) -> + AllTabsExceptions = [logger, code], + %% The logger table is excluded from the AllTabs list + %% below because it uses decentralized counters to keep + %% track of the size and the memory counters. This cause + %% ets:info(T,size) and ets:info(T,memory) to trigger + %% allocations and frees that may change the amount of + %% memory that is allocated for ETS. + %% + %% The code table is excluded from the list below + %% because the amount of memory allocated for it may + %% change if the tested code loads a new module. + AllTabs = + lists:sort( + [begin + case ets:info(T,write_concurrency) of + true -> + ct:fail("Background ETS table (~p) that " + "use decentralized counters (Add exception?)", + [ets:info(T,name)]); + _ -> ok + end, + {T, + ets:info(T,name), + ets:info(T,size), + ets:info(T,memory), + ets:info(T,type)} + end + || T <- ets:all(), + not lists:member(ets:info(T, name), AllTabsExceptions)]), wait_for_memory_deallocations(), - - AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size), - ets:info(T,memory),ets:info(T,type)} - end, ets:all()), - EtsAllocSize = erts_debug:alloc_blocks_size(ets_alloc), ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end, - - Mem = {ErlangMemoryEts, EtsAllocSize}, - {Mem, AllTabs} + FlxCtrMemUsage = erts_debug:get_internal_state(flxctr_memory_usage), + Mem = {ErlangMemoryEts, EtsAllocSize, FlxCtrMemUsage}, + EtsMem = {Mem, AllTabs}, + case PrevEtsMem of + first -> ok; + _ when PrevEtsMem =:= EtsMem -> ok; + _ -> + io:format("etsmem(): Change in attempt ~p~n~nbefore:~n~p~n~nafter:~n~p~n~n", + [AttemptNr, PrevEtsMem, EtsMem]) + end, + EtsMem end, - not_used, + first, lists:seq(1,2)). verify_etsmem(MI) -> |