summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Slepchin <igor.slepchin@gmail.com>2018-09-25 00:44:00 -0400
committerIgor Slepchin <igor.slepchin@gmail.com>2018-10-11 17:03:29 -0400
commit917eeea53273f00489715a94a90cc0c2bb129b74 (patch)
tree742ae6d7fad27f30ef8c1d5ac25bd5d4e3c4658f
parent210665e8a252faecf28ccebade999e734ab92582 (diff)
downloaderlang-917eeea53273f00489715a94a90cc0c2bb129b74.tar.gz
"cork" tcp socket around file:sendfile
This fixes 200ms delay on the last TCP segment when using file:sendfile/2 on Linux (ERL-698).
-rw-r--r--erts/preloaded/src/prim_inet.erl24
1 files changed, 23 insertions, 1 deletions
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index c98c7937b7..abd322e5cf 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -520,13 +520,35 @@ sendfile(S, FileHandle, Offset, Length)
sendfile(S, FileHandle, Offset, Length) ->
case erlang:port_info(S, connected) of
{connected, Pid} when Pid =:= self() ->
- sendfile_1(S, FileHandle, Offset, Length);
+ Uncork = sendfile_maybe_cork(S),
+ Result = sendfile_1(S, FileHandle, Offset, Length),
+ sendfile_maybe_uncork(S, Uncork),
+ Result;
{connected, Pid} when Pid =/= self() ->
{error, not_owner};
_Other ->
{error, einval}
end.
+sendfile_maybe_cork(S) ->
+ case getprotocol(S) of
+ tcp ->
+ case getopts(S, [nopush]) of
+ {ok, [{nopush,false}]} ->
+ _ = setopts(S, [{nopush,true}]),
+ true;
+ _ ->
+ false
+ end;
+ _ -> false
+ end.
+
+sendfile_maybe_uncork(S, true) ->
+ _ = setopts(S, [{nopush,false}]),
+ ok;
+sendfile_maybe_uncork(_, false) ->
+ ok.
+
sendfile_1(S, FileHandle, Offset, 0) ->
sendfile_1(S, FileHandle, Offset, (1 bsl 63) - 1);
sendfile_1(_S, _FileHandle, Offset, Length) when