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 | ||||
|  | ||||
|   /// 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. | ||||
|   template<class C> C *register_component(C *c) { | ||||
| @@ -316,7 +308,7 @@ class Application { | ||||
|     } \ | ||||
|     return nullptr; \ | ||||
|   } | ||||
|   const std::vector<Device *> &get_devices() { return this->devices_; } | ||||
|   const auto &get_devices() { return this->devices_; } | ||||
| #else | ||||
| #define GET_ENTITY_METHOD(entity_type, entity_name, entities_member) \ | ||||
|   entity_type *get_##entity_name##_by_key(uint32_t key, bool include_internal = false) { \ | ||||
| @@ -328,7 +320,7 @@ class Application { | ||||
|   } | ||||
| #endif  // USE_DEVICES | ||||
| #ifdef USE_AREAS | ||||
|   const std::vector<Area *> &get_areas() { return this->areas_; } | ||||
|   const auto &get_areas() { return this->areas_; } | ||||
| #endif | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   auto &get_binary_sensors() const { return this->binary_sensors_; } | ||||
| @@ -462,12 +454,7 @@ class Application { | ||||
|   const char *comment_{nullptr}; | ||||
|   const char *compilation_time_{nullptr}; | ||||
|  | ||||
|   // size_t members | ||||
|   size_t dump_config_at_{SIZE_MAX}; | ||||
|  | ||||
|   // Vectors (largest members) | ||||
|   std::vector<Component *> components_{}; | ||||
|  | ||||
|   // std::vector (3 pointers each: begin, end, capacity) | ||||
|   // Partitioned vector design for looping components | ||||
|   // ================================================= | ||||
|   // Components are partitioned into [active | inactive] sections: | ||||
| @@ -485,12 +472,54 @@ class Application { | ||||
|   //   and active_end_ is incremented | ||||
|   // - This eliminates branch mispredictions from flag checking in the hot loop | ||||
|   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 | ||||
|   std::vector<Device *> devices_{}; | ||||
|   StaticVector<Device *, ESPHOME_DEVICE_COUNT> devices_{}; | ||||
| #endif | ||||
| #ifdef USE_AREAS | ||||
|   std::vector<Area *> areas_{}; | ||||
|   StaticVector<Area *, ESPHOME_AREA_COUNT> areas_{}; | ||||
| #endif | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   StaticVector<binary_sensor::BinarySensor *, ESPHOME_ENTITY_BINARY_SENSOR_COUNT> binary_sensors_{}; | ||||
| @@ -556,41 +585,6 @@ class Application { | ||||
| #ifdef USE_UPDATE | ||||
|   StaticVector<update::UpdateEntity *, ESPHOME_ENTITY_UPDATE_COUNT> updates_{}; | ||||
| #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. | ||||
|   | ||||
| @@ -444,10 +444,8 @@ async def to_code(config: ConfigType) -> None: | ||||
|             config[CONF_NAME_ADD_MAC_SUFFIX], | ||||
|         ) | ||||
|     ) | ||||
|     # Reserve space for components to avoid reallocation during registration | ||||
|     cg.add( | ||||
|         cg.RawStatement(f"App.reserve_components({len(CORE.component_ids)});"), | ||||
|     ) | ||||
|     # Define component count for static allocation | ||||
|     cg.add_define("ESPHOME_COMPONENT_COUNT", len(CORE.component_ids)) | ||||
|  | ||||
|     CORE.add_job(_add_platform_reserves) | ||||
|  | ||||
| @@ -516,8 +514,8 @@ async def to_code(config: ConfigType) -> None: | ||||
|     all_areas.extend(config[CONF_AREAS]) | ||||
|  | ||||
|     if all_areas: | ||||
|         cg.add(cg.RawStatement(f"App.reserve_area({len(all_areas)});")) | ||||
|         cg.add_define("USE_AREAS") | ||||
|         cg.add_define("ESPHOME_AREA_COUNT", len(all_areas)) | ||||
|  | ||||
|         for area_conf in all_areas: | ||||
|             area_id: core.ID = area_conf[CONF_ID] | ||||
| @@ -534,9 +532,9 @@ async def to_code(config: ConfigType) -> None: | ||||
|     if not devices: | ||||
|         return | ||||
|  | ||||
|     # Reserve space for devices | ||||
|     cg.add(cg.RawStatement(f"App.reserve_device({len(devices)});")) | ||||
|     # Define device count for static allocation | ||||
|     cg.add_define("USE_DEVICES") | ||||
|     cg.add_define("ESPHOME_DEVICE_COUNT", len(devices)) | ||||
|  | ||||
|     # Process each device | ||||
|     for dev_conf in devices: | ||||
|   | ||||
| @@ -240,7 +240,10 @@ | ||||
|  | ||||
| #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_BINARY_SENSOR_COUNT 1 | ||||
| #define ESPHOME_ENTITY_BUTTON_COUNT 1 | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include <cstdint> | ||||
| #include <cstring> | ||||
| #include <functional> | ||||
| #include <iterator> | ||||
| #include <limits> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| @@ -100,6 +101,8 @@ template<typename T, size_t N> class StaticVector { | ||||
|   using value_type = T; | ||||
|   using iterator = typename std::array<T, N>::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: | ||||
|   std::array<T, N> data_{}; | ||||
| @@ -114,6 +117,7 @@ template<typename T, size_t N> class StaticVector { | ||||
|   } | ||||
|  | ||||
|   size_t size() const { return count_; } | ||||
|   bool empty() const { return count_ == 0; } | ||||
|  | ||||
|   T &operator[](size_t i) { 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_; } | ||||
|   const_iterator begin() const { return data_.begin(); } | ||||
|   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