aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/file.erl
diff options
context:
space:
mode:
authorNathan Long <[email protected]>2016-09-13 08:36:42 -0400
committerNathan Long <[email protected]>2016-09-24 06:55:11 -0400
commit07b0f4315b079cce7aeef7babdba1bbb686de611 (patch)
tree0b7c8cb07090e61ba39bc7f85229cc0d6a96be90 /lib/kernel/src/file.erl
parent7228e3ea97f8e2a19be97740053892e67cc20baf (diff)
downloadotp-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.erl49
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!.