[Scummvm-git-logs] scummvm master -> 5636ffb180ff878452fa98041af62722d3ce060a
sev-
sev at scummvm.org
Mon Nov 1 11:15:34 UTC 2021
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7a43994545 CLOUD: Fix Networking::Reader's window logic
5636ffb180 CLOUD: Tweak Networking::Reader pattern-matching logic
Commit: 7a43994545189870b7d6abe87e6156afda83bf00
https://github.com/scummvm/scummvm/commit/7a43994545189870b7d6abe87e6156afda83bf00
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2021-11-01T12:15:27+01:00
Commit Message:
CLOUD: Fix Networking::Reader's window logic
Instead of shifting bytes in the array every time we read 1 byte, Reader now has two "pointers": where it reads from and writes into. This makes the buffer "circular", and removes the unnecessary bytes shifting, which results in increased file upload speed (only for the LAN server; libcurl side stays intact).
Changed paths:
backends/networking/sdl_net/reader.cpp
backends/networking/sdl_net/reader.h
diff --git a/backends/networking/sdl_net/reader.cpp b/backends/networking/sdl_net/reader.cpp
index 0c700bc709..94b1abae0d 100644
--- a/backends/networking/sdl_net/reader.cpp
+++ b/backends/networking/sdl_net/reader.cpp
@@ -36,6 +36,8 @@ Reader::Reader() {
_window = nullptr;
_windowUsed = 0;
_windowSize = 0;
+ _windowReadPosition = 0;
+ _windowWritePosition = 0;
_headersStream = nullptr;
_firstBlock = true;
@@ -63,6 +65,8 @@ Reader &Reader::operator=(Reader &r) {
_window = r._window;
_windowUsed = r._windowUsed;
_windowSize = r._windowSize;
+ _windowReadPosition = r._windowReadPosition;
+ _windowWritePosition = r._windowWritePosition;
r._window = nullptr;
_headersStream = r._headersStream;
@@ -308,21 +312,24 @@ void Reader::makeWindow(uint32 size) {
_window = new byte[size];
_windowUsed = 0;
_windowSize = size;
+ _windowReadPosition = 0;
+ _windowWritePosition = 0;
}
void Reader::freeWindow() {
delete[] _window;
_window = nullptr;
_windowUsed = _windowSize = 0;
+ _windowReadPosition = _windowWritePosition = 0;
}
namespace {
-bool windowEqualsString(const byte *window, uint32 windowSize, const Common::String &boundary) {
+bool windowEqualsString(const byte *window, uint32 windowStart, uint32 windowSize, const Common::String &boundary) {
if (boundary.size() != windowSize)
return false;
for (uint32 i = 0; i < windowSize; ++i) {
- if (window[i] != boundary[i])
+ if (window[(windowStart + i) % windowSize] != boundary[i])
return false;
}
@@ -332,19 +339,20 @@ bool windowEqualsString(const byte *window, uint32 windowSize, const Common::Str
bool Reader::readOneByteInStream(Common::WriteStream *stream, const Common::String &boundary) {
byte b = readOne();
- _window[_windowUsed++] = b;
+ ++_windowUsed;
+ _window[_windowWritePosition] = b;
+ _windowWritePosition = (_windowWritePosition + 1) % _windowSize;
if (_windowUsed < _windowSize)
return true;
//when window is filled, check whether that's the boundary
- if (windowEqualsString(_window, _windowSize, boundary))
+ if (windowEqualsString(_window, _windowReadPosition, _windowSize, boundary))
return false;
//if not, add the first byte of the window to the string
if (stream)
- stream->writeByte(_window[0]);
- for (uint32 i = 1; i < _windowSize; ++i)
- _window[i - 1] = _window[i];
+ stream->writeByte(_window[_windowReadPosition]);
+ _windowReadPosition = (_windowReadPosition + 1) % _windowSize;
--_windowUsed;
return true;
}
diff --git a/backends/networking/sdl_net/reader.h b/backends/networking/sdl_net/reader.h
index 60557fdf06..3d9028020c 100644
--- a/backends/networking/sdl_net/reader.h
+++ b/backends/networking/sdl_net/reader.h
@@ -78,7 +78,7 @@ class Reader {
uint32 _bytesLeft;
byte *_window;
- uint32 _windowUsed, _windowSize;
+ uint32 _windowUsed, _windowSize, _windowReadPosition, _windowWritePosition;
Common::MemoryReadWriteStream *_headersStream;
Commit: 5636ffb180ff878452fa98041af62722d3ce060a
https://github.com/scummvm/scummvm/commit/5636ffb180ff878452fa98041af62722d3ce060a
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2021-11-01T12:15:27+01:00
Commit Message:
CLOUD: Tweak Networking::Reader pattern-matching logic
Instead of doing linear strcmp-like operation after every byte read, Reader now computes a "hash" of the needle it searches for and updates "hash" of the window contents. Now, it only does strcmp if window has the same "hash" as the needle, which also improves file upload speed for ScummVM's local webserver.
Changed paths:
backends/networking/sdl_net/reader.cpp
backends/networking/sdl_net/reader.h
diff --git a/backends/networking/sdl_net/reader.cpp b/backends/networking/sdl_net/reader.cpp
index 94b1abae0d..6e16cd30ac 100644
--- a/backends/networking/sdl_net/reader.cpp
+++ b/backends/networking/sdl_net/reader.cpp
@@ -38,6 +38,7 @@ Reader::Reader() {
_windowSize = 0;
_windowReadPosition = 0;
_windowWritePosition = 0;
+ _windowHash = 0;
_headersStream = nullptr;
_firstBlock = true;
@@ -67,6 +68,7 @@ Reader &Reader::operator=(Reader &r) {
_windowSize = r._windowSize;
_windowReadPosition = r._windowReadPosition;
_windowWritePosition = r._windowWritePosition;
+ _windowHash = r._windowHash;
r._window = nullptr;
_headersStream = r._headersStream;
@@ -98,8 +100,18 @@ void Reader::cleanup() {
freeWindow();
}
+namespace {
+uint32 calculateHash(const Common::String& boundary) {
+ uint32 result = 0;
+ for (uint32 i = 0; i < boundary.size(); ++i)
+ result ^= boundary[i];
+ return result;
+}
+}
+
bool Reader::readAndHandleFirstHeaders() {
Common::String boundary = "\r\n\r\n";
+ uint32 boundaryHash = calculateHash(boundary);
if (_window == nullptr) {
makeWindow(boundary.size());
}
@@ -107,7 +119,7 @@ bool Reader::readAndHandleFirstHeaders() {
_headersStream = new Common::MemoryReadWriteStream(DisposeAfterUse::YES);
}
- while (readOneByteInStream(_headersStream, boundary)) {
+ while (readOneByteInStream(_headersStream, boundary, boundaryHash)) {
if (_headersStream->size() > SUSPICIOUS_HEADERS_SIZE) {
_isBadRequest = true;
return true;
@@ -124,9 +136,10 @@ bool Reader::readAndHandleFirstHeaders() {
bool Reader::readBlockHeadersIntoStream(Common::WriteStream *stream) {
Common::String boundary = "\r\n\r\n";
+ uint32 boundaryHash = calculateHash(boundary);
if (_window == nullptr) makeWindow(boundary.size());
- while (readOneByteInStream(stream, boundary)) {
+ while (readOneByteInStream(stream, boundary, boundaryHash)) {
if (!bytesLeft())
return false;
}
@@ -292,7 +305,8 @@ bool Reader::readContentIntoStream(Common::WriteStream *stream) {
if (_window == nullptr)
makeWindow(boundary.size());
- while (readOneByteInStream(stream, boundary)) {
+ uint32 boundaryHash = calculateHash(boundary);
+ while (readOneByteInStream(stream, boundary, boundaryHash)) {
if (!bytesLeft())
return false;
}
@@ -314,6 +328,7 @@ void Reader::makeWindow(uint32 size) {
_windowSize = size;
_windowReadPosition = 0;
_windowWritePosition = 0;
+ _windowHash = 0;
}
void Reader::freeWindow() {
@@ -321,6 +336,7 @@ void Reader::freeWindow() {
_window = nullptr;
_windowUsed = _windowSize = 0;
_windowReadPosition = _windowWritePosition = 0;
+ _windowHash = 0;
}
namespace {
@@ -337,21 +353,23 @@ bool windowEqualsString(const byte *window, uint32 windowStart, uint32 windowSiz
}
}
-bool Reader::readOneByteInStream(Common::WriteStream *stream, const Common::String &boundary) {
+bool Reader::readOneByteInStream(Common::WriteStream *stream, const Common::String &boundary, const uint32 boundaryHash) {
byte b = readOne();
++_windowUsed;
_window[_windowWritePosition] = b;
_windowWritePosition = (_windowWritePosition + 1) % _windowSize;
+ _windowHash ^= b;
if (_windowUsed < _windowSize)
return true;
//when window is filled, check whether that's the boundary
- if (windowEqualsString(_window, _windowReadPosition, _windowSize, boundary))
+ if (_windowHash == boundaryHash && windowEqualsString(_window, _windowReadPosition, _windowSize, boundary))
return false;
//if not, add the first byte of the window to the string
if (stream)
stream->writeByte(_window[_windowReadPosition]);
+ _windowHash ^= _window[_windowReadPosition];
_windowReadPosition = (_windowReadPosition + 1) % _windowSize;
--_windowUsed;
return true;
diff --git a/backends/networking/sdl_net/reader.h b/backends/networking/sdl_net/reader.h
index 3d9028020c..83d0ebb043 100644
--- a/backends/networking/sdl_net/reader.h
+++ b/backends/networking/sdl_net/reader.h
@@ -79,6 +79,7 @@ class Reader {
byte *_window;
uint32 _windowUsed, _windowSize, _windowReadPosition, _windowWritePosition;
+ uint32 _windowHash;
Common::MemoryReadWriteStream *_headersStream;
@@ -105,7 +106,7 @@ class Reader {
void makeWindow(uint32 size);
void freeWindow();
- bool readOneByteInStream(Common::WriteStream *stream, const Common::String &boundary);
+ bool readOneByteInStream(Common::WriteStream *stream, const Common::String &boundary, const uint32 boundaryHash);
byte readOne();
uint32 bytesLeft() const;
More information about the Scummvm-git-logs
mailing list