@@ -14,25 +14,83 @@ defmodule IEx.History do
1414
1515 limit = IEx.Options . get ( :history_size )
1616 start_counter = Process . get ( :iex_history_start_counter )
17- should_collect = limit_history ( start_counter , counter , limit )
17+ should_collect = limit_history ( start_counter , counter , limit , false )
1818 if should_collect do
19- IO . puts "...collecting garbage"
20- :erlang . garbage_collect
19+ collect_garbage ( )
2120 end
2221 end
2322
24- defp limit_history ( _ , _ , limit ) when limit < 0 do
23+ defp limit_history ( _ , _ , limit , _ ) when limit < 0 do
2524 false
2625 end
2726
28- defp limit_history ( counter , max_counter , limit ) when max_counter - counter < limit do
27+ defp limit_history ( counter , max_counter , limit , should_collect ) when max_counter - counter < limit do
2928 Process . put ( :iex_history_start_counter , counter )
30- true
29+ should_collect
3130 end
3231
33- defp limit_history ( counter , max_counter , limit ) do
34- Process . delete ( { :iex_history , counter } )
35- limit_history ( counter + 1 , max_counter , limit )
32+ defp limit_history ( counter , max_counter , limit , should_collect ) do
33+ if not should_collect do
34+ entry = Process . delete ( { :iex_history , counter } )
35+ should_collect = has_binary ( entry . result )
36+ else
37+ Process . delete ( { :iex_history , counter } )
38+ end
39+ limit_history ( counter + 1 , max_counter , limit , should_collect )
40+ end
41+
42+ # Checks val and each of its elements (if it is a list or a tuple)
43+ # recursively to see if it has any binaries
44+ defp has_binary ( val ) do
45+ try do
46+ has_bin ( val )
47+ catch
48+ :throw , true -> true
49+ end
50+ end
51+
52+ # Worker function used by has_binary. Throws when the first binary of the
53+ # minimum specified size is found
54+ defp has_bin ( val ) when is_tuple ( val ) do
55+ has_bin ( val , tuple_size ( val ) - 1 )
56+ end
57+
58+ defp has_bin ( [ h | t ] ) do
59+ has_bin ( h )
60+ has_bin ( t )
61+ end
62+
63+ defp has_bin ( val ) when byte_size ( val ) > 64 do
64+ throw true
65+ end
66+
67+ defp has_bin ( _ ) do
68+ false
69+ end
70+
71+ defp has_bin ( _ , - 1 ) do
72+ false
73+ end
74+
75+ defp has_bin ( tuple , index ) do
76+ has_bin ( elem ( tuple , index ) )
77+ has_bin ( tuple , index - 1 )
78+ end
79+
80+ # Based on https://github.com/erlang/otp/blob/7dcccee4371477e983f026db9e243cb66900b1ef/lib/stdlib/src/shell.erl#L1401
81+ defp collect_garbage do
82+ :erlang . garbage_collect ( self ( ) )
83+ try do
84+ :erlang . garbage_collect ( Process . whereis ( :user ) )
85+ catch
86+ _ , _ -> nil
87+ end
88+ try do
89+ :erlang . garbage_collect ( Process . group_leader ( ) )
90+ catch
91+ _ , _ -> nil
92+ end
93+ :erlang . garbage_collect ( )
3694 end
3795
3896 ### each ###
0 commit comments