From a742ce1d321de204f0f70c61f83bc08af56cf4f1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 May 2024 22:40:27 +0200 Subject: [PATCH] Optimize `FileReadStream` seeking if new position is within the cached buffer --- .../Engine/Serialization/FileReadStream.cpp | 41 ++++++++++++++++++- Source/Engine/Serialization/FileReadStream.h | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Serialization/FileReadStream.cpp b/Source/Engine/Serialization/FileReadStream.cpp index c542c9490..4aaee55cc 100644 --- a/Source/Engine/Serialization/FileReadStream.cpp +++ b/Source/Engine/Serialization/FileReadStream.cpp @@ -4,6 +4,8 @@ #include "Engine/Core/Log.h" #include "Engine/Platform/File.h" +#define USE_FILE_POS (1) + FileReadStream* FileReadStream::Open(const StringView& path) { const auto file = File::Open(path, FileMode::OpenExisting, FileAccess::Read, FileShare::Read); @@ -24,8 +26,12 @@ FileReadStream::FileReadStream(File* file) : _file(file) , _virtualPosInBuffer(0) , _bufferSize(0) +#if USE_FILE_POS + , _filePosition(file->GetPosition()) +#else + , _filePosition(0) +#endif { - ASSERT_LOW_LAYER(_file); } FileReadStream::~FileReadStream() @@ -62,16 +68,40 @@ uint32 FileReadStream::GetLength() uint32 FileReadStream::GetPosition() { +#if USE_FILE_POS + return _filePosition - _bufferSize + _virtualPosInBuffer; +#else return _file->GetPosition() - _bufferSize + _virtualPosInBuffer; +#endif } void FileReadStream::SetPosition(uint32 seek) { +#if USE_FILE_POS + // Skip if position won't change + if (GetPosition() == seek) + { + return; + } + + // Try to seek with virtual position + uint32 bufferStartPos = _filePosition - _bufferSize; + if (seek >= GetPosition() && seek < _filePosition) + { + _virtualPosInBuffer = seek - bufferStartPos; + return; + } +#endif + // Seek _file->SetPosition(seek); + _filePosition = _file->GetPosition(); // Update buffer _hasError |= _file->Read(_buffer, FILESTREAM_BUFFER_SIZE, &_bufferSize) != 0; +#if USE_FILE_POS + _filePosition += _bufferSize; +#endif _virtualPosInBuffer = 0; } @@ -88,6 +118,9 @@ void FileReadStream::ReadBytes(void* data, uint32 bytes) { CHECK(_virtualPosInBuffer == 0); _hasError |= _file->Read(_buffer, FILESTREAM_BUFFER_SIZE, &_bufferSize) != 0; +#if USE_FILE_POS + _filePosition += _bufferSize; +#endif } // Check if buffer has enough data for this read @@ -107,6 +140,9 @@ void FileReadStream::ReadBytes(void* data, uint32 bytes) bytes -= bufferBytesLeft; _virtualPosInBuffer = 0; _hasError |= _file->Read(_buffer, FILESTREAM_BUFFER_SIZE, &_bufferSize) != 0; +#if USE_FILE_POS + _filePosition += _bufferSize; +#endif } // Read as much as can using whole buffer @@ -116,6 +152,9 @@ void FileReadStream::ReadBytes(void* data, uint32 bytes) data = (byte*)data + FILESTREAM_BUFFER_SIZE; bytes -= FILESTREAM_BUFFER_SIZE; _hasError |= _file->Read(_buffer, FILESTREAM_BUFFER_SIZE, &_bufferSize) != 0; +#if USE_FILE_POS + _filePosition += _bufferSize; +#endif } // Read the rest of the buffer but without flushing its data diff --git a/Source/Engine/Serialization/FileReadStream.h b/Source/Engine/Serialization/FileReadStream.h index c5a9c22c7..ff88efcc1 100644 --- a/Source/Engine/Serialization/FileReadStream.h +++ b/Source/Engine/Serialization/FileReadStream.h @@ -15,6 +15,7 @@ private: File* _file; uint32 _virtualPosInBuffer; // Current position in the buffer (index) uint32 _bufferSize; // Amount of loaded bytes from the file to the buffer + uint32 _filePosition; // Cached position in the file (native) byte _buffer[FILESTREAM_BUFFER_SIZE]; public: