Skip to content

Commit 799ada3

Browse files
committed
Add socket protocol support and trim the encode path
The shackle protocol is now configurable with the protocol app env, so pools can run on shackle_socket instead of gen_tcp. The setup path (startup, auth, use keyspace) picks gen_tcp or the socket module based on the socket type. encode_long_string no longer copies the query into a fresh binary, and the query flags are computed with direct map lookups instead of four query_opts round trips. Against a local Scylla (64 callers, pool of 16), shackle_socket cuts client CPU from ~24.8 to ~19.8 us per request; throughput is server bound and unchanged. Requires a shackle release with shackle_socket when the protocol env is set; the default is unchanged.
1 parent 4da2b01 commit 799ada3

5 files changed

Lines changed: 49 additions & 47 deletions

File tree

src/marina_client.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ init(_Opts) ->
3030
frame_flags = marina_utils:frame_flags()
3131
}}.
3232

33-
-spec setup(inet:socket(), state()) ->
33+
-spec setup(shackle:socket(), state()) ->
3434
{ok, state()} |
3535
{error, atom(), state()}.
3636

src/marina_pool.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ start(<<A, B, C, D>> = RpcAddress) ->
105105
PoolSize = ?GET_ENV(pool_size, ?DEFAULT_POOL_SIZE),
106106
PoolStrategy = ?GET_ENV(pool_strategy, ?DEFAULT_POOL_STRATEGY),
107107
Port = ?GET_ENV(port, ?DEFAULT_PORT),
108+
Protocol = ?GET_ENV(protocol, shackle_tcp),
108109
Reconnect = ?GET_ENV(reconnect, ?DEFAULT_RECONNECT),
109110
ReconnectTimeMax = ?GET_ENV(reconnect_time_max,
110111
?DEFAULT_RECONNECT_MAX),
@@ -115,6 +116,7 @@ start(<<A, B, C, D>> = RpcAddress) ->
115116
ClientOptions = [
116117
{ip, Ip},
117118
{port, Port},
119+
{protocol, Protocol},
118120
{reconnect, Reconnect},
119121
{reconnect_time_max, ReconnectTimeMax},
120122
{reconnect_time_min, ReconnectTimeMin},

src/marina_request.erl

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -158,44 +158,34 @@ encode_batch_values(Values) ->
158158
[marina_types:encode_bytes(V) || V <- Values]].
159159

160160
flags(QueryOpts) ->
161-
{Mask1, Values} = values_flag(QueryOpts),
162-
Mask2 = skip_metadata(QueryOpts),
163-
{Mask3, PageSize} = page_size_flag(QueryOpts),
164-
{Mask4, PagingState} = paging_state(QueryOpts),
161+
{Mask1, Values} = values_flag(maps:get(values, QueryOpts, undefined)),
162+
Mask2 = skip_metadata(maps:get(skip_metadata, QueryOpts, false)),
163+
{Mask3, PageSize} =
164+
page_size_flag(maps:get(page_size, QueryOpts, undefined)),
165+
{Mask4, PagingState} =
166+
paging_state(maps:get(paging_state, QueryOpts, undefined)),
165167
Flags = Mask1 + Mask2 + Mask3 + Mask4,
166168
[Flags, Values, PageSize, PagingState].
167169

168-
page_size_flag(QueryOpts) ->
169-
case marina_utils:query_opts(page_size, QueryOpts) of
170-
undefined ->
171-
{0, []};
172-
PageSize ->
173-
{4, marina_types:encode_int(PageSize)}
174-
end.
175-
176-
paging_state(QueryOpts) ->
177-
case marina_utils:query_opts(paging_state, QueryOpts) of
178-
undefined ->
179-
{0, []};
180-
PagingState ->
181-
{8, marina_types:encode_bytes(PagingState)}
182-
end.
183-
184-
skip_metadata(QueryOpts) ->
185-
case marina_utils:query_opts(skip_metadata, QueryOpts) of
186-
false -> 0;
187-
true -> 2
188-
end.
189-
190-
values_flag(QueryOpts) ->
191-
case marina_utils:query_opts(values, QueryOpts) of
192-
undefined ->
193-
{0, []};
194-
Values ->
195-
ValuesCount = length(Values),
196-
EncodedValues = [marina_types:encode_bytes(Value) ||
197-
Value <- Values],
198-
Values2 = [marina_types:encode_short(ValuesCount),
199-
EncodedValues],
200-
{1, Values2}
201-
end.
170+
page_size_flag(undefined) ->
171+
{0, []};
172+
page_size_flag(PageSize) ->
173+
{4, marina_types:encode_int(PageSize)}.
174+
175+
paging_state(undefined) ->
176+
{0, []};
177+
paging_state(PagingState) ->
178+
{8, marina_types:encode_bytes(PagingState)}.
179+
180+
skip_metadata(false) ->
181+
0;
182+
skip_metadata(true) ->
183+
2.
184+
185+
values_flag(undefined) ->
186+
{0, []};
187+
values_flag(Values) ->
188+
ValuesCount = length(Values),
189+
EncodedValues = [marina_types:encode_bytes(Value) || Value <- Values],
190+
Values2 = [marina_types:encode_short(ValuesCount), EncodedValues],
191+
{1, Values2}.

src/marina_types.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,10 @@ encode_list(Values) ->
160160
encode_long(Value) ->
161161
<<Value:64/signed>>.
162162

163-
-spec encode_long_string(binary()) -> binary().
163+
-spec encode_long_string(binary()) -> iodata().
164164

165165
encode_long_string(Value) ->
166-
<<(encode_int(size(Value)))/binary, Value/binary>>.
166+
[encode_int(size(Value)), Value].
167167

168168
-spec encode_short(integer()) -> binary().
169169
encode_short(Value) ->

src/marina_utils.erl

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
]).
1818

1919
%% public
20-
-spec authenticate(inet:socket()) ->
20+
-spec authenticate(shackle:socket()) ->
2121
ok | {error, atom()}.
2222

2323
authenticate(Socket) ->
@@ -103,18 +103,18 @@ server_to_pool(Node) ->
103103
PoolBin = erlang:iolist_to_binary(lists:join(<<"_">>, PoolSplit)),
104104
erlang:binary_to_atom(PoolBin).
105105

106-
-spec sync_msg(inet:socket(), iodata()) ->
106+
-spec sync_msg(shackle:socket(), iodata()) ->
107107
{ok, term()} | {error, term()}.
108108

109109
sync_msg(Socket, Msg) ->
110-
case gen_tcp:send(Socket, Msg) of
110+
case sock_send(Socket, Msg) of
111111
ok ->
112112
rcv_buf(Socket, <<>>);
113113
{error, Reason} ->
114114
{error, Reason}
115115
end.
116116

117-
-spec startup(inet:socket()) ->
117+
-spec startup(shackle:socket()) ->
118118
{ok, binary() | undefined} | {error, atom()}.
119119

120120
startup(Socket) ->
@@ -140,7 +140,7 @@ timeout(Timeout, Timestamp) ->
140140
Diff = timer:now_diff(os:timestamp(), Timestamp) div 1000,
141141
Timeout - Diff.
142142

143-
-spec use_keyspace(inet:socket()) ->
143+
-spec use_keyspace(shackle:socket()) ->
144144
ok | {error, atom()}.
145145

146146
use_keyspace(Socket) ->
@@ -164,7 +164,7 @@ authenticate(Username, Password, Socket) when is_binary(Username),
164164
end.
165165

166166
rcv_buf(Socket, Buffer) ->
167-
case gen_tcp:recv(Socket, 0, ?DEFAULT_RECV_TIMEOUT) of
167+
case sock_recv(Socket) of
168168
{ok, Msg} ->
169169
Buffer2 = <<Buffer/binary, Msg/binary>>,
170170
case marina_frame:decode(Buffer2) of
@@ -177,6 +177,16 @@ rcv_buf(Socket, Buffer) ->
177177
{error, Reason}
178178
end.
179179

180+
sock_recv(Socket) when is_port(Socket) ->
181+
gen_tcp:recv(Socket, 0, ?DEFAULT_RECV_TIMEOUT);
182+
sock_recv(Socket) ->
183+
socket:recv(Socket, 0, ?DEFAULT_RECV_TIMEOUT).
184+
185+
sock_send(Socket, Msg) when is_port(Socket) ->
186+
gen_tcp:send(Socket, Msg);
187+
sock_send(Socket, Msg) ->
188+
socket:send(Socket, Msg).
189+
180190
use_keyspace(undefined, _Socket) ->
181191
ok;
182192
use_keyspace(Keyspace, Socket) when is_binary(Keyspace)->

0 commit comments

Comments
 (0)