diff options
author | Adam Kocoloski <kocolosk@apache.org> | 2019-12-18 15:22:18 -0500 |
---|---|---|
committer | Adam Kocoloski <kocolosk@apache.org> | 2020-01-06 13:12:55 -0500 |
commit | e641a740978447f0b29785580e46d2e30e822001 (patch) | |
tree | 793d73b5ae478a6248d055b18926e6cd85c46918 | |
parent | 04bebb3f99b2045da0deb090afb4e6c4eacb67f5 (diff) | |
download | couchdb-e641a740978447f0b29785580e46d2e30e822001.tar.gz |
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.
-rw-r--r-- | src/ioq.erl | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/src/ioq.erl b/src/ioq.erl index 9ca26567a..81d94a36f 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 |