Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions io/io/inc/ROOT/RRawFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ protected:
/// By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX implementations
virtual void ReadVImpl(RIOVec *ioVec, unsigned int nReq);

// Default implementation: no-op
virtual void SetDiscourageReadAheadImpl(bool /* value */) {}

/// Open the file if not already open. Otherwise noop.
void EnsureOpen();

Expand Down Expand Up @@ -178,8 +181,9 @@ public:
/// Returns the limits regarding the ioVec input to ReadV for this specific file; may open the file as a side-effect.
virtual RIOVecLimits GetReadVLimits() { return RIOVecLimits(); }

/// Turn off buffered reads; all scalar read requests go directly to the implementation. Buffering can be turned
/// back on.
/// Turn on/off buffered reads; if off, all scalar read requests go directly to the implementation. Buffering also
/// turns on and off OS read-ahead where supported: if buffering is switched, SetDiscourageReadAheadImpl() will be
/// called accordingly.
void SetBuffering(bool value);
bool IsBuffering() const { return fIsBuffering; }

Expand Down
1 change: 1 addition & 0 deletions io/io/inc/ROOT/RRawFileUnix.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ protected:
size_t ReadAtImpl(void *buffer, size_t nbytes, std::uint64_t offset) final;
void ReadVImpl(RIOVec *ioVec, unsigned int nReq) final;
std::uint64_t GetSizeImpl() final;
void SetDiscourageReadAheadImpl(bool value) final;

public:
RRawFileUnix(std::string_view url, RRawFile::ROptions options);
Expand Down
3 changes: 3 additions & 0 deletions io/io/src/RRawFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void ROOT::Internal::RRawFile::EnsureOpen()

OpenImpl();
fIsOpen = true;
SetDiscourageReadAheadImpl(!fIsBuffering);
}

void ROOT::Internal::RRawFile::ReadVImpl(RIOVec *ioVec, unsigned int nReq)
Expand Down Expand Up @@ -200,6 +201,8 @@ void ROOT::Internal::RRawFile::SetBuffering(bool value)
fIsBuffering = value;
if (!fIsBuffering)
fBufferSpace.reset();
if (fIsOpen)
SetDiscourageReadAheadImpl(!fIsBuffering);
}

bool ROOT::Internal::RRawFile::Readln(std::string &line)
Expand Down
9 changes: 9 additions & 0 deletions io/io/src/RRawFileUnix.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ void ROOT::Internal::RRawFileUnix::OpenImpl()
}
}

void ROOT::Internal::RRawFileUnix::SetDiscourageReadAheadImpl(bool value)
{
#ifndef __APPLE__
posix_fadvise(fFileDes, 0, 0, value ? POSIX_FADV_RANDOM : POSIX_FADV_SEQUENTIAL);
#else
(void)value;
#endif
}

void ROOT::Internal::RRawFileUnix::ReadVImpl(RIOVec *ioVec, unsigned int nReq)
{
#ifdef R__HAS_URING
Expand Down
22 changes: 22 additions & 0 deletions io/io/test/RRawFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class RRawFileMock : public RRawFile {
public:
std::string fContent;
unsigned fNumReadAt;
bool fDiscourageReadAhead = false;

RRawFileMock(const std::string &content, RRawFile::ROptions options)
: RRawFile("", options), fContent(content), fNumReadAt(0) { }
Expand All @@ -39,6 +40,8 @@ class RRawFileMock : public RRawFile {
}

std::uint64_t GetSizeImpl() final { return fContent.size(); }

void SetDiscourageReadAheadImpl(bool val) final { fDiscourageReadAhead = val; }
};

} // anonymous namespace
Expand Down Expand Up @@ -272,3 +275,22 @@ TEST(RRawFileTFile, TFile)
EXPECT_EQ(seek[2], 0);
EXPECT_EQ(seek[3], 100);
}

TEST(RRawFile, Readahead)
{
{
RRawFileMock mock("", ROOT::Internal::RRawFile::ROptions());
(void)mock.GetSize();
EXPECT_FALSE(mock.fDiscourageReadAhead);
}

{
RRawFileMock mock("", ROOT::Internal::RRawFile::ROptions());
mock.SetBuffering(false);
EXPECT_FALSE(mock.fDiscourageReadAhead);
(void)mock.GetSize();
EXPECT_TRUE(mock.fDiscourageReadAhead);
mock.SetBuffering(true);
EXPECT_FALSE(mock.fDiscourageReadAhead);
}
}
Loading