Skip to content

Commit e1d333d

Browse files
committed
Send iodata with socket:sendv
socket:send flattens iolists with list_to_binary on every call; sendv (OTP 27+) converts the iolist to an iovec and hands it to a single writev-style NIF call instead. Binaries keep using send.
1 parent 92dc5ae commit e1d333d

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

src/shackle_socket.erl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
-include("shackle_internal.hrl").
33

44
%% The socket specs on OTP < 28 predate {otp, select_read} and its
5-
%% recv return shapes, although both work at runtime from OTP 27.3.
6-
-dialyzer({nowarn_function, [recv/1, setopts/2]}).
5+
%% recv return shapes, and socket:sendv only exists from OTP 27,
6+
%% although everything works at runtime from OTP 27.3.
7+
-dialyzer({nowarn_function, [recv/1, send/2, sendv/2, setopts/2]}).
8+
-ignore_xref([
9+
{socket, sendv, 2}
10+
]).
711

812
-behavior(shackle_protocol).
913
-export([
@@ -78,15 +82,19 @@ recv(Socket) ->
7882
-spec send(shackle:socket(), iodata()) ->
7983
ok | {error, atom()}.
8084

81-
send(Socket, Data) ->
85+
send(Socket, Data) when is_binary(Data) ->
8286
case socket:send(Socket, Data) of
8387
ok ->
8488
ok;
8589
{error, {Reason, _RestData}} ->
8690
{error, Reason};
8791
{error, Reason} ->
8892
{error, Reason}
89-
end.
93+
end;
94+
%% socket:send flattens iolists with list_to_binary; sendv keeps the
95+
%% iovec and writes it in one NIF call
96+
send(Socket, Data) ->
97+
sendv(Socket, erlang:iolist_to_iovec(Data)).
9098

9199
-spec setopts(shackle:socket(), [gen_tcp:option()]) ->
92100
ok |
@@ -112,6 +120,18 @@ setopts(Socket, Opts) ->
112120
connect_opts(Socket, Opts).
113121

114122
%% private
123+
sendv(Socket, IOV) ->
124+
case socket:sendv(Socket, IOV) of
125+
ok ->
126+
ok;
127+
{ok, RestIOV} ->
128+
sendv(Socket, RestIOV);
129+
{error, {Reason, _RestIOV}} ->
130+
{error, Reason};
131+
{error, Reason} ->
132+
{error, Reason}
133+
end.
134+
115135
connect_opts(_Socket, []) ->
116136
ok;
117137
connect_opts(Socket, [{nodelay, Bool} | T]) ->

0 commit comments

Comments
 (0)