mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge branch 'static_comp_areas' into integration
This commit is contained in:
		| @@ -214,14 +214,6 @@ class Application { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   /// Reserve space for components to avoid memory fragmentation |   /// Reserve space for components to avoid memory fragmentation | ||||||
|   void reserve_components(size_t count) { this->components_.reserve(count); } |  | ||||||
|  |  | ||||||
| #ifdef USE_AREAS |  | ||||||
|   void reserve_area(size_t count) { this->areas_.reserve(count); } |  | ||||||
| #endif |  | ||||||
| #ifdef USE_DEVICES |  | ||||||
|   void reserve_device(size_t count) { this->devices_.reserve(count); } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   /// Register the component in this Application instance. |   /// Register the component in this Application instance. | ||||||
|   template<class C> C *register_component(C *c) { |   template<class C> C *register_component(C *c) { | ||||||
| @@ -316,7 +308,7 @@ class Application { | |||||||
|     } \ |     } \ | ||||||
|     return nullptr; \ |     return nullptr; \ | ||||||
|   } |   } | ||||||
|   const std::vector<Device *> &get_devices() { return this->devices_; } |   const auto &get_devices() { return this->devices_; } | ||||||
| #else | #else | ||||||
| #define GET_ENTITY_METHOD(entity_type, entity_name, entities_member) \ | #define GET_ENTITY_METHOD(entity_type, entity_name, entities_member) \ | ||||||
|   entity_type *get_##entity_name##_by_key(uint32_t key, bool include_internal = false) { \ |   entity_type *get_##entity_name##_by_key(uint32_t key, bool include_internal = false) { \ | ||||||
| @@ -328,7 +320,7 @@ class Application { | |||||||
|   } |   } | ||||||
| #endif  // USE_DEVICES | #endif  // USE_DEVICES | ||||||
| #ifdef USE_AREAS | #ifdef USE_AREAS | ||||||
|   const std::vector<Area *> &get_areas() { return this->areas_; } |   const auto &get_areas() { return this->areas_; } | ||||||
| #endif | #endif | ||||||
| #ifdef USE_BINARY_SENSOR | #ifdef USE_BINARY_SENSOR | ||||||
|   auto &get_binary_sensors() const { return this->binary_sensors_; } |   auto &get_binary_sensors() const { return this->binary_sensors_; } | ||||||
| @@ -462,12 +454,7 @@ class Application { | |||||||
|   const char *comment_{nullptr}; |   const char *comment_{nullptr}; | ||||||
|   const char *compilation_time_{nullptr}; |   const char *compilation_time_{nullptr}; | ||||||
|  |  | ||||||
|   // size_t members |   // std::vector (3 pointers each: begin, end, capacity) | ||||||
|   size_t dump_config_at_{SIZE_MAX}; |  | ||||||
|  |  | ||||||
|   // Vectors (largest members) |  | ||||||
|   std::vector<Component *> components_{}; |  | ||||||
|  |  | ||||||
|   // Partitioned vector design for looping components |   // Partitioned vector design for looping components | ||||||
|   // ================================================= |   // ================================================= | ||||||
|   // Components are partitioned into [active | inactive] sections: |   // Components are partitioned into [active | inactive] sections: | ||||||
| @@ -485,12 +472,54 @@ class Application { | |||||||
|   //   and active_end_ is incremented |   //   and active_end_ is incremented | ||||||
|   // - This eliminates branch mispredictions from flag checking in the hot loop |   // - This eliminates branch mispredictions from flag checking in the hot loop | ||||||
|   std::vector<Component *> looping_components_{}; |   std::vector<Component *> looping_components_{}; | ||||||
|  | #ifdef USE_SOCKET_SELECT_SUPPORT | ||||||
|  |   std::vector<int> socket_fds_;  // Vector of all monitored socket file descriptors | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   // std::string members (typically 24-32 bytes each) | ||||||
|  |   std::string name_; | ||||||
|  |   std::string friendly_name_; | ||||||
|  |  | ||||||
|  |   // size_t members | ||||||
|  |   size_t dump_config_at_{SIZE_MAX}; | ||||||
|  |  | ||||||
|  |   // 4-byte members | ||||||
|  |   uint32_t last_loop_{0}; | ||||||
|  |   uint32_t loop_component_start_time_{0}; | ||||||
|  |  | ||||||
|  | #ifdef USE_SOCKET_SELECT_SUPPORT | ||||||
|  |   int max_fd_{-1};  // Highest file descriptor number for select() | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   // 2-byte members (grouped together for alignment) | ||||||
|  |   uint16_t loop_interval_{16};                 // Loop interval in ms (max 65535ms = 65.5 seconds) | ||||||
|  |   uint16_t looping_components_active_end_{0};  // Index marking end of active components in looping_components_ | ||||||
|  |   uint16_t current_loop_index_{0};             // For safe reentrant modifications during iteration | ||||||
|  |  | ||||||
|  |   // 1-byte members (grouped together to minimize padding) | ||||||
|  |   uint8_t app_state_{0}; | ||||||
|  |   bool name_add_mac_suffix_; | ||||||
|  |   bool in_loop_{false}; | ||||||
|  |   volatile bool has_pending_enable_loop_requests_{false}; | ||||||
|  |  | ||||||
|  | #ifdef USE_SOCKET_SELECT_SUPPORT | ||||||
|  |   bool socket_fds_changed_{false};  // Flag to rebuild base_read_fds_ when socket_fds_ changes | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef USE_SOCKET_SELECT_SUPPORT | ||||||
|  |   // Variable-sized members | ||||||
|  |   fd_set base_read_fds_{};  // Cached fd_set rebuilt only when socket_fds_ changes | ||||||
|  |   fd_set read_fds_{};       // Working fd_set for select(), copied from base_read_fds_ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   // StaticVectors (largest members - contain actual array data inline) | ||||||
|  |   StaticVector<Component *, ESPHOME_COMPONENT_COUNT> components_{}; | ||||||
|  |  | ||||||
| #ifdef USE_DEVICES | #ifdef USE_DEVICES | ||||||
|   std::vector<Device *> devices_{}; |   StaticVector<Device *, ESPHOME_DEVICE_COUNT> devices_{}; | ||||||
| #endif | #endif | ||||||
| #ifdef USE_AREAS | #ifdef USE_AREAS | ||||||
|   std::vector<Area *> areas_{}; |   StaticVector<Area *, ESPHOME_AREA_COUNT> areas_{}; | ||||||
| #endif | #endif | ||||||
| #ifdef USE_BINARY_SENSOR | #ifdef USE_BINARY_SENSOR | ||||||
|   StaticVector<binary_sensor::BinarySensor *, ESPHOME_ENTITY_BINARY_SENSOR_COUNT> binary_sensors_{}; |   StaticVector<binary_sensor::BinarySensor *, ESPHOME_ENTITY_BINARY_SENSOR_COUNT> binary_sensors_{}; | ||||||
| @@ -556,41 +585,6 @@ class Application { | |||||||
| #ifdef USE_UPDATE | #ifdef USE_UPDATE | ||||||
|   StaticVector<update::UpdateEntity *, ESPHOME_ENTITY_UPDATE_COUNT> updates_{}; |   StaticVector<update::UpdateEntity *, ESPHOME_ENTITY_UPDATE_COUNT> updates_{}; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef USE_SOCKET_SELECT_SUPPORT |  | ||||||
|   std::vector<int> socket_fds_;  // Vector of all monitored socket file descriptors |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   // String members |  | ||||||
|   std::string name_; |  | ||||||
|   std::string friendly_name_; |  | ||||||
|  |  | ||||||
|   // 4-byte members |  | ||||||
|   uint32_t last_loop_{0}; |  | ||||||
|   uint32_t loop_component_start_time_{0}; |  | ||||||
|  |  | ||||||
| #ifdef USE_SOCKET_SELECT_SUPPORT |  | ||||||
|   int max_fd_{-1};  // Highest file descriptor number for select() |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   // 2-byte members (grouped together for alignment) |  | ||||||
|   uint16_t loop_interval_{16};  // Loop interval in ms (max 65535ms = 65.5 seconds) |  | ||||||
|   uint16_t looping_components_active_end_{0}; |  | ||||||
|   uint16_t current_loop_index_{0};  // For safe reentrant modifications during iteration |  | ||||||
|  |  | ||||||
|   // 1-byte members (grouped together to minimize padding) |  | ||||||
|   uint8_t app_state_{0}; |  | ||||||
|   bool name_add_mac_suffix_; |  | ||||||
|   bool in_loop_{false}; |  | ||||||
|   volatile bool has_pending_enable_loop_requests_{false}; |  | ||||||
|  |  | ||||||
| #ifdef USE_SOCKET_SELECT_SUPPORT |  | ||||||
|   bool socket_fds_changed_{false};  // Flag to rebuild base_read_fds_ when socket_fds_ changes |  | ||||||
|  |  | ||||||
|   // Variable-sized members at end |  | ||||||
|   fd_set base_read_fds_{};  // Cached fd_set rebuilt only when socket_fds_ changes |  | ||||||
|   fd_set read_fds_{};       // Working fd_set for select(), copied from base_read_fds_ |  | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /// Global storage of Application pointer - only one Application can exist. | /// Global storage of Application pointer - only one Application can exist. | ||||||
|   | |||||||
| @@ -444,10 +444,8 @@ async def to_code(config: ConfigType) -> None: | |||||||
|             config[CONF_NAME_ADD_MAC_SUFFIX], |             config[CONF_NAME_ADD_MAC_SUFFIX], | ||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|     # Reserve space for components to avoid reallocation during registration |     # Define component count for static allocation | ||||||
|     cg.add( |     cg.add_define("ESPHOME_COMPONENT_COUNT", len(CORE.component_ids)) | ||||||
|         cg.RawStatement(f"App.reserve_components({len(CORE.component_ids)});"), |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     CORE.add_job(_add_platform_reserves) |     CORE.add_job(_add_platform_reserves) | ||||||
|  |  | ||||||
| @@ -516,8 +514,8 @@ async def to_code(config: ConfigType) -> None: | |||||||
|     all_areas.extend(config[CONF_AREAS]) |     all_areas.extend(config[CONF_AREAS]) | ||||||
|  |  | ||||||
|     if all_areas: |     if all_areas: | ||||||
|         cg.add(cg.RawStatement(f"App.reserve_area({len(all_areas)});")) |  | ||||||
|         cg.add_define("USE_AREAS") |         cg.add_define("USE_AREAS") | ||||||
|  |         cg.add_define("ESPHOME_AREA_COUNT", len(all_areas)) | ||||||
|  |  | ||||||
|         for area_conf in all_areas: |         for area_conf in all_areas: | ||||||
|             area_id: core.ID = area_conf[CONF_ID] |             area_id: core.ID = area_conf[CONF_ID] | ||||||
| @@ -534,9 +532,9 @@ async def to_code(config: ConfigType) -> None: | |||||||
|     if not devices: |     if not devices: | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     # Reserve space for devices |     # Define device count for static allocation | ||||||
|     cg.add(cg.RawStatement(f"App.reserve_device({len(devices)});")) |  | ||||||
|     cg.add_define("USE_DEVICES") |     cg.add_define("USE_DEVICES") | ||||||
|  |     cg.add_define("ESPHOME_DEVICE_COUNT", len(devices)) | ||||||
|  |  | ||||||
|     # Process each device |     # Process each device | ||||||
|     for dev_conf in devices: |     for dev_conf in devices: | ||||||
|   | |||||||
| @@ -240,7 +240,10 @@ | |||||||
|  |  | ||||||
| #define USE_DASHBOARD_IMPORT | #define USE_DASHBOARD_IMPORT | ||||||
|  |  | ||||||
| // Default entity counts for static analysis | // Default counts for static analysis | ||||||
|  | #define ESPHOME_COMPONENT_COUNT 50 | ||||||
|  | #define ESPHOME_DEVICE_COUNT 10 | ||||||
|  | #define ESPHOME_AREA_COUNT 10 | ||||||
| #define ESPHOME_ENTITY_ALARM_CONTROL_PANEL_COUNT 1 | #define ESPHOME_ENTITY_ALARM_CONTROL_PANEL_COUNT 1 | ||||||
| #define ESPHOME_ENTITY_BINARY_SENSOR_COUNT 1 | #define ESPHOME_ENTITY_BINARY_SENSOR_COUNT 1 | ||||||
| #define ESPHOME_ENTITY_BUTTON_COUNT 1 | #define ESPHOME_ENTITY_BUTTON_COUNT 1 | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <functional> | #include <functional> | ||||||
|  | #include <iterator> | ||||||
| #include <limits> | #include <limits> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| @@ -100,6 +101,8 @@ template<typename T, size_t N> class StaticVector { | |||||||
|   using value_type = T; |   using value_type = T; | ||||||
|   using iterator = typename std::array<T, N>::iterator; |   using iterator = typename std::array<T, N>::iterator; | ||||||
|   using const_iterator = typename std::array<T, N>::const_iterator; |   using const_iterator = typename std::array<T, N>::const_iterator; | ||||||
|  |   using reverse_iterator = std::reverse_iterator<iterator>; | ||||||
|  |   using const_reverse_iterator = std::reverse_iterator<const_iterator>; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   std::array<T, N> data_{}; |   std::array<T, N> data_{}; | ||||||
| @@ -114,6 +117,7 @@ template<typename T, size_t N> class StaticVector { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { return count_; } |   size_t size() const { return count_; } | ||||||
|  |   bool empty() const { return count_ == 0; } | ||||||
|  |  | ||||||
|   T &operator[](size_t i) { return data_[i]; } |   T &operator[](size_t i) { return data_[i]; } | ||||||
|   const T &operator[](size_t i) const { return data_[i]; } |   const T &operator[](size_t i) const { return data_[i]; } | ||||||
| @@ -123,6 +127,12 @@ template<typename T, size_t N> class StaticVector { | |||||||
|   iterator end() { return data_.begin() + count_; } |   iterator end() { return data_.begin() + count_; } | ||||||
|   const_iterator begin() const { return data_.begin(); } |   const_iterator begin() const { return data_.begin(); } | ||||||
|   const_iterator end() const { return data_.begin() + count_; } |   const_iterator end() const { return data_.begin() + count_; } | ||||||
|  |  | ||||||
|  |   // Reverse iterators | ||||||
|  |   reverse_iterator rbegin() { return reverse_iterator(end()); } | ||||||
|  |   reverse_iterator rend() { return reverse_iterator(begin()); } | ||||||
|  |   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } | ||||||
|  |   const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| ///@} | ///@} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user