Skip to content

Commit 154fa6f

Browse files
committed
Optimise msg_store recovery in case of large message file
Since 4.0.0 (commit d45fbc3) the shared message store writes large messages into their own rdq files. This information can be utilised when scanning rdq files during recovery to avoid reading in the whole message body into memory unnecessarily. This commit addresses the same issue that was addressed in 3.13.x by commit baeefbe (ie. appending a large binary together from 4MB chunks leaves a lot of garbage and memory fragmentation behind) but even more efficiently. Large messages which were written before 4.0.0, which don't fully fill the rdq file, are still handled as before.
1 parent c5867a7 commit 154fa6f

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

deps/rabbit/src/rabbit_msg_store.erl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,39 @@ scan_data(<<Size:64, MsgIdAndMsg:Size/binary, 255, Rest/bits>> = Data,
15371537
scan_data(Rest2, Fd, Fun, Offset + 1, FileSize, MsgIdsFound, Acc)
15381538
end
15391539
end;
1540+
%% Large message alone in its own file
1541+
scan_data(<<Size:64, MsgIdInt:128, _Rest/bits>> = Data, Fd, Fun, Offset, FileSize, _MsgIdsFound, _Acc)
1542+
when Size >= ?LARGE_MESSAGE_THRESHOLD + 16,
1543+
Offset == 0,
1544+
FileSize == Size + 9 ->
1545+
{ok, CurrentPos} = file:position(Fd, cur),
1546+
case file:pread(Fd, FileSize - 1, 1) of
1547+
{ok, <<255>>} ->
1548+
%% Avoid sub-binary construction.
1549+
MsgId = <<MsgIdInt:128>>,
1550+
TotalSize = FileSize,
1551+
case Fun({MsgId, TotalSize, Offset}) of
1552+
%% Confirmed to be a message by the provided fun.
1553+
{valid, Entry} ->
1554+
[Entry];
1555+
%% Confirmed to be a message but we don't need it anymore.
1556+
previously_valid ->
1557+
[];
1558+
%% Not a message, try the next byte.
1559+
invalid ->
1560+
{ok, _} = file:position(Fd, CurrentPos),
1561+
<<_, Rest2/bits>> = Data,
1562+
scan_data(Rest2, Fd, Fun, Offset + 1, FileSize, #{}, [])
1563+
end;
1564+
_ ->
1565+
%% It is quite unexpected that FileSize matches the
1566+
%% expected Size but the end marker is wrong.
1567+
%% There is no compaction in case of large message files
1568+
%% so it can only happen with byte corruption?
1569+
<<_, Rest2/bits>> = Data,
1570+
{ok, _} = file:position(Fd, CurrentPos),
1571+
scan_data(Rest2, Fd, Fun, Offset + 1, FileSize, #{}, [])
1572+
end;
15401573
%% This might be the start of a message.
15411574
scan_data(<<Size:64, Rest/bits>> = Data, Fd, Fun, Offset, FileSize, MsgIdsFound, Acc)
15421575
when byte_size(Rest) < Size + 1, Size < FileSize - Offset ->

0 commit comments

Comments
 (0)