From fb602ec0c938db5075a56e48fee9c9c7efb9ab6f Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 May 2021 15:23:52 +0200 Subject: [PATCH 1/2] Fix allocator mismatch in SawyerChunk on Windows with Debug This change allows to use HeapReAlloc in FinaliseLargeTempBuffer when running Debug builds. --- src/openrct2/rct12/SawyerChunk.cpp | 5 +++-- src/openrct2/rct12/SawyerChunkReader.cpp | 11 +++++++---- src/openrct2/rct12/SawyerChunkReader.h | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/openrct2/rct12/SawyerChunk.cpp b/src/openrct2/rct12/SawyerChunk.cpp index b5db22a579..6873c94924 100644 --- a/src/openrct2/rct12/SawyerChunk.cpp +++ b/src/openrct2/rct12/SawyerChunk.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -10,6 +10,7 @@ #include "SawyerChunk.h" #include "../core/Memory.hpp" +#include "SawyerChunkReader.h" SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, void* data, size_t length) { @@ -20,5 +21,5 @@ SawyerChunk::SawyerChunk(SAWYER_ENCODING encoding, void* data, size_t length) SawyerChunk::~SawyerChunk() { - Memory::Free(_data); + SawyerChunkReader::FreeChunk(_data); } diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index f1bf44933f..4f584130ae 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -158,6 +158,11 @@ void SawyerChunkReader::ReadChunk(void* dst, size_t length) } } +void SawyerChunkReader::FreeChunk(void* data) +{ + FreeLargeTempBuffer(data); +} + size_t SawyerChunkReader::DecodeChunk(void* dst, size_t dstCapacity, const void* src, const sawyercoding_chunk_header& header) { size_t resultLength; @@ -315,9 +320,7 @@ void* SawyerChunkReader::AllocateLargeTempBuffer() void* SawyerChunkReader::FinaliseLargeTempBuffer(void* buffer, size_t len) { #ifdef __USE_HEAP_ALLOC__ - auto finalBuffer = std::malloc(len); - std::memcpy(finalBuffer, buffer, len); - HeapFree(GetProcessHeap(), 0, buffer); + auto finalBuffer = HeapReAlloc(GetProcessHeap(), 0, buffer, len); #else auto finalBuffer = static_cast(std::realloc(buffer, len)); #endif diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 8fb370b25e..9d68f55726 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers + * Copyright (c) 2014-2021 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -84,6 +84,11 @@ public: return result; } + /** + * Frees the chunk data, to be used when destructing SawyerChunks + */ + static void FreeChunk(void* data); + private: static size_t DecodeChunk(void* dst, size_t dstCapacity, const void* src, const sawyercoding_chunk_header& header); static size_t DecodeChunkRLERepeat(void* dst, size_t dstCapacity, const void* src, size_t srcLength); From 66abc696908cd3bfb8f51a40e65d5b07bef6fec7 Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 May 2021 15:26:59 +0200 Subject: [PATCH 2/2] Add a persistentChunks flag to SawyerChunkReader New behaviour of SawyerChunkReader is to skip shrinking the chunk memory unless persistentChunks is set to true. At the moment all uses of SawyerChunks created by the reader are temporary and shrinking memory right before freeing them is a waste of time. Speeds up loading times and index building --- distribution/changelog.txt | 2 +- src/openrct2/rct12/SawyerChunkReader.cpp | 13 ++++++++++--- src/openrct2/rct12/SawyerChunkReader.h | 6 ++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 88d71712d7..5f70d38fb5 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -21,7 +21,7 @@ - Fix: [#14604] American-style Steam Trains are not imported correctly from RCT1 saves. - Fix: [#14638] The “About OpenRCT2” window cannot be themed. - Fix: [#14710] Ride/Track Design preview does not show if it costs more money than available. -- Improved: [#14712]: Improve startup times. +- Improved: [#14712, #14716]: Improve startup times. 0.3.3 (2021-03-13) ------------------------------------------------------------------------ diff --git a/src/openrct2/rct12/SawyerChunkReader.cpp b/src/openrct2/rct12/SawyerChunkReader.cpp index 4f584130ae..cf03dfdc5b 100644 --- a/src/openrct2/rct12/SawyerChunkReader.cpp +++ b/src/openrct2/rct12/SawyerChunkReader.cpp @@ -27,8 +27,9 @@ constexpr const char* EXCEPTION_MSG_DESTINATION_TOO_SMALL = "Chunk data larger t constexpr const char* EXCEPTION_MSG_INVALID_CHUNK_ENCODING = "Invalid chunk encoding."; constexpr const char* EXCEPTION_MSG_ZERO_SIZED_CHUNK = "Encountered zero-sized chunk."; -SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream) +SawyerChunkReader::SawyerChunkReader(OpenRCT2::IStream* stream, bool persistentChunks) : _stream(stream) + , _createsPersistentChunks(persistentChunks) { } @@ -78,7 +79,10 @@ std::shared_ptr SawyerChunkReader::ReadChunk() { throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); } - buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + if (_createsPersistentChunks) + { + buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + } return std::make_shared( static_cast(header.encoding), buffer, uncompressedLength); } @@ -126,7 +130,10 @@ std::shared_ptr SawyerChunkReader::ReadChunkTrack() { throw SawyerChunkException(EXCEPTION_MSG_ZERO_SIZED_CHUNK); } - buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + if (_createsPersistentChunks) + { + buffer = static_cast(FinaliseLargeTempBuffer(buffer, uncompressedLength)); + } return std::make_shared(SAWYER_ENCODING::RLE, buffer, uncompressedLength); } catch (const std::exception&) diff --git a/src/openrct2/rct12/SawyerChunkReader.h b/src/openrct2/rct12/SawyerChunkReader.h index 9d68f55726..0873c8b845 100644 --- a/src/openrct2/rct12/SawyerChunkReader.h +++ b/src/openrct2/rct12/SawyerChunkReader.h @@ -36,15 +36,17 @@ namespace OpenRCT2 /** * Reads sawyer encoding chunks from a data stream. This can be used to read - * SC6, SV6 and RCT2 objects. + * SC6, SV6 and RCT2 objects. persistentChunks is a hint to the reader that the chunk will be preserved, + * and thus the chunk memory should be shrunk. */ class SawyerChunkReader final { private: OpenRCT2::IStream* const _stream = nullptr; + const bool _createsPersistentChunks = false; public: - explicit SawyerChunkReader(OpenRCT2::IStream* stream); + explicit SawyerChunkReader(OpenRCT2::IStream* stream, bool persistentChunks = false); /** * Skips the next chunk in the stream without decoding or reading its data