1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1997-2013. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: 20: %% Test the garbage collector (or Memory Recycler) 21: 22: -module(gc_SUITE). 23: 24: -include_lib("test_server/include/test_server.hrl"). 25: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 26: init_per_group/2,end_per_group/2]). 27: 28: -define(default_timeout, ?t:minutes(10)). 29: 30: -export([grow_heap/1, grow_stack/1, grow_stack_heap/1]). 31: 32: suite() -> [{ct_hooks,[ts_install_cth]}]. 33: 34: all() -> 35: [grow_heap, grow_stack, grow_stack_heap]. 36: 37: groups() -> 38: []. 39: 40: init_per_suite(Config) -> 41: Config. 42: 43: end_per_suite(_Config) -> 44: ok. 45: 46: init_per_group(_GroupName, Config) -> 47: Config. 48: 49: end_per_group(_GroupName, Config) -> 50: Config. 51: 52: 53: grow_heap(doc) -> ["Produce a growing list of elements, ", 54: "for X calls, then drop one item per call", 55: "until the list is empty."]; 56: grow_heap(Config) when is_list(Config) -> 57: Dog = test_server:timetrap(test_server:minutes(40)), 58: ok = grow_heap1(256), 59: ok = grow_heap1(512), 60: ok = grow_heap1(1024), 61: ok = grow_heap1(2048), 62: test_server:timetrap_cancel(Dog), 63: ok. 64: 65: grow_heap1(Len) -> 66: io:format("~ngrow_heap with ~p items.",[Len]), 67: show_heap("before:"), 68: grow_heap1([], Len, 0, up), 69: show_heap("after:"). 70: 71: grow_heap1(List, MaxLen, MaxLen, up) -> 72: show_heap("top:"), 73: grow_heap1(List, MaxLen, MaxLen-1, down); 74: grow_heap1(List, MaxLen, CurLen, up) -> 75: NewList=[make_arbit()|List], 76: grow_heap1(NewList, MaxLen, CurLen+1, up); 77: grow_heap1([], _MaxLen, _, down) -> 78: ok; 79: grow_heap1([_|List], MaxLen, CurLen, down) -> 80: {_,_,C} = erlang:now(), 81: Num = C rem (length(List))+1, 82: Elem = lists:nth(Num, List), 83: NewList = lists:delete(Elem, List), 84: grow_heap1(NewList, MaxLen, CurLen-1, down). 85: 86: 87: 88: grow_stack(doc) -> ["Increase and decrease stack size, and ", 89: "drop off some garbage from time to time."]; 90: grow_stack(Config) when is_list(Config) -> 91: Dog = test_server:timetrap(test_server:minutes(80)), 92: show_heap("before:"), 93: grow_stack1(200, 0), 94: show_heap("after:"), 95: test_server:timetrap_cancel(Dog), 96: ok. 97: 98: grow_stack1(0, _) -> 99: ok; 100: grow_stack1(Recs, 0) -> 101: % show_heap("running:"), 102: grow_stack1(Recs-1, Recs), 103: grow_stack1(0,0); 104: grow_stack1(Recs, CurRecs) -> 105: grow_stack1(Recs, CurRecs-1), 106: make_arbit(), 107: grow_stack1(1,0), 108: ok. 109: 110: 111: %% Let's see how BEAM handles this one... 112: grow_stack_heap(doc) -> ["While growing the heap, bounces the size ", 113: "of the stack, and while reducing the heap", 114: "bounces the stack usage."]; 115: grow_stack_heap(Config) when is_list(Config) -> 116: Dog = test_server:timetrap(test_server:minutes(40)), 117: grow_stack_heap1(16), 118: grow_stack_heap1(32), 119: test_server:timetrap_cancel(Dog), 120: ok. 121: 122: grow_stack_heap1(MaxLen) -> 123: io:format("~ngrow_stack_heap with ~p items.",[MaxLen]), 124: show_heap("before:"), 125: grow_stack_heap1([], MaxLen, 0, up), 126: show_heap("after:"). 127: 128: grow_stack_heap1(List, MaxLen, MaxLen, up) -> 129: show_heap("top:"), 130: grow_stack_heap1(List, MaxLen, MaxLen-1, down); 131: grow_stack_heap1(List, MaxLen, CurLen, up) -> 132: grow_stack1(CurLen*2,0), 133: grow_stack_heap1([make_arbit()|List], MaxLen, CurLen+1, up), 134: ok; 135: 136: grow_stack_heap1([], _MaxLen, _, down) -> ok; 137: grow_stack_heap1([_|List], MaxLen, CurLen, down) -> 138: grow_stack1(CurLen*2,0), 139: {_,_,C}=erlang:now(), 140: Num=C rem (length(List))+1, 141: Elem=lists:nth(Num, List), 142: NewList=lists:delete(Elem, List), 143: grow_stack_heap1(NewList, MaxLen, CurLen-1, down), 144: ok. 145: 146: 147: %% Create an arbitrary element/term. 148: make_arbit() -> 149: {AA,BB,CC}=erlang:now(), 150: A=AA+1, B=BB+1, C=CC+1, 151: New = 152: case C rem 9 of 153: 0 -> make_string((B div C) +5); 154: 1 -> C; 155: 2 -> make_ref(); 156: 3 -> self(); 157: 4 -> list_to_binary(make_string((C div B) + 12)); 158: 5 -> (C*B)/(A+1); 159: 6 -> list_to_tuple(make_string((B div C) +5)); 160: 7 -> list_to_atom(make_string(((C div B) rem 254) + 2)); 161: 8 -> fun(X) -> {X,AA,make_string((B div C)+10)} end 162: end, 163: New. 164: 165: %% Create an arbitrary string of a certain length. 166: make_string(Length) -> 167: Alph="abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"++ 168: "0123456789", 169: make_string(Alph, Length, []). 170: 171: make_string(_, 0, Acc) -> 172: Acc; 173: make_string(Alph, Length, Acc) -> 174: {_,_,C}=erlang:now(), 175: Pos=1+(Length*C rem length(Alph)), 176: make_string(Alph, Length-1, 177: [lists:nth(Pos,Alph)|Acc]). 178: 179: show_heap(String) -> 180: garbage_collect(self()), 181: receive after 1 -> ok end, 182: {heap_size, HSize}=process_info(self(), heap_size), 183: {stack_size, SSize}=process_info(self(), stack_size), 184: io:format("Heap/Stack "++String++"~p/~p", [HSize, SSize]). 185: