From 93b28447ee3532313e7f6dc29a1ef2c4dc7e1ed0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 4 Aug 2025 15:13:55 -1000 Subject: [PATCH] [bluetooth_proxy] Optimize memory usage with fixed-size array and const string references (#10015) --- .../bluetooth_proxy/bluetooth_proxy.cpp | 15 +++++++++------ .../components/bluetooth_proxy/bluetooth_proxy.h | 14 +++++++++----- .../components/esp32_ble_client/ble_client_base.h | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index a59a33117a..97b0884dda 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -35,8 +35,8 @@ void BluetoothProxy::setup() { // Don't pre-allocate pool - let it grow only if needed in busy environments // Many devices in quiet areas will never need the overflow pool - this->connections_free_response_.limit = this->connections_.size(); - this->connections_free_response_.free = this->connections_.size(); + this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS; + this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS; this->parent_->add_scanner_state_callback([this](esp32_ble_tracker::ScannerState state) { if (this->api_connection_ != nullptr) { @@ -134,12 +134,13 @@ void BluetoothProxy::dump_config() { ESP_LOGCONFIG(TAG, " Active: %s\n" " Connections: %d", - YESNO(this->active_), this->connections_.size()); + YESNO(this->active_), this->connection_count_); } void BluetoothProxy::loop() { if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr) { - for (auto *connection : this->connections_) { + for (uint8_t i = 0; i < this->connection_count_; i++) { + auto *connection = this->connections_[i]; if (connection->get_address() != 0 && !connection->disconnect_pending()) { connection->disconnect(); } @@ -162,7 +163,8 @@ esp32_ble_tracker::AdvertisementParserType BluetoothProxy::get_advertisement_par } BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool reserve) { - for (auto *connection : this->connections_) { + for (uint8_t i = 0; i < this->connection_count_; i++) { + auto *connection = this->connections_[i]; if (connection->get_address() == address) return connection; } @@ -170,7 +172,8 @@ BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool rese if (!reserve) return nullptr; - for (auto *connection : this->connections_) { + for (uint8_t i = 0; i < this->connection_count_; i++) { + auto *connection = this->connections_[i]; if (connection->get_address() == 0) { connection->send_service_ = DONE_SENDING_SERVICES; connection->set_address(address); diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 70deef1ebd..d367dad438 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -2,6 +2,7 @@ #ifdef USE_ESP32 +#include #include #include @@ -63,8 +64,10 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override; void register_connection(BluetoothConnection *connection) { - this->connections_.push_back(connection); - connection->proxy_ = this; + if (this->connection_count_ < BLUETOOTH_PROXY_MAX_CONNECTIONS) { + this->connections_[this->connection_count_++] = connection; + connection->proxy_ = this; + } } void bluetooth_device_request(const api::BluetoothDeviceRequest &msg); @@ -138,8 +141,8 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com // Group 1: Pointers (4 bytes each, naturally aligned) api::APIConnection *api_connection_{nullptr}; - // Group 2: Container types (typically 12 bytes on 32-bit) - std::vector connections_{}; + // Group 2: Fixed-size array of connection pointers + std::array connections_{}; // BLE advertisement batching std::vector advertisement_pool_; @@ -154,7 +157,8 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com // Group 4: 1-byte types grouped together bool active_; uint8_t advertisement_count_{0}; - // 2 bytes used, 2 bytes padding + uint8_t connection_count_{0}; + // 3 bytes used, 1 byte padding }; extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index b30e9cd444..93260b1c15 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -66,7 +66,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { (uint8_t) (this->address_ >> 0) & 0xff); } } - std::string address_str() const { return this->address_str_; } + const std::string &address_str() const { return this->address_str_; } BLEService *get_service(espbt::ESPBTUUID uuid); BLEService *get_service(uint16_t uuid);