Skip to content

Commit 79a1d39

Browse files
committed
Optimise read planning.
Previously we had to do do a linear search through the list of segment reference to find which file to read a given entry from. This commit introduced a new module `ra_lol` which is a "list of list" type of ordered data structure that replaces the use of a plain list. ra_log keeps data in a list of 64 entry sized "rows" which subtantially reduces the amount of work needed to find a given segment ref as we first scan each row to find the row with the segref in then we can the fixed size row. Even a server with 4096 segment only need to scan at most 128 to find any given entry. This commit also fixes a few issues in segref compaction and changes the type of the segment ref to a {ra_range:range(), filename()} to work better with the ra_range module.
1 parent c8dbe23 commit 79a1d39

8 files changed

+503
-192
lines changed

Diff for: src/ra_log.erl

+15-9
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@
6464
-define(WAL_RESEND_TIMEOUT, 5000).
6565

6666
-type ra_meta_key() :: atom().
67-
-type segment_ref() :: {From :: ra_index(), To :: ra_index(),
68-
File :: file:filename_all()}.
67+
-type segment_ref() :: {ra_range:range(), File :: file:filename_all()}.
6968
-type event_body() :: {written, ra_term(), ra:range()} |
7069
{segments, [{ets:tid(), ra:range()}], [segment_ref()]} |
7170
{resend_write, ra_index()} |
@@ -279,7 +278,7 @@ init(#{uid := UId,
279278
LastSegRefIdx = case SegRefs of
280279
[] ->
281280
-1;
282-
[{_, L, _} | _] ->
281+
[{{_, L}, _} | _] ->
283282
L
284283
end,
285284
LastWrittenIdx = case ra_log_wal:last_writer_seq(Wal, UId) of
@@ -969,8 +968,14 @@ should_snapshot(snapshot, Idx,
969968
% We should take a snapshot if the new snapshot index would allow us
970969
% to discard any segments or if the we've handled enough commands
971970
% since the last snapshot.
972-
CanFreeSegments = lists:any(fun({_, To, _}) -> To =< Idx end,
973-
ra_log_reader:segment_refs(Reader)),
971+
CanFreeSegments = case ra_log_reader:range(Reader) of
972+
undefined ->
973+
false;
974+
{Start, _End} ->
975+
%% this isn't 100% guaranteed to free a segment
976+
%% but there is a good chance
977+
Idx > Start
978+
end,
974979
CanFreeSegments orelse Idx > SnapLimit;
975980
should_snapshot(checkpoint, Idx,
976981
#?MODULE{cfg = #cfg{min_checkpoint_interval = CheckpointInter},
@@ -1029,7 +1034,8 @@ overview(#?MODULE{last_index = LastIndex,
10291034
last_term => LastTerm,
10301035
first_index => FirstIndex,
10311036
last_written_index_term => LWIT,
1032-
num_segments => length(ra_log_reader:segment_refs(Reader)),
1037+
num_segments => ra_log_reader:segment_ref_count(Reader),
1038+
segments_range => ra_log_reader:range(Reader),
10331039
open_segments => ra_log_reader:num_open_segments(Reader),
10341040
snapshot_index => case CurrSnap of
10351041
undefined -> undefined;
@@ -1166,9 +1172,9 @@ delete_segments(SnapIdx, #?MODULE{cfg = #cfg{log_id = LogId,
11661172
ok = ra_log_segment_writer:truncate_segments(SegWriter,
11671173
UId, Pivot)
11681174
end),
1169-
Active = ra_log_reader:segment_refs(Reader),
1175+
NumActive = ra_log_reader:segment_ref_count(Reader),
11701176
?DEBUG("~ts: ~b obsolete segments at ~b - remaining: ~b, pivot ~0p",
1171-
[LogId, length(Obsolete), SnapIdx, length(Active), Pivot]),
1177+
[LogId, length(Obsolete), SnapIdx, NumActive, Pivot]),
11721178
State = State0#?MODULE{reader = Reader},
11731179
{State, log_update_effects(Readers, Pid, State)}
11741180
end.
@@ -1331,7 +1337,7 @@ recover_ranges(UId, MtRange, SegWriter) ->
13311337
[SegRef | Acc]
13321338
end
13331339
end, [], SegFiles),
1334-
SegRanges = [{F, L} || {F, L, _} <- SegRefs],
1340+
SegRanges = [Range || {Range, _} <- SegRefs],
13351341
Ranges = [MtRange | SegRanges],
13361342
{pick_range(Ranges, undefined), SegRefs}.
13371343

0 commit comments

Comments
 (0)