From 07b0f4315b079cce7aeef7babdba1bbb686de611 Mon Sep 17 00:00:00 2001 From: Nathan Long Date: Tue, 13 Sep 2016 08:36:42 -0400 Subject: Let file:write_file/3 use writev Previously, this function would turn any input into a single binary before writing. This meant it could not take advantage of the `writev` system call if it was given a list of binaries and told to write with `raw` mode. To see this, start an erlang shell on the parent commit, and also start this dtrace script: https://github.com/evanmiller/tracewrite like this: sudo dtrace -s tracewrite.d -p $(pgrep beam) In the erlang shell, run the following: file:write_file("/tmp/tmp.txt", [<<97,98>>, <<98,97>>], [raw]). In the dtrace output, you will see that the system call used is `write`. Now repeat with this commit, and you will see that `writev` is used. --- lib/kernel/src/file.erl | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 58b601e456..1971df9038 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -397,25 +397,36 @@ write_file(Name, Bin) -> Modes :: [mode()], Reason :: posix() | badarg | terminated | system_limit. -write_file(Name, Bin, ModeList) when is_list(ModeList) -> - case make_binary(Bin) of - B when is_binary(B) -> - case open(Name, [binary, write | - lists:delete(binary, - lists:delete(write, ModeList))]) of - {ok, Handle} -> - case write(Handle, B) of - ok -> - close(Handle); - E1 -> - _ = close(Handle), - E1 - end; - E2 -> - E2 - end; - E3 -> - E3 +write_file(Name, IOData, ModeList) when is_list(ModeList) -> + case lists:member(raw, ModeList) of + true -> + %% For backwards compatibility of error messages + try iolist_size(IOData) of + _Size -> do_write_file(Name, IOData, ModeList) + catch + error:Error -> {error, Error} + end; + false -> + case make_binary(IOData) of + Bin when is_binary(Bin) -> + do_write_file(Name, Bin, ModeList); + Error -> + Error + end + end. + +do_write_file(Name, IOData, ModeList) -> + case open(Name, [binary, write | ModeList]) of + {ok, Handle} -> + case write(Handle, IOData) of + ok -> + close(Handle); + E1 -> + _ = close(Handle), + E1 + end; + E2 -> + E2 end. %% Obsolete, undocumented, local node only, don't use!. -- cgit v1.2.3