Skip to content

Commit

Permalink
issue-852: detecting sequential access pattern and caching results no…
Browse files Browse the repository at this point in the history
…t only per node but per handle as well (#1029)

* issue-852: detecting sequential access pattern and caching results not only per node but per handle as well

* issue-852: detecting sequential access pattern and caching results not only per node but per handle as well - improved ut
  • Loading branch information
qkrorlqr authored Apr 23, 2024
1 parent f837d7c commit 46405e1
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 37 deletions.
86 changes: 70 additions & 16 deletions cloud/filestore/libs/storage/tablet/model/read_ahead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ namespace {

////////////////////////////////////////////////////////////////////////////////

constexpr ui64 NoHandle = Max<ui64>();

////////////////////////////////////////////////////////////////////////////////

bool IsCloseToSequential(
const TRingBuffer<TReadAheadCache::TRange>& byteRanges,
ui32 maxGapPercentage)
Expand Down Expand Up @@ -69,8 +73,11 @@ void TReadAheadCache::Reset(
NodeStates.clear();
}

bool TReadAheadCache::TryFillResult(
////////////////////////////////////////////////////////////////////////////////

bool TReadAheadCache::TryFillResultImpl(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
NProtoPrivate::TDescribeDataResponse* response)
{
Expand All @@ -79,8 +86,13 @@ bool TReadAheadCache::TryFillResult(
return false;
}

for (ui32 i = 0; i < nodeState->DescribeResults.Size(); ++i) {
const auto& result = nodeState->DescribeResults.Back(i);
auto* handleState = nodeState->HandleStates.FindPtr(handle);
if (!handleState) {
return false;
}

for (ui32 i = 0; i < handleState->DescribeResults.Size(); ++i) {
const auto& result = handleState->DescribeResults.Back(i);
if (result.Range.Contains(range)) {
FilterResult(range, result.Response, response);
return true;
Expand All @@ -90,17 +102,29 @@ bool TReadAheadCache::TryFillResult(
return false;
}

TMaybe<TByteRange> TReadAheadCache::RegisterDescribe(
bool TReadAheadCache::TryFillResult(
ui64 nodeId,
const TByteRange inputRange)
ui64 handle,
const TByteRange& range,
NProtoPrivate::TDescribeDataResponse* response)
{
if (!RangeSize) {
return {};
if (TryFillResultImpl(nodeId, handle, range, response)) {
return true;
}

auto& nodeState = Access(nodeId);
nodeState.LastRanges.PushBack(TRange(inputRange));
if (IsCloseToSequential(nodeState.LastRanges, MaxGapPercentage)
return TryFillResultImpl(nodeId, NoHandle, range, response);
}

////////////////////////////////////////////////////////////////////////////////

TMaybe<TByteRange> TReadAheadCache::RegisterDescribeImpl(
ui64 nodeId,
ui64 handle,
const TByteRange inputRange)
{
auto& handleState = Access(nodeId, handle);
handleState.LastRanges.PushBack(TRange(inputRange));
if (IsCloseToSequential(handleState.LastRanges, MaxGapPercentage)
&& inputRange.Length < RangeSize)
{
return TByteRange(inputRange.Offset, RangeSize, inputRange.BlockSize);
Expand All @@ -109,32 +133,62 @@ TMaybe<TByteRange> TReadAheadCache::RegisterDescribe(
return {};
}

TMaybe<TByteRange> TReadAheadCache::RegisterDescribe(
ui64 nodeId,
ui64 handle,
const TByteRange inputRange)
{
if (!RangeSize) {
return {};
}

auto result = RegisterDescribeImpl(nodeId, handle, inputRange);
if (result) {
return result;
}

return RegisterDescribeImpl(nodeId, NoHandle, inputRange);
}

////////////////////////////////////////////////////////////////////////////////

void TReadAheadCache::InvalidateCache(ui64 nodeId)
{
NodeStates.clear(nodeId);
}

void TReadAheadCache::OnDestroyHandle(ui64 nodeId, ui64 handle)
{
if (auto* nodeState = NodeStates.FindPtr(nodeId)) {
nodeState->HandleStates.erase(handle);
}
}

////////////////////////////////////////////////////////////////////////////////

void TReadAheadCache::RegisterResult(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
const NProtoPrivate::TDescribeDataResponse& result)
{
Access(nodeId).DescribeResults.PushBack({TRange(range), result});
Access(nodeId, handle).DescribeResults.PushBack({TRange(range), result});
Access(nodeId, NoHandle).DescribeResults.PushBack({TRange(range), result});
}

TReadAheadCache::TNodeState& TReadAheadCache::Access(ui64 nodeId)
TReadAheadCache::THandleState& TReadAheadCache::Access(ui64 nodeId, ui64 handle)
{
// TODO: LRU eviction
if (NodeStates.size() >= MaxNodes && !NodeStates.contains(nodeId)) {
NodeStates.clear();
}

auto& nodeState = NodeStates[nodeId];
if (!nodeState.DescribeResults.Capacity()) {
nodeState.DescribeResults.Reset(MaxResultsPerNode);
auto& handleState = NodeStates[nodeId].HandleStates[handle];
if (!handleState.DescribeResults.Capacity()) {
handleState.DescribeResults.Reset(MaxResultsPerNode);
}

return nodeState;
return handleState;
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
34 changes: 30 additions & 4 deletions cloud/filestore/libs/storage/tablet/model/read_ahead.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,24 @@ class TReadAheadCache
using TDescribeResults = TRingBuffer<TDescribeResult>;
using TByteRanges = TRingBuffer<TRange>;

struct TNodeState
struct THandleState
{
static const ui32 RANGE_COUNT = 32;
TByteRanges LastRanges;
TDescribeResults DescribeResults;

TNodeState()
THandleState()
: LastRanges(RANGE_COUNT)
, DescribeResults(0)
{
}
};

struct TNodeState
{
THashMap<ui64, THandleState> HandleStates;
};

using TNodeStates = THashMap<ui64, TNodeState>;

private:
Expand All @@ -88,7 +93,7 @@ class TReadAheadCache
ui32 MaxGapPercentage = 0;

public:
TReadAheadCache(IAllocator* allocator);
explicit TReadAheadCache(IAllocator* allocator);
~TReadAheadCache();

void Reset(
Expand All @@ -99,16 +104,20 @@ class TReadAheadCache

bool TryFillResult(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
NProtoPrivate::TDescribeDataResponse* response);

// returns the suggested range to describe
TMaybe<TByteRange> RegisterDescribe(
ui64 nodeId,
ui64 handle,
const TByteRange inputRange);
void InvalidateCache(ui64 nodeId);
void OnDestroyHandle(ui64 nodeId, ui64 handle);
void RegisterResult(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
const NProtoPrivate::TDescribeDataResponse& result);

Expand All @@ -118,7 +127,24 @@ class TReadAheadCache
}

private:
TNodeState& Access(ui64 nodeId);
THandleState& Access(ui64 nodeId, ui64 handle);

bool TryFillResultImpl(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
NProtoPrivate::TDescribeDataResponse* response);

TMaybe<TByteRange> RegisterDescribeImpl(
ui64 nodeId,
ui64 handle,
const TByteRange inputRange);

void RegisterResultImpl(
ui64 nodeId,
ui64 handle,
const TByteRange& range,
const NProtoPrivate::TDescribeDataResponse& result);
};

////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit 46405e1

Please sign in to comment.