Skip to content

Commit

Permalink
Added a new configuration parameter to allow the administrator to con…
Browse files Browse the repository at this point in the history
…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
Thomas O'Dowd committed Apr 7, 2010
1 parent d57f77c commit aa217d8
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 2 deletions.
6 changes: 5 additions & 1 deletion include/yaws.hrl
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions man/yaws.conf.5
Expand Up @@ -107,6 +107,15 @@ Set this value to control the maximum number of connections
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
Expand Down
7 changes: 7 additions & 0 deletions scripts/yaws.conf.template
Expand Up @@ -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
Expand Down
42 changes: 42 additions & 0 deletions src/yaws_config.erl
Expand Up @@ -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) ->
Expand Down Expand Up @@ -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) ->
Expand Down
9 changes: 8 additions & 1 deletion src/yaws_server.erl
Expand Up @@ -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),
Expand Down

0 comments on commit aa217d8

Please sign in to comment.