Inets performance
Ulf Wiger
etxuwig@REDACTED
Wed Mar 7 10:30:51 CET 2001
On Tue, 6 Mar 2001, Miguel Barreiro Paz wrote:
>Under high throughput demands, Inets
>will suffer badly from its higher cpu overhead compared to Apache (who
>quickly gets I/O bound before processor is a bottleneck, unless you abuse
>quite a bit of rewriting rules and such).
Inets is in dire need of optimization.
>I suppose Apache on Linux nowadays will serve html files with
>sendfile(2) directly if it can (ie., unless it has to parse shtml or
>so), thus avoiding a copy, a userspace buffer, and at least two
>kernel-userspace switches per write. That is close to as fast as you
>can get without hardcore kernelHTTPd solutions :)
Inets could at least use a linked-in driver that chunked a file and
delivered the chunks directly to a socket.
The file.erl module is really somewhat optimized for fairness (to
erlang processes not using heavy I/O) and pays extra reductions for
each message coming from the driver. If you want to write some
application that has really fast file I/O, you can't use file.erl as
it works today (as mnesia has found out...)
>I my very limited experience with inets, I have found a bit limiting
>that it can't serve streams, only finite-length data. And as far as
>I remember it won't serve anything produced by an erlet until the
>erlet has finished its output.
When I wrote my source code viewer (the ccviewer contrib), I
implemented such a function. I didn't use Inets, but I'm sure the same
thing could be done there. Here's the code: ccv_html_lib:progress(Fmt,
Args) mimics io:format/2 and <herecy>uses the process dictionary to
keep track of the socket, and to cache the complete page</herecy>.
When done, the request thread calls maybe_save_progress(). The reason
for this was that I use this for operations that can take so long that
the Netscape client often times out. In such a case (or if the user
closes the window), the complete page is stored an can be fetched
later.
/Uffe
progress(Fmt, Args) ->
progress(Fmt, Args, get_socket()).
progress(Fmt, Args, Socket) ->
Str = io_lib:format(Fmt, Args),
to_socket(Socket, Str),
store_progress(Str),
io:format("~p:" ++ Fmt, [self()|Args]).
to_socket(no_socket, _) -> ok;
to_socket(Socket, Str) ->
case send(Socket, Str) of
{error, Reason} ->
put(progress_to_socket, closed);
_ ->
ok
end.
store_progress(Str) ->
Sofar = get_html_progress(),
put(html_progress, [Str | Sofar]).
get_html_progress() ->
case get(html_progress) of
undefined ->
[];
Other ->
Other
end.
maybe_save_progress() ->
Title = get_strict(progress_title),
User = get_strict(progress_user),
Key = get_strict(progress_key),
case get_socket() of
no_socket ->
case get(html_progress) of
undefined ->
ok;
HtmlRev ->
Bin = list_to_binary(["<pre>\n",
lists:reverse(HtmlRev),
"\n</pre>"]),
ccv_user:store_page(Key, Title, User, Bin)
end;
Socket ->
ok
end.
get_strict(Key) ->
case get(Key) of
undefined ->
exit(unexpected);
Other ->
Other
end.
--
Ulf Wiger tfn: +46 8 719 81 95
Senior System Architect mob: +46 70 519 81 95
Strategic Product & System Management ATM Multiservice Networks
Data Backbone & Optical Services Division Ericsson Telecom AB
More information about the erlang-questions
mailing list