From 0a56b18cfbb583649bdbc7f0a379df5d63ea2880 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 5 Mar 2025 22:02:16 +0100 Subject: [PATCH] Reuse allocations for decompression --- src/BlockDecoder.cpp | 11 +++++------ src/BlockDecoder.h | 3 ++- src/ZlibDecompressor.cpp | 13 +++---------- src/ZlibDecompressor.h | 6 ++++-- src/ZstdDecompressor.cpp | 17 +++++------------ src/ZstdDecompressor.h | 6 ++++-- 6 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/BlockDecoder.cpp b/src/BlockDecoder.cpp index 8f9767c..34644e3 100644 --- a/src/BlockDecoder.cpp +++ b/src/BlockDecoder.cpp @@ -56,13 +56,12 @@ void BlockDecoder::decode(const ustring &datastr) } m_version = version; - ustring datastr2; if (version >= 29) { // decompress whole block at once m_zstd_decompressor.setData(data, length, 1); - datastr2 = m_zstd_decompressor.decompress(); - data = datastr2.c_str(); - length = datastr2.size(); + m_zstd_decompressor.decompress(m_scratch); + data = m_scratch.c_str(); + length = m_scratch.size(); } size_t dataOffset = 0; @@ -115,8 +114,8 @@ void BlockDecoder::decode(const ustring &datastr) // version < 29 ZlibDecompressor decompressor(data, length); decompressor.setSeekPos(dataOffset); - m_mapData = decompressor.decompress(); - decompressor.decompress(); // unused metadata + decompressor.decompress(m_mapData); + decompressor.decompress(m_scratch); // unused metadata dataOffset = decompressor.seekPos(); // Skip unused node timers diff --git a/src/BlockDecoder.h b/src/BlockDecoder.h index eae6e69..0fa2162 100644 --- a/src/BlockDecoder.h +++ b/src/BlockDecoder.h @@ -23,6 +23,7 @@ private: u8 m_version, m_contentWidth; ustring m_mapData; - // one instance for performance + // cached allocations/instances for performance ZstdDecompressor m_zstd_decompressor; + ustring m_scratch; }; diff --git a/src/ZlibDecompressor.cpp b/src/ZlibDecompressor.cpp index 2222ae4..d6b6514 100644 --- a/src/ZlibDecompressor.cpp +++ b/src/ZlibDecompressor.cpp @@ -28,18 +28,13 @@ void ZlibDecompressor::setSeekPos(size_t seekPos) m_seekPos = seekPos; } -size_t ZlibDecompressor::seekPos() const -{ - return m_seekPos; -} - -ustring ZlibDecompressor::decompress() +void ZlibDecompressor::decompress(ustring &buffer) { const unsigned char *data = m_data + m_seekPos; const size_t size = m_size - m_seekPos; - ustring buffer; - constexpr size_t BUFSIZE = 32 * 1024; + // output space is extended in chunks of this size + constexpr size_t BUFSIZE = 8 * 1024; z_stream strm; strm.zalloc = Z_NULL; @@ -73,7 +68,5 @@ ustring ZlibDecompressor::decompress() m_seekPos += strm.next_in - data; buffer.resize(buffer.size() - strm.avail_out); (void) Z(inflateEnd)(&strm); - - return buffer; } diff --git a/src/ZlibDecompressor.h b/src/ZlibDecompressor.h index 03da532..d914895 100644 --- a/src/ZlibDecompressor.h +++ b/src/ZlibDecompressor.h @@ -11,8 +11,10 @@ public: ZlibDecompressor(const u8 *data, size_t size); ~ZlibDecompressor(); void setSeekPos(size_t seekPos); - size_t seekPos() const; - ustring decompress(); + size_t seekPos() const { return m_seekPos; } + // Decompress and return one zlib stream from the buffer + // Advances seekPos as appropriate. + void decompress(ustring &dst); private: const u8 *m_data; diff --git a/src/ZstdDecompressor.cpp b/src/ZstdDecompressor.cpp index 8cdcb68..6e2c62f 100644 --- a/src/ZstdDecompressor.cpp +++ b/src/ZstdDecompressor.cpp @@ -21,18 +21,13 @@ void ZstdDecompressor::setData(const u8 *data, size_t size, size_t seekPos) m_size = size; } -std::size_t ZstdDecompressor::seekPos() const -{ - return m_seekPos; -} - -ustring ZstdDecompressor::decompress() +void ZstdDecompressor::decompress(ustring &buffer) { ZSTD_DStream *stream = reinterpret_cast(m_stream); ZSTD_inBuffer inbuf = { m_data, m_size, m_seekPos }; - ustring buffer; - constexpr size_t BUFSIZE = 32 * 1024; + // output space is extended in chunks of this size + constexpr size_t BUFSIZE = 8 * 1024; buffer.resize(BUFSIZE); ZSTD_outBuffer outbuf = { &buffer[0], buffer.size(), 0 }; @@ -42,17 +37,15 @@ ustring ZstdDecompressor::decompress() size_t ret; do { ret = ZSTD_decompressStream(stream, &outbuf, &inbuf); + if (ret && ZSTD_isError(ret)) + throw DecompressError(); if (outbuf.size == outbuf.pos) { outbuf.size += BUFSIZE; buffer.resize(outbuf.size); outbuf.dst = &buffer[0]; } - if (ret && ZSTD_isError(ret)) - throw DecompressError(); } while (ret != 0); m_seekPos = inbuf.pos; buffer.resize(outbuf.pos); - - return buffer; } diff --git a/src/ZstdDecompressor.h b/src/ZstdDecompressor.h index 861481e..2649617 100644 --- a/src/ZstdDecompressor.h +++ b/src/ZstdDecompressor.h @@ -11,8 +11,10 @@ public: ZstdDecompressor(); ~ZstdDecompressor(); void setData(const u8 *data, size_t size, size_t seekPos); - size_t seekPos() const; - ustring decompress(); + size_t seekPos() const { return m_seekPos; } + // Decompress and return one zstd stream from the buffer + // Advances seekPos as appropriate. + void decompress(ustring &dst); private: void *m_stream; // ZSTD_DStream