Permalink
Browse files

Added a new configuration parameter to allow the administrator to con…

…trol

the erlang virtual machines garbage collection knobs when spawning a new
process to handle incoming connections. The option is called "process_options".
Its default value is the empty list which uses erlangs default options as
is the case now. This is useful for long lived connections which can generate
a lot of garbage if left untapped. Use with care :-)
  • Loading branch information...
1 parent d57f77c commit aa217d8f0e029d2d9f3e16499c7951d09692e79d Thomas O'Dowd committed Apr 7, 2010
Showing with 71 additions and 2 deletions.
  1. +5 −1 include/yaws.hrl
  2. +9 −0 man/yaws.conf.5
  3. +7 −0 scripts/yaws.conf.template
  4. +42 −0 src/yaws_config.erl
  5. +8 −1 src/yaws_server.erl
View
@@ -77,7 +77,11 @@
max_num_cached_files = 400,
max_num_cached_bytes = 1000000, %% 1 MEG
max_size_cached_file = 8000,
- max_connections = nolimit, %% max number of TCP connections
+ max_connections = nolimit, %% max number of TCP connections
+ process_options = [], %% Override default connection handler processes
+ %% spawn options for performance/memory tuning.
+ %% [] | [{fullsweep_after, Number}, {min_heap_size, Size}]
+ %% other options such as monitor, link are ignored.
large_file_chunk_size = 10240,
mnesia_dir = [],
log_wrap_size = 10000000, % wrap logs after 10M
View
@@ -108,6 +108,15 @@ from HTTP clients into the server. This is implemented by closing
the last socket if the limit threshold is reached.
.TP
+\fB process_options = "[]" | "[{fullsweep_after, int()} | {min_heap_size, int()}]"\fR
+Override the garbage collection option parameters for processes
+which handle new connections. Useful for systems which expect long lived
+connections which handle a lot of data. The default value is erlangs
+default which does minimal garbage collection until the process dies.
+The value type is a quoted string which contains an erlang proplist.
+See erlangs erlang:spawn_opt/4 function for more details.
+
+.TP
\fB log_wrap_size = Integer\fR
The logs written by yaws are all wrap logs, the default value at the
size where they wrap around and the original gets renamed to File.old
@@ -29,6 +29,13 @@ include_dir = %yawsdir%/examples/include
# max number of connections from clients into the server
max_connections = nolimit
+# Override the garbage collection option parameters for processes
+# which handle new connections. Useful for systems which expect long lived
+# connections which handle a lot of data. The default value is erlangs
+# default. Valid options are {fullsweep_after, X} and/or {min_heap_size, Y} where
+# X and Y are integers. See erlangs erlang:spawn_opt/4 function for more details.
+# The value type is a quoted string containing an erlang proplist
+process_options = "[]"
# This is a debug variable, possible values are http | traffic | false
# It is also possible to set the trace (possibly to the tty) while
View
@@ -584,6 +584,15 @@ fload(FD, globals, GC, C, Cs, Lno, Chars) ->
{error, ?F("Expect integer at line ~w", [Lno])}
end;
+ ["process_options", '=', POpts] ->
+ case parse_process_options(POpts) of
+ {ok, ProcList} ->
+ fload(FD, globals, GC#gconf{process_options=ProcList},
+ C, Cs, Lno+1, Next);
+ {error, Str} ->
+ {error, ?F("~s at line ~w", [Str, Lno])}
+ end;
+
["log_wrap_size", '=', Int] ->
case (catch list_to_integer(Int)) of
I when is_integer(I) ->
@@ -1467,6 +1476,39 @@ is_string_char([C|T]) ->
is_special(C) ->
lists:member(C, [$=, $<, $>, $,]).
+%% parse the argument string PLString which can either be the undefined atom
+%% or a proplist. Currently the only supported keys are fullsweep_after and
+%% min_heap_size. Any other key/values are ignored.
+parse_process_options(PLString) ->
+ case erl_scan:string(PLString ++ ".") of
+ {ok, PLTokens, _} ->
+ case erl_parse:parse_term(PLTokens) of
+ {ok, undefined} ->
+ {ok, []};
+ {ok, []} ->
+ {ok, []};
+ {ok, [Hd|_Tl]=PList} when is_atom(Hd); is_tuple(Hd) ->
+ %% create new safe proplist of desired options
+ {ok, proplists_int_copy([], PList, [fullsweep_after, min_heap_size])};
+ _ ->
+ {error, "Expect undefined or proplist"}
+ end;
+ _ ->
+ {error, "Expect undefined or proplist"}
+ end.
+
+%% copy proplist integer values for the given keys from the
+%% Src proplist to the Dest proplist. Ignored keys that are not
+%% found or have non-integer values. Returns the new Dest proplist.
+proplists_int_copy(Dest, _Src, []) ->
+ Dest;
+proplists_int_copy(Dest, Src, [Key|NextKeys]) ->
+ case proplists:get_value(Key, Src) of
+ Val when is_integer(Val) ->
+ proplists_int_copy([{Key, Val}|Dest], Src, NextKeys);
+ _ ->
+ proplists_int_copy(Dest, Src, NextKeys)
+ end.
parse_soap_srv_mods(['<', Module, ',' , Handler, ',', WsdlFile, '>' | Tail],
Ack) ->
View
@@ -908,7 +908,14 @@ initial_acceptor(GS) ->
acceptor(GS) ->
- proc_lib:spawn_link(?MODULE, acceptor0, [GS, self()]).
+ case (GS#gs.gconf)#gconf.process_options of
+ [] ->
+ proc_lib:spawn_link(?MODULE, acceptor0, [GS, self()]);
+ Opts ->
+ %% as we tightly controlled what is set in options, we can blindly add "link" to
+ %% get a linked process as per default case and use the provided options.
+ proc_lib:spawn_opt(?MODULE, acceptor0, [GS, self()], [link | Opts])
+ end.
acceptor0(GS, Top) ->
?TC([{record, GS, gs}]),
put(gc, GS#gs.gconf),

0 comments on commit aa217d8

Please sign in to comment.