From 6028e85fa9fee0ba5527fa0c62dfacdd2436cd87 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 7 Jun 2021 01:47:11 -0400 Subject: [PATCH] Avoid `ftell()` calls by `pfSizedStream`. According to profiling, calls to `ftell()` when reading creatables is the largest time sink when reading PRPs. On a trivial test with two iterations of loading Garrison, the results are thus: Before: 68.68s (34.34s avg) After: 7.68s (3.84s avg) --- core/Stream/pfSizedStream.cpp | 24 +++++++++++++++--------- core/Stream/pfSizedStream.h | 7 ++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/Stream/pfSizedStream.cpp b/core/Stream/pfSizedStream.cpp index 44063b1c9..17a5bd79d 100644 --- a/core/Stream/pfSizedStream.cpp +++ b/core/Stream/pfSizedStream.cpp @@ -18,7 +18,7 @@ #include "Debug/plDebug.h" pfSizedStream::pfSizedStream(hsStream* S, uint32_t len) - : fBase(S), fLength(len) + : fBase(S), fLength(len), fPos() { if (S) { ver = S->getVer(); @@ -41,37 +41,43 @@ void pfSizedStream::seek(uint32_t pos) } fBase->seek(fBegin + pos); + fPos = std::min(pos, fLength); } void pfSizedStream::skip(int32_t count) { - if (pos() + count > fLength) { // pos() is the index in the sub-stream + if (fPos + count > fLength) { // fPos is the index in the sub-stream throw hsFileReadException(__FILE__, __LINE__, ST::format("Seek out of range: {} bytes requested, {} available", - count, (fLength - pos())).c_str()); + count, (fLength - fPos)).c_str()); } fBase->skip(count); + fPos += count; } size_t pfSizedStream::read(size_t size, void* buf) { - if (pos() + size > fLength) { // pos() is the index in the sub-stream + if (fPos + size > fLength) { // fPos is the index in the sub-stream throw hsFileReadException(__FILE__, __LINE__, ST::format("Read past end of sized stream: {} bytes requested, {} available", - size, (fLength - pos())).c_str()); + size, (fLength - fPos)).c_str()); } - return fBase->read(size, buf); + size_t nread = fBase->read(size, buf); + fPos += nread; + return nread; } size_t pfSizedStream::write(size_t size, const void* buf) { - if (pos() + size > fLength) { // pos() is the index in the sub-stream + if (fPos + size > fLength) { // fPos is the index in the sub-stream throw hsFileReadException(__FILE__, __LINE__, ST::format("Write past end of sized stream: {} bytes requested, {} available", - size, (fLength - pos())).c_str()); + size, (fLength - fPos)).c_str()); } - return fBase->write(size, buf); + size_t nwrite = fBase->write(size, buf); + fPos += nwrite; + return nwrite; } diff --git a/core/Stream/pfSizedStream.h b/core/Stream/pfSizedStream.h index 248f0c605..a0e5cb50d 100644 --- a/core/Stream/pfSizedStream.h +++ b/core/Stream/pfSizedStream.h @@ -19,20 +19,21 @@ #include "hsStream.h" -class PLASMA_DLL pfSizedStream : public hsStream +class PLASMA_DLL pfSizedStream HS_FINAL : public hsStream { private: hsStream* fBase; uint32_t fLength; //!< the length of the substream - not the end position of it! uint32_t fBegin; + uint32_t fPos; public: pfSizedStream(hsStream* S, uint32_t len); ~pfSizedStream() { } // Do NOT free fBase!!! uint32_t size() const HS_OVERRIDE { return fLength; } - uint32_t pos() const HS_OVERRIDE { return fBase->pos() - fBegin; } - bool eof() const HS_OVERRIDE { return fBase->eof() || pos() == fLength; } + uint32_t pos() const HS_OVERRIDE { return fPos; } + bool eof() const HS_OVERRIDE { return fPos == fLength || fBase->eof(); } void seek(uint32_t pos) HS_OVERRIDE; void skip(int32_t count) HS_OVERRIDE;