From 692a674fe086b24fa462723688ced2722cfde3b9 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 14 Apr 2015 00:25:23 +0900 Subject: [PATCH] SocketRecvBuffer: Eliminate memmove Since we don't try to read into buffer if buffer is not empty, we don't have to memmove things. This commit mostly rewrites SocketRecvBuffer. --- src/DownloadCommand.cc | 2 +- src/HttpConnection.cc | 4 ++-- src/HttpServer.cc | 6 +++--- src/HttpSkipResponseCommand.cc | 2 +- src/SocketRecvBuffer.cc | 37 +++++++++++++++++----------------- src/SocketRecvBuffer.h | 30 ++++++++++++--------------- 6 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 1cd2cc59..5be8d551 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -187,7 +187,7 @@ bool DownloadCommand::executeInternal() { getSocketRecvBuffer()->getBufferLength()); bufSize = streamFilter_->getBytesProcessed(); } - getSocketRecvBuffer()->shiftBuffer(bufSize); + getSocketRecvBuffer()->drain(bufSize); peerStat_->updateDownloadLength(bufSize); getDownloadContext()->updateDownloadLength(bufSize); } diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc index ff043e20..c3767b24 100644 --- a/src/HttpConnection.cc +++ b/src/HttpConnection.cc @@ -157,12 +157,12 @@ std::unique_ptr HttpConnection::receiveResponse() httpResponse->setHttpHeader(proc->getResult()); httpResponse->setHttpRequest(outstandingHttpRequests_.front()-> popHttpRequest()); - socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed()); + socketRecvBuffer_->drain(proc->getLastBytesProcessed()); outstandingHttpRequests_.pop_front(); return httpResponse; } - socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed()); + socketRecvBuffer_->drain(proc->getLastBytesProcessed()); return nullptr; } diff --git a/src/HttpServer.cc b/src/HttpServer.cc index cac0cc7f..455f8afe 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -142,7 +142,7 @@ bool HttpServer::receiveRequest() lastRequestHeader_ = headerProcessor_->getResult(); A2_LOG_INFO(fmt("HTTP Server received request\n%s", headerProcessor_->getHeaderString().c_str())); - socketRecvBuffer_->shiftBuffer(headerProcessor_->getLastBytesProcessed()); + socketRecvBuffer_->drain(headerProcessor_->getLastBytesProcessed()); bodyConsumed_ = 0; if(setupResponseRecv() < 0) { A2_LOG_INFO("Request path is invaild. Ignore the request body."); @@ -175,7 +175,7 @@ bool HttpServer::receiveRequest() } return true; } else { - socketRecvBuffer_->shiftBuffer(headerProcessor_->getLastBytesProcessed()); + socketRecvBuffer_->drain(headerProcessor_->getLastBytesProcessed()); return false; } } @@ -197,7 +197,7 @@ bool HttpServer::receiveBody() if(lastBody_) { lastBody_->writeData(socketRecvBuffer_->getBuffer(), length, 0); } - socketRecvBuffer_->shiftBuffer(length); + socketRecvBuffer_->drain(length); bodyConsumed_ += length; return lastContentLength_ == bodyConsumed_; } diff --git a/src/HttpSkipResponseCommand.cc b/src/HttpSkipResponseCommand.cc index ef5d3d76..d2149c1f 100644 --- a/src/HttpSkipResponseCommand.cc +++ b/src/HttpSkipResponseCommand.cc @@ -138,7 +138,7 @@ bool HttpSkipResponseCommand::executeInternal() getSocketRecvBuffer()->getBufferLength()); bufSize = streamFilter_->getBytesProcessed(); } - getSocketRecvBuffer()->shiftBuffer(bufSize); + getSocketRecvBuffer()->drain(bufSize); } if(totalLength_ != 0 && eof) { throw DL_RETRY_EX(EX_GOT_EOF); diff --git a/src/SocketRecvBuffer.cc b/src/SocketRecvBuffer.cc index beb163c5..1007365c 100644 --- a/src/SocketRecvBuffer.cc +++ b/src/SocketRecvBuffer.cc @@ -39,17 +39,11 @@ #include "SocketCore.h" #include "LogFactory.h" -#include "a2functional.h" namespace aria2 { -SocketRecvBuffer::SocketRecvBuffer -(std::shared_ptr socket, - size_t capacity) - : socket_(std::move(socket)), - capacity_(capacity), - buf_(make_unique(capacity_)), - bufLen_(0) +SocketRecvBuffer::SocketRecvBuffer(std::shared_ptr socket) + : socket_(std::move(socket)), pos_(buf_.data()), last_(pos_) {} SocketRecvBuffer::~SocketRecvBuffer() @@ -57,21 +51,28 @@ SocketRecvBuffer::~SocketRecvBuffer() ssize_t SocketRecvBuffer::recv() { - size_t len = capacity_ - bufLen_; - if(len > 0) { - socket_->readData(buf_.get() + bufLen_, len); - bufLen_ += len; - } else { + size_t n = std::end(buf_) - last_; + if (n == 0) { A2_LOG_DEBUG("Buffer full"); + return 0; } - return len; + socket_->readData(last_, n); + last_ += n; + return n; } -void SocketRecvBuffer::shiftBuffer(size_t offset) +void SocketRecvBuffer::drain(size_t n) { - assert(offset <= bufLen_); - memmove(buf_.get(), buf_.get() + offset, bufLen_ - offset); - bufLen_ -= offset; + assert(pos_ + n <= last_); + pos_ += n; + if (pos_ == last_) { + truncateBuffer(); + } +} + +void SocketRecvBuffer::truncateBuffer() +{ + pos_ = last_ = buf_.data(); } } // namespace aria2 diff --git a/src/SocketRecvBuffer.h b/src/SocketRecvBuffer.h index 00d04bb7..ceee253e 100644 --- a/src/SocketRecvBuffer.h +++ b/src/SocketRecvBuffer.h @@ -38,6 +38,7 @@ #include "common.h" #include +#include namespace aria2 { @@ -45,21 +46,17 @@ class SocketCore; class SocketRecvBuffer { public: - SocketRecvBuffer - (std::shared_ptr socket, - size_t capacity = 16*1024); + SocketRecvBuffer(std::shared_ptr socket); ~SocketRecvBuffer(); // Reads data from socket as much as capacity allows. Returns the // number of bytes read. ssize_t recv(); - // Shifts buffer by offset bytes. offset must satisfy offset <= - // getBufferLength(). - void shiftBuffer(size_t offset); // Truncates the contents of buffer to 0. - void clearBuffer() - { - bufLen_ = 0; - } + void truncateBuffer(); + // Drains first n bytes of data from buffer. It is an programmer's + // responsibility to ensure that n is smaller or equal to the + // buffered data. + void drain(size_t n); const std::shared_ptr& getSocket() const { @@ -68,25 +65,24 @@ public: const unsigned char* getBuffer() const { - return buf_.get(); + return pos_; } size_t getBufferLength() const { - return bufLen_; + return last_ - pos_; } bool bufferEmpty() const { - return bufLen_ == 0; + return pos_ == last_; } - void pushBuffer(const unsigned char* data, size_t len); private: + std::array buf_; std::shared_ptr socket_; - size_t capacity_; - std::unique_ptr buf_; - size_t bufLen_; + unsigned char *pos_; + unsigned char *last_; }; } // namespace aria2