From 945d1e21f2a42f5393f0c7108b7a7de69a8f9f47 Mon Sep 17 00:00:00 2001 From: paveldn Date: Wed, 20 Mar 2024 09:10:48 +0100 Subject: [PATCH] Buffers optimisation --- include/utils/circular_buffer.h | 95 +++++++++++++++++++++------- include/utils/haier_log.h | 37 ++++------- src/transport/protocol_transport.cpp | 55 ++++++++++++++-- src/utils/haier_log.cpp | 21 +++++- test/simple_transport_test/test.cpp | 4 +- test/utils/virtual_stream.cpp | 2 +- tools/utils/serial_stream.cpp | 4 +- 7 files changed, 154 insertions(+), 64 deletions(-) diff --git a/include/utils/circular_buffer.h b/include/utils/circular_buffer.h index 28db833..af7dc13 100644 --- a/include/utils/circular_buffer.h +++ b/include/utils/circular_buffer.h @@ -2,6 +2,7 @@ #define CIRCULAR_BUFFER_H #include +#include template class CircularBuffer @@ -14,16 +15,19 @@ class CircularBuffer ~CircularBuffer() noexcept; CircularBuffer& operator=(const CircularBuffer& source); const T& operator[] (size_t index) const; - size_t get_capacity() const { return size_; }; - size_t get_available() const { return head_ <= tail_ ? tail_ - head_ : size_ - head_ + tail_; }; + size_t get_capacity() const { return capacity_; }; + size_t get_size() const; + size_t get_space() const { return this->capacity_ - this->get_size(); }; size_t push(const T& item); size_t push(const T* items, size_t size); size_t pop(T* items, size_t size); + T* reserve(size_t& size); void clear(); size_t drop(size_t size); - bool empty() const { return head_ == tail_; }; + bool empty() const { return is_empty_; }; private: - size_t size_; + bool is_empty_; + size_t capacity_; T* buffer_; size_t head_; size_t tail_; @@ -31,21 +35,27 @@ class CircularBuffer template CircularBuffer::CircularBuffer(size_t capacity) : - size_(capacity < CIRCULAR_BUFFER_MINIMUM_SIZE ? CIRCULAR_BUFFER_MINIMUM_SIZE : capacity), - buffer_(new T[size_]), + is_empty_(true), + capacity_(capacity < CIRCULAR_BUFFER_MINIMUM_SIZE ? CIRCULAR_BUFFER_MINIMUM_SIZE : capacity), + buffer_(new T[capacity_]), head_(0), tail_(0) {} template CircularBuffer::CircularBuffer(const CircularBuffer& source) : - size_(source.size_), - buffer_(new T[size_]), + is_empty_(source.is_empty_), + capacity_(source.capacity_), + buffer_(new T[capacity_]), head_(source.head_), tail_(source.tail_) { - for (size_t i = this->head_; i < this->tail_; i++) - this->buffer_[i] = source.buffer_[i]; + size_t size = source.get_size(); + for (size_t i = 0; i < size; i++) + { + size_t ind = (this->head_ + i) % this->capacity_; + this->buffer_[ind] = source.buffer_[ind]; + } } template @@ -60,12 +70,16 @@ CircularBuffer& CircularBuffer::operator=(const CircularBuffer& source) if (this != &source) { delete[] this->buffer_; - this->size_ = source.size_; - this->buffer_ = new T[this->size_]; + this->capacity_ = source.capacity_; + this->buffer_ = new T[this->capacity_]; this->head_ = source.head_; this->tail_ = source.tail_; - for (size_t i = this->head_; i < this->tail_; i++) - this->buffer_[i] = source.buffer_[i]; + size_t size = source.get_size(); + for (size_t i = 0; i < size; i++) + { + size_t ind = (this->head_ + i) % this->capacity_; + this->buffer_[ind] = source.buffer_[ind]; + } } return *this; } @@ -73,16 +87,25 @@ CircularBuffer& CircularBuffer::operator=(const CircularBuffer& source) template const T& CircularBuffer::operator[] (size_t index) const { - return this->buffer_[(this->head_ + index) % this->size_]; + return this->buffer_[(this->head_ + index) % this->capacity_]; +} + +template +size_t CircularBuffer::get_size() const +{ + if (this->tail_ == this->head_) + return this->is_empty_ ? 0 : this->capacity_; + return this->head_ < this->tail_ ? this->tail_ - this->head_ : this->capacity_ - this->head_ + this->tail_; } template size_t CircularBuffer::push(const T& item) { - if ((this->tail_ + 1) % this->size_ != this->head_) + if (this->is_empty_ || (this->tail_ != this->head_)) { this->buffer_[this->tail_] = item; - this->tail_ = (this->tail_ + 1) % this->size_; + this->tail_ = (this->tail_ + 1) % this->capacity_; + this->is_empty_ = false; return 1; } return 0; @@ -91,34 +114,57 @@ size_t CircularBuffer::push(const T& item) template size_t CircularBuffer::push(const T* items, size_t size) { - size_t size_to_push = (int)(this->size_ - this->get_available()); + size_t size_to_push = this->get_space(); if (size_to_push > size) size_to_push = size; for (size_t i = 0; i < size_to_push; i++) { this->buffer_[tail_] = items[i]; - this->tail_ = (this->tail_ + 1) % this->size_; + this->tail_ = (this->tail_ + 1) % this->capacity_; } + if (size_to_push > 0) + this->is_empty_ = false; return size_to_push; } template size_t CircularBuffer::pop(T* items, size_t size) { - size_t pop_size = this->get_available(); + size_t sz = this->get_size(); + size_t pop_size = sz; if (size < pop_size) pop_size = size; for (size_t i = 0; i < pop_size; i++) { items[i] = this->buffer_[this->head_]; - this->head_ = (this->head_ + 1) % this->size_; + this->head_ = (this->head_ + 1) % this->capacity_; } + if (pop_size == sz) + this->is_empty_ = true; return pop_size; } +template +T* CircularBuffer::reserve(size_t& size) +{ + size_t new_size; + size_t head = this->head_ == 0 ? this->capacity_ : 0; + if (head > this->tail_) + new_size = std::min(size, head - this->tail_); + else + new_size = std::min(size, this->capacity_ - this->tail_); + T* result = this->buffer_ + this->tail_; + this->tail_ = (this->tail_ + new_size) % this->capacity_; + size = new_size; + if (new_size > 0) + this->is_empty_ = false; + return result; +} + template void CircularBuffer::clear() { + this->is_empty_ = true; this->head_ = 0; this->tail_ = 0; } @@ -126,10 +172,13 @@ void CircularBuffer::clear() template size_t CircularBuffer::drop(size_t size) { - size_t drop_size = this->get_available(); + size_t sz = this->get_size(); + size_t drop_size = sz; if (size < drop_size) drop_size = size; - this->head_ = (this->head_ + drop_size) % this->size_; + this->head_ = (this->head_ + drop_size) % this->capacity_; + if (drop_size == sz) + this->is_empty_ = true;; return drop_size; } diff --git a/include/utils/haier_log.h b/include/utils/haier_log.h index d5d620f..8763f82 100644 --- a/include/utils/haier_log.h +++ b/include/utils/haier_log.h @@ -12,54 +12,38 @@ extern const char hex_map[]; #if (HAIER_LOG_LEVEL > 0) #define HAIER_LOGE(...) log_haier(haier_protocol::HaierLogLevel::LEVEL_ERROR, __VA_ARGS__) + #define HAIER_BUFE(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_ERROR, header, buffer, size) #else #define HAIER_LOGE(...) + #define HAIER_BUFE(header, buffer, size) #endif #if (HAIER_LOG_LEVEL > 1) #define HAIER_LOGW(...) log_haier(haier_protocol::HaierLogLevel::LEVEL_WARNING, __VA_ARGS__) + #define HAIER_BUFW(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_WARNING, header, buffer, size) #else #define HAIER_LOGW(...) + #define HAIER_BUFW(header, buffer, size) #endif #if (HAIER_LOG_LEVEL > 2) #define HAIER_LOGI(...) log_haier(haier_protocol::HaierLogLevel::LEVEL_INFO, __VA_ARGS__) + #define HAIER_BUFI(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_INFO, header, buffer, size) #else #define HAIER_LOGI(...) + #define HAIER_BUFI(header, buffer, size) #endif #if (HAIER_LOG_LEVEL > 3) #define HAIER_LOGD(...) log_haier(haier_protocol::HaierLogLevel::LEVEL_DEBUG, __VA_ARGS__) + #define HAIER_BUFD(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_DEBUG, header, buffer, size) #else #define HAIER_LOGD(...) + #define HAIER_BUFD(header, buffer, size) #endif #if (HAIER_LOG_LEVEL > 4) #define HAIER_LOGV(...) log_haier(haier_protocol::HaierLogLevel::LEVEL_VERBOSE, __VA_ARGS__) + #define HAIER_BUFV(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_VERBOSE, header, buffer, size) #else #define HAIER_LOGV(...) -#endif - -#if (HAIER_LOG_LEVEL > 0) -#define HAIER_BUFE(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_ERROR, header, buffer, size) -#else -#define HAIER_BUFE(header, buffer, size) -#endif -#if (HAIER_LOG_LEVEL > 1) -#define HAIER_BUFW(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_WARNING, header, buffer, size) -#else -#define HAIER_BUFW(header, buffer, size) -#endif -#if (HAIER_LOG_LEVEL > 2) -#define HAIER_BUFI(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_INFO, header, buffer, size) -#else -#define HAIER_BUFI(header, buffer, size) -#endif -#if (HAIER_LOG_LEVEL > 3) -#define HAIER_BUFD(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_DEBUG, header, buffer, size) -#else -#define HAIER_BUFD(header, buffer, size) -#endif -#if (HAIER_LOG_LEVEL > 4) -#define HAIER_BUFV(header, buffer, size) log_haier_buffer(haier_protocol::HaierLogLevel::LEVEL_VERBOSE, header, buffer, size) -#else -#define HAIER_BUFV(header, buffer, size) + #define HAIER_BUFV(header, buffer, size) #endif std::string buf_to_hex(const uint8_t* message, size_t size); @@ -81,6 +65,7 @@ using LogHandler = std::function; size_t log_haier(HaierLogLevel level, const char* format, ...); size_t log_haier_buffer(HaierLogLevel level, const char* header, const uint8_t* buffer, size_t size); +size_t log_haier_buffers(HaierLogLevel level, const char* header, const uint8_t* buffer1, size_t size1, const uint8_t* buffer2, size_t size2); void set_log_handler(LogHandler); void reset_log_handler(); diff --git a/src/transport/protocol_transport.cpp b/src/transport/protocol_transport.cpp index fb67e14..c255122 100644 --- a/src/transport/protocol_transport.cpp +++ b/src/transport/protocol_transport.cpp @@ -37,6 +37,47 @@ uint8_t TransportLevelHandler::send_data(uint8_t frame_type, const uint8_t *data return (uint8_t)size; } +size_t TransportLevelHandler::read_data() +{ + size_t count = this->stream_.available(); + if (count >= this->buffer_.get_capacity()) + count = this->buffer_.get_capacity(); + // Need to make space + size_t available = this->buffer_.get_space(); + if (count > available) + { + this->drop_bytes_(count - available); + if (this->frame_start_found_) + { + // Resetting frame because we will lose it start + HAIER_LOGW("Frame lost because of buffer overflow"); + this->pos_ = 0; + this->sep_count_ = 0; + this->frame_start_found_ = false; + this->current_frame_.reset(); + } + } + size_t size1 = count; + size_t size2 = 0; + uint8_t *buf1 = this->buffer_.reserve(size1); + uint8_t *buf2 = nullptr; + size1 = this->stream_.read_array(buf1, size1); + if (count > size1) + { + size2 = count - size1; + buf2 = this->buffer_.reserve(size2); + size2 = this->stream_.read_array(buf2, size2); + } +#if (HAIER_LOG_LEVEL > 4) + if (size1 + size2 > 0) + { + log_haier_buffers(haier_protocol::HaierLogLevel::LEVEL_VERBOSE, "Received data:", buf1, size1, buf2, size2); + } +#endif + return size1 + size2; +} + +#if 0 size_t TransportLevelHandler::read_data() { size_t bytes_read = 0; @@ -50,7 +91,6 @@ size_t TransportLevelHandler::read_data() #if (HAIER_LOG_LEVEL > 4) out_buf[bytes_read] = val; #endif - // IF there is 0xFF 0x55 replace it with 0xFF if (this->buffer_.push(val) == 0) break; bytes_read++; @@ -63,6 +103,7 @@ size_t TransportLevelHandler::read_data() #endif return bytes_read; } +#endif void TransportLevelHandler::process_data() { @@ -82,7 +123,7 @@ void TransportLevelHandler::process_data() } if (!this->buffer_.empty()) { - size_t buf_size = this->buffer_.get_available(); + size_t buf_size = this->buffer_.get_size(); int bytes_to_drop = 0; while (this->pos_ < buf_size) { @@ -147,7 +188,7 @@ void TransportLevelHandler::process_data() this->current_frame_.reset(); pos_ = 0; sep_count_ = 0; - buf_size = buffer_.get_available(); + buf_size = buffer_.get_size(); frame_start_found_ = false; continue; } @@ -192,7 +233,7 @@ void TransportLevelHandler::process_data() this->current_frame_.reset(); this->pos_ = 0; this->sep_count_ = 0; - buf_size = buffer_.get_available(); + buf_size = buffer_.get_size(); this->frame_start_found_ = false; continue; } @@ -218,7 +259,7 @@ void TransportLevelHandler::process_data() this->current_frame_.reset(); this->pos_ = 0; this->sep_count_ = 0; - buf_size = this->buffer_.get_available(); + buf_size = this->buffer_.get_size(); this->frame_start_found_ = false; continue; } @@ -245,7 +286,7 @@ void TransportLevelHandler::process_data() void TransportLevelHandler::reset_protocol() noexcept { this->current_frame_.reset(); - size_t bytesToDrop = this->buffer_.get_available(); + size_t bytesToDrop = this->buffer_.get_size(); if (pos_ < bytesToDrop) bytesToDrop = pos_; this->drop_bytes_(bytesToDrop); @@ -278,7 +319,7 @@ TransportLevelHandler::~TransportLevelHandler() void TransportLevelHandler::clear_() { - HAIER_LOGV("Clearing buffer, data size: %d", this->buffer_.get_available()); + HAIER_LOGV("Clearing buffer, data size: %d", this->buffer_.get_size()); this->buffer_.clear(); this->pos_ = 0; this->sep_count_ = 0; diff --git a/src/utils/haier_log.cpp b/src/utils/haier_log.cpp index 69bfe80..445038b 100644 --- a/src/utils/haier_log.cpp +++ b/src/utils/haier_log.cpp @@ -94,6 +94,11 @@ size_t log_haier(HaierLogLevel level, const char *format, ...) } size_t log_haier_buffer(HaierLogLevel level, const char *header, const uint8_t *buffer, size_t size) +{ + return log_haier_buffers(level, header, buffer, size, nullptr, 0); +} + +size_t log_haier_buffers(HaierLogLevel level, const char *header, const uint8_t *buffer1, size_t size1, const uint8_t *buffer2, size_t size2) { size_t res = 0; if ((global_log_handler != nullptr) && (level != HaierLogLevel::LEVEL_NONE)) @@ -110,10 +115,20 @@ size_t log_haier_buffer(HaierLogLevel level, const char *header, const uint8_t * } msg_buffer[res++] = ' '; } - if ((buffer != nullptr) && (size > 0)) - res += print_buf(buffer, size, msg_buffer + res, BUFFER_SIZE - res); - else + if (size1 + size2 == 0) res += snprintf(msg_buffer + res, BUFFER_SIZE - res - 1, ""); + else + { + if ((buffer1 != nullptr) && (size1 > 0)) + { + res += print_buf(buffer1, size1, msg_buffer + res, BUFFER_SIZE - res); + if ((BUFFER_SIZE - res > 0) && (size2 > 0)) + { + msg_buffer[res++] = ' '; + res += print_buf(buffer2, size2, msg_buffer + res, BUFFER_SIZE - res); + } + } + } global_log_handler(level, HAIER_LOG_TAG, msg_buffer); } return res; diff --git a/test/simple_transport_test/test.cpp b/test/simple_transport_test/test.cpp index 38f43db..0d376bf 100644 --- a/test/simple_transport_test/test.cpp +++ b/test/simple_transport_test/test.cpp @@ -10,7 +10,7 @@ class TestStream : public haier_protocol::ProtocolStream { public: TestStream() : mBuffer(2000) {}; - virtual size_t available() noexcept { return mBuffer.get_available(); }; + virtual size_t available() noexcept { return mBuffer.get_size(); }; virtual size_t read_array(uint8_t* data, size_t len) noexcept; virtual void write_array(const uint8_t* data, size_t len) noexcept; void addByte(uint8_t val); @@ -21,7 +21,7 @@ class TestStream : public haier_protocol::ProtocolStream size_t TestStream::read_array(uint8_t* data, size_t len) noexcept { - size_t toRead = mBuffer.get_available(); + size_t toRead = mBuffer.get_size(); if (len < toRead) toRead = len; return mBuffer.pop(data, toRead); diff --git a/test/utils/virtual_stream.cpp b/test/utils/virtual_stream.cpp index 08be790..1999fbd 100644 --- a/test/utils/virtual_stream.cpp +++ b/test/utils/virtual_stream.cpp @@ -8,7 +8,7 @@ VirtualStream::VirtualStream(CircularBuffer& tx_buffer, CircularBuffer< } size_t VirtualStream::available() noexcept { - return this->rx_buffer_.get_available(); + return this->rx_buffer_.get_size(); } size_t VirtualStream::read_array(uint8_t* data, size_t len) noexcept { return this->rx_buffer_.pop(data, len); diff --git a/tools/utils/serial_stream.cpp b/tools/utils/serial_stream.cpp index 145ebdb..20c5f8f 100644 --- a/tools/utils/serial_stream.cpp +++ b/tools/utils/serial_stream.cpp @@ -46,12 +46,12 @@ size_t SerialStream::available() noexcept { else return 0; } - return buffer_.get_available(); + return buffer_.get_size(); }; size_t SerialStream::read_array(uint8_t* data, size_t len) noexcept { if (!is_valid() || buffer_.empty()) return 0; - size_t av = buffer_.get_available(); + size_t av = buffer_.get_size(); if (av < len) len = av; return buffer_.pop(data, len);