diff options
author | Nathan Long <[email protected]> | 2016-09-13 08:36:42 -0400 |
---|---|---|
committer | Nathan Long <[email protected]> | 2016-09-24 06:55:11 -0400 |
commit | 07b0f4315b079cce7aeef7babdba1bbb686de611 (patch) | |
tree | 0b7c8cb07090e61ba39bc7f85229cc0d6a96be90 /lib/kernel/src/file.erl | |
parent | 7228e3ea97f8e2a19be97740053892e67cc20baf (diff) | |
download | otp-07b0f4315b079cce7aeef7babdba1bbb686de611.tar.gz otp-07b0f4315b079cce7aeef7babdba1bbb686de611.tar.bz2 otp-07b0f4315b079cce7aeef7babdba1bbb686de611.zip |
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.
Diffstat (limited to 'lib/kernel/src/file.erl')
-rw-r--r-- | lib/kernel/src/file.erl | 49 |
1 files 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!. |