aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/file_io_server.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-12-07 12:16:04 +0100
committerBjörn Gustavsson <[email protected]>2017-12-08 07:11:18 +0100
commit2fb94bbae9b3ebf6bbd5b0ba3546450036764383 (patch)
tree29b2ae1ffbe29efc45a90e15b249af419a672fae /lib/kernel/src/file_io_server.erl
parent71bb60815630574bf710b8ce8a7d3b0e48b5a985 (diff)
downloadotp-2fb94bbae9b3ebf6bbd5b0ba3546450036764383.tar.gz
otp-2fb94bbae9b3ebf6bbd5b0ba3546450036764383.tar.bz2
otp-2fb94bbae9b3ebf6bbd5b0ba3546450036764383.zip
Slightly optimize reading of cooked files in list mode
In general, the new NIF-based file routines are faster than the old efile driver. However, on some computers, building the entire OTP system is somewhat slower. It turns out that it is because 'erlc' cheated by turning off the IO thread pool (using '+A0') to avoid context switches between scheduler threads and threads in the IO thread pool. The new file routines perform IO on dirty IO threads, and there is (by intent) no way to force the operations to occur on scheduler threads to avoid the context switches What we can do to is to use a small (4Kb) read-ahead buffer for files opened for reading (only) in list mode (which is how the compiler opens its input files). The buffering reduces the number of context switches between scheduler threads and dirty IO threads. On my computer that seems to slightly speed up building of the entire OTP system. The buffer should do no harm. The only potential for harm I can think of is random access to a file opened in read mode, where the read-ahead buffer could slightly decrease performance. That does not seems to be a likely use case in practice, though.
Diffstat (limited to 'lib/kernel/src/file_io_server.erl')
-rw-r--r--lib/kernel/src/file_io_server.erl21
1 files changed, 20 insertions, 1 deletions
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 2b35d2acfb..34d5497a4a 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -68,7 +68,8 @@ do_start(Spawn, Owner, FileName, ModeList) ->
erlang:dt_restore_tag(Utag),
%% process_flag(trap_exit, true),
case parse_options(ModeList) of
- {ReadMode, UnicodeMode, Opts} ->
+ {ReadMode, UnicodeMode, Opts0} ->
+ Opts = maybe_add_read_ahead(ReadMode, Opts0),
case raw_file_io:open(FileName, [raw | Opts]) of
{error, Reason} = Error ->
Self ! {Ref, Error},
@@ -158,6 +159,24 @@ valid_enc({utf32,little}) ->
valid_enc(_Other) ->
{error,badarg}.
+%% Add a small read_ahead buffer if the file is opened for reading
+%% only in list mode and no read_ahead is already given.
+maybe_add_read_ahead(binary, Opts) ->
+ Opts;
+maybe_add_read_ahead(list, Opts) ->
+ P = fun(read_ahead) -> true;
+ ({read_ahead,_}) -> true;
+ (append) -> true;
+ (exclusive) -> true;
+ (write) -> true;
+ (_) -> false
+ end,
+ case lists:any(P, Opts) of
+ false ->
+ [{read_ahead, 4096}|Opts];
+ true ->
+ Opts
+ end.
server_loop(#state{mref = Mref} = State) ->
receive