From 2f1595b94836f49fa9a42de0abbc2b3df771f300 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 26 Aug 2023 20:59:16 -0400 Subject: [PATCH] Avoid a copy in AuthSrv downloads. For auth files, this looked something like: Disk/SDL Blob -> Temporary Buffer -> Send Buffer -> OS Buffer For minified SDL, we had the same thing, but instead of the Disk as a backing store, we were using a buffer in userspace, which meant there were three redundant copies instead of just two in disk file case. This removes the temporary buffer from the equation such that the process is now: Disk/SDL Blob -> Send Buffer -> OS Buffer --- AuthServ/AuthServer.cpp | 10 ++++------ streams.cpp | 21 +++++++++++++++++++++ streams.h | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/AuthServ/AuthServer.cpp b/AuthServ/AuthServer.cpp index cb4f882..2dc043f 100755 --- a/AuthServ/AuthServer.cpp +++ b/AuthServ/AuthServer.cpp @@ -646,16 +646,15 @@ void cb_downloadStart(AuthServer_Private& client) client.m_buffer.write(stream->size()); client.m_buffer.write(stream->tell()); - uint8_t data[CHUNK_SIZE]; if (stream->size() > CHUNK_SIZE) { client.m_buffer.write(CHUNK_SIZE); + uint8_t* data = client.m_buffer.allocate(CHUNK_SIZE); stream->readBytes(data, CHUNK_SIZE); - client.m_buffer.writeBytes(data, CHUNK_SIZE); client.m_downloads[transId] = stream; } else { client.m_buffer.write(stream->size()); + uint8_t* data = client.m_buffer.allocate(stream->size()); stream->readBytes(data, stream->size()); - client.m_buffer.writeBytes(data, stream->size()); delete stream; } @@ -680,16 +679,15 @@ void cb_downloadNext(AuthServer_Private& client) client.m_buffer.write(fi->second->size()); client.m_buffer.write(fi->second->tell()); - uint8_t data[CHUNK_SIZE]; size_t bytesLeft = fi->second->size() - fi->second->tell(); if (bytesLeft > CHUNK_SIZE) { client.m_buffer.write(CHUNK_SIZE); + uint8_t* data = client.m_buffer.allocate(CHUNK_SIZE); fi->second->readBytes(data, CHUNK_SIZE); - client.m_buffer.writeBytes(data, CHUNK_SIZE); } else { client.m_buffer.write(bytesLeft); + uint8_t* data = client.m_buffer.allocate(bytesLeft); fi->second->readBytes(data, bytesLeft); - client.m_buffer.writeBytes(data, bytesLeft); delete fi->second; client.m_downloads.erase(fi); } diff --git a/streams.cpp b/streams.cpp index 78abded..575dd1b 100644 --- a/streams.cpp +++ b/streams.cpp @@ -228,6 +228,27 @@ void DS::BufferStream::steal(uint8_t* buffer, size_t size) m_position = 0; } +uint8_t* DS::BufferStream::allocate(size_t size) +{ + if (m_position + size > m_alloc) { + // Resize stream + size_t bigger = m_alloc ? m_alloc : 4096; + while (m_position + size > bigger) + bigger *= 2; + uint8_t* newbuffer = new uint8_t[bigger]; + if (m_size != 0) + memcpy(newbuffer, m_buffer, m_size); + delete[] m_buffer; + m_buffer = newbuffer; + m_alloc = bigger; + } + uint8_t* result = m_buffer + m_position; + m_position += size; + if (m_position > m_size) + m_size = m_position; + return result; +} + ssize_t DS::BlobStream::readBytes(void* buffer, size_t count) { diff --git a/streams.h b/streams.h index bda1584..7ac1db1 100644 --- a/streams.h +++ b/streams.h @@ -174,6 +174,8 @@ namespace DS void set(const void* buffer, size_t size); void steal(uint8_t* buffer, size_t size); + uint8_t* allocate(size_t size); + void ref() { ++m_refs; } void unref() {