Improve logbook performance when no entities are filtered (#36842)

Various tweaks to reduce the python overhead of
the lazy class
This commit is contained in:
J. Nick Koston 2020-06-17 15:23:42 -05:00 committed by GitHub
parent 903db07feb
commit 3d385796da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -377,7 +377,7 @@ def _get_events(hass, config, start_day, end_day, entity_id=None):
def yield_events(query):
"""Yield Events that are not filtered away."""
for row in query.yield_per(500):
for row in query.yield_per(1000):
event = LazyEventPartialState(row)
if _keep_event(hass, event, entities_filter):
yield event
@ -385,8 +385,10 @@ def _get_events(hass, config, start_day, end_day, entity_id=None):
with session_scope(hass=hass) as session:
if entity_id is not None:
entity_ids = [entity_id.lower()]
else:
elif config.get(CONF_EXCLUDE) or config.get(CONF_INCLUDE):
entity_ids = _get_related_entity_ids(session, entities_filter)
else:
entity_ids = None
query = (
session.query(
@ -404,14 +406,21 @@ def _get_events(hass, config, start_day, end_day, entity_id=None):
Events.event_type.in_(ALL_EVENT_TYPES + list(hass.data.get(DOMAIN, {})))
)
.filter((Events.time_fired > start_day) & (Events.time_fired < end_day))
.filter(
)
if entity_ids:
query = query.filter(
(
(States.last_updated == States.last_changed)
& States.entity_id.in_(entity_ids)
)
| (States.state_id.is_(None))
)
)
else:
query = query.filter(
(States.last_updated == States.last_changed)
| (States.state_id.is_(None))
)
prev_states = {}
return list(humanify(hass, yield_events(query), prev_states))
@ -425,7 +434,6 @@ def _get_attribute(hass, entity_id, event, attribute):
def _keep_event(hass, event, entities_filter):
entity_id = None
if event.event_type == EVENT_STATE_CHANGED:
entity_id = event.entity_id
@ -444,20 +452,18 @@ def _keep_event(hass, event, entities_filter):
elif event.event_type == EVENT_LOGBOOK_ENTRY:
event_data = event.data
domain = event_data.get(ATTR_DOMAIN)
entity_id = None
elif event.event_type in hass.data.get(DOMAIN, {}) and not event.data.get(
"entity_id"
):
# If the entity_id isn't described, use the domain that describes
# the event for filtering.
domain = hass.data[DOMAIN][event.event_type][0]
entity_id = None
else:
event_data = event.data
domain = event_data.get(ATTR_DOMAIN)
entity_id = event_data.get("entity_id")
if entity_id:
domain = split_entity_id(entity_id)[0]
if not entity_id and domain:
entity_id = f"{domain}."
@ -556,18 +562,25 @@ def _entry_message_from_event(hass, entity_id, domain, event):
class LazyEventPartialState:
"""A lazy version of core Event with limited State joined in."""
__slots__ = ["_row", "_event_data", "_time_fired"]
__slots__ = [
"_row",
"_event_data",
"_time_fired",
"event_type",
"entity_id",
"state",
"domain",
]
def __init__(self, row):
"""Init the lazy event."""
self._row = row
self._event_data = None
self._time_fired = None
@property
def event_type(self):
"""Type of event."""
return self._row.event_type
self.event_type = self._row.event_type
self.entity_id = self._row.entity_id
self.state = self._row.state
self.domain = self._row.domain
@property
def context_user_id(self):
@ -617,18 +630,3 @@ class LazyEventPartialState:
.get(ATTR_HIDDEN, False)
)
return False
@property
def entity_id(self):
"""Entity id that changed state."""
return self._row.entity_id
@property
def domain(self):
"""Domain of the entity_id that changed state."""
return self._row.domain
@property
def state(self):
"""State of the entity_id that changed state."""
return self._row.state