You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ko...@apache.org on 2020/01/06 18:27:17 UTC
[couchdb] 17/19: Enable users to bypass IOQ for certain IO classes
This is an automated email from the ASF dual-hosted git repository.
kocolosk pushed a commit to branch ioq-in-tree
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit e641a740978447f0b29785580e46d2e30e822001
Author: Adam Kocoloski <ko...@apache.org>
AuthorDate: Wed Dec 18 15:22:18 2019 -0500
Enable users to bypass IOQ for certain IO classes
This patch allows an administrator to configure a "bypass" which
will cause a particular class of IO to be submitted directly to the
file descriptor or OS process instead of going through the IO queueing
mechanism. Installing a bypass can result in higher throughput and
lower latency, at the expense of less control over the stability of the
system.
A bypass is configured via the `ioq.priority` configuration block:
[ioq.bypass]
read = true
write = true
compaction = false
This configuration will cause user-submitted read IO to be submitted
directly. At this time the following classes are available:
- os_process
- read
- write
- view_update
- shard_sync
- compaction
This also expands the "compaction" queue to be a general-purpose
"background" queue that handles IO for both compaction and internal
replication (aka shard_sync). The other four classes are handled by the
"interactive" queue. As before, the [ioq] ratio setting determines the
likelihood that background IO will be selected ahead of interactive IO
when both queues are non-empty.
---
src/ioq.erl | 49 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/src/ioq.erl b/src/ioq.erl
index 9ca2656..81d94a3 100644
--- a/src/ioq.erl
+++ b/src/ioq.erl
@@ -26,7 +26,7 @@
concurrency,
ratio,
interactive=queue:new(),
- compaction=queue:new(),
+ background=queue:new(),
running=[]
}).
@@ -41,7 +41,38 @@
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-call(Fd, Msg, Priority) ->
+call(Fd, Msg, Metadata) ->
+ Priority = io_class(Msg, Metadata),
+ case bypass(Priority) of
+ true ->
+ gen_server:call(Fd, Msg);
+ false ->
+ queued_call(Fd, Msg, Priority)
+ end.
+
+bypass(Priority) ->
+ config:get("ioq.bypass", atom_to_list(Priority)) =:= "true".
+
+io_class({prompt, _}, _) ->
+ os_process;
+io_class({data, _}, _) ->
+ os_process;
+io_class(_, {interactive, _}) ->
+ read;
+io_class(_, {db_update, _}) ->
+ write;
+io_class(_, {view_update, _, _}) ->
+ view_update;
+io_class(_, {internal_repl, _}) ->
+ shard_sync;
+io_class(_, {db_compact, _}) ->
+ compaction;
+io_class(_, {view_compact, _, _}) ->
+ compaction;
+io_class(_, _) ->
+ other.
+
+queued_call(Fd, Msg, Priority) ->
Request = #request{fd=Fd, msg=Msg, priority=Priority, from=self()},
try
gen_server:call(?MODULE, Request, infinity)
@@ -107,10 +138,10 @@ code_change(_Vsn, State, _Extra) ->
terminate(_Reason, _State) ->
ok.
-enqueue_request(#request{priority={db_compact, _}}=Request, #state{}=State) ->
- State#state{compaction=queue:in(Request, State#state.compaction)};
-enqueue_request(#request{priority={view_compact, _, _}}=Request, #state{}=State) ->
- State#state{compaction=queue:in(Request, State#state.compaction)};
+enqueue_request(#request{priority=compaction}=Request, #state{}=State) ->
+ State#state{background=queue:in(Request, State#state.background)};
+enqueue_request(#request{priority=shard_sync}=Request, #state{}=State) ->
+ State#state{background=queue:in(Request, State#state.background)};
enqueue_request(#request{}=Request, #state{}=State) ->
State#state{interactive=queue:in(Request, State#state.interactive)}.
@@ -128,17 +159,17 @@ maybe_submit_request(State) ->
State.
make_next_request(#state{}=State) ->
- case {queue:is_empty(State#state.compaction), queue:is_empty(State#state.interactive)} of
+ case {queue:is_empty(State#state.background), queue:is_empty(State#state.interactive)} of
{true, true} ->
State;
{true, false} ->
choose_next_request(#state.interactive, State);
{false, true} ->
- choose_next_request(#state.compaction, State);
+ choose_next_request(#state.background, State);
{false, false} ->
case couch_rand:uniform() < State#state.ratio of
true ->
- choose_next_request(#state.compaction, State);
+ choose_next_request(#state.background, State);
false ->
choose_next_request(#state.interactive, State)
end