diff options
author | Björn Gustavsson <[email protected]> | 2017-12-07 12:16:04 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-12-08 07:11:18 +0100 |
commit | 2fb94bbae9b3ebf6bbd5b0ba3546450036764383 (patch) | |
tree | 29b2ae1ffbe29efc45a90e15b249af419a672fae | |
parent | 71bb60815630574bf710b8ce8a7d3b0e48b5a985 (diff) | |
download | otp-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.
-rw-r--r-- | lib/kernel/src/file_io_server.erl | 21 |
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 |