mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Significantly reduce clock_gettime syscalls on platforms with broken vdso (#81257)
This commit is contained in:
parent
8416cc1906
commit
1589c06203
@ -3,13 +3,13 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
from bleak import BleakError
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.debounce import Debouncer
|
||||
from homeassistant.util.dt import monotonic_time_coarse
|
||||
|
||||
from . import BluetoothChange, BluetoothScanningMode, BluetoothServiceInfoBleak
|
||||
from .passive_update_processor import PassiveBluetoothProcessorCoordinator
|
||||
@ -94,7 +94,7 @@ class ActiveBluetoothProcessorCoordinator(
|
||||
"""Return true if time to try and poll."""
|
||||
poll_age: float | None = None
|
||||
if self._last_poll:
|
||||
poll_age = time.monotonic() - self._last_poll
|
||||
poll_age = monotonic_time_coarse() - self._last_poll
|
||||
return self._needs_poll_method(service_info, poll_age)
|
||||
|
||||
async def _async_poll_data(
|
||||
@ -124,7 +124,7 @@ class ActiveBluetoothProcessorCoordinator(
|
||||
self.last_poll_successful = False
|
||||
return
|
||||
finally:
|
||||
self._last_poll = time.monotonic()
|
||||
self._last_poll = monotonic_time_coarse()
|
||||
|
||||
if not self.last_poll_successful:
|
||||
self.logger.debug("%s: Polling recovered")
|
||||
|
@ -7,7 +7,6 @@ from dataclasses import replace
|
||||
from datetime import datetime, timedelta
|
||||
import itertools
|
||||
import logging
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Any, Final
|
||||
|
||||
from bleak.backends.scanner import AdvertisementDataCallback
|
||||
@ -22,6 +21,7 @@ from homeassistant.core import (
|
||||
)
|
||||
from homeassistant.helpers import discovery_flow
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.util.dt import monotonic_time_coarse
|
||||
|
||||
from .advertisement_tracker import AdvertisementTracker
|
||||
from .const import (
|
||||
@ -69,7 +69,7 @@ APPLE_START_BYTES_WANTED: Final = {
|
||||
APPLE_DEVICE_ID_START_BYTE,
|
||||
}
|
||||
|
||||
MONOTONIC_TIME: Final = time.monotonic
|
||||
MONOTONIC_TIME: Final = monotonic_time_coarse
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -6,7 +6,6 @@ from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import platform
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
import async_timeout
|
||||
@ -22,6 +21,7 @@ from dbus_fast import InvalidMessageError
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.util.dt import monotonic_time_coarse
|
||||
from homeassistant.util.package import is_docker_env
|
||||
|
||||
from .const import (
|
||||
@ -35,7 +35,7 @@ from .models import BaseHaScanner, BluetoothScanningMode, BluetoothServiceInfoBl
|
||||
from .util import adapter_human_name, async_reset_adapter
|
||||
|
||||
OriginalBleakScanner = bleak.BleakScanner
|
||||
MONOTONIC_TIME = time.monotonic
|
||||
MONOTONIC_TIME = monotonic_time_coarse
|
||||
|
||||
# or_patterns is a workaround for the fact that passive scanning
|
||||
# needs at least one matcher to be set. The below matcher
|
||||
|
@ -2,11 +2,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import time
|
||||
|
||||
from bluetooth_auto_recovery import recover_adapter
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.util.dt import monotonic_time_coarse
|
||||
|
||||
from .const import (
|
||||
DEFAULT_ADAPTER_BY_PLATFORM,
|
||||
@ -29,7 +29,7 @@ async def async_load_history_from_system() -> dict[str, BluetoothServiceInfoBlea
|
||||
|
||||
bluez_dbus = BlueZDBusObjects()
|
||||
await bluez_dbus.load()
|
||||
now = time.monotonic()
|
||||
now = monotonic_time_coarse()
|
||||
return {
|
||||
address: BluetoothServiceInfoBleak(
|
||||
name=history.advertisement_data.local_name
|
||||
|
@ -19,6 +19,7 @@ from homeassistant.components.bluetooth import (
|
||||
)
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.util.dt import monotonic_time_coarse
|
||||
|
||||
TWO_CHAR = re.compile("..")
|
||||
|
||||
@ -84,7 +85,7 @@ class ESPHomeScanner(BaseHaScanner):
|
||||
@callback
|
||||
def async_on_advertisement(self, adv: BluetoothLEAdvertisement) -> None:
|
||||
"""Call the registered callback."""
|
||||
now = time.monotonic()
|
||||
now = monotonic_time_coarse()
|
||||
address = ":".join(TWO_CHAR.findall("%012X" % adv.address)) # must be upper
|
||||
name = adv.name
|
||||
if prev_discovery := self._discovered_device_advertisement_datas.get(address):
|
||||
|
@ -4,7 +4,9 @@ from __future__ import annotations
|
||||
import bisect
|
||||
from contextlib import suppress
|
||||
import datetime as dt
|
||||
import platform
|
||||
import re
|
||||
import time
|
||||
from typing import Any
|
||||
import zoneinfo
|
||||
|
||||
@ -13,6 +15,7 @@ import ciso8601
|
||||
DATE_STR_FORMAT = "%Y-%m-%d"
|
||||
UTC = dt.timezone.utc
|
||||
DEFAULT_TIME_ZONE: dt.tzinfo = dt.timezone.utc
|
||||
CLOCK_MONOTONIC_COARSE = 6
|
||||
|
||||
# EPOCHORDINAL is not exposed as a constant
|
||||
# https://github.com/python/cpython/blob/3.10/Lib/zoneinfo/_zoneinfo.py#L12
|
||||
@ -461,3 +464,26 @@ def _datetime_ambiguous(dattim: dt.datetime) -> bool:
|
||||
assert dattim.tzinfo is not None
|
||||
opposite_fold = dattim.replace(fold=not dattim.fold)
|
||||
return _datetime_exists(dattim) and dattim.utcoffset() != opposite_fold.utcoffset()
|
||||
|
||||
|
||||
def __monotonic_time_coarse() -> float:
|
||||
"""Return a monotonic time in seconds.
|
||||
|
||||
This is the coarse version of time_monotonic, which is faster but less accurate.
|
||||
|
||||
Since many arm64 and 32-bit platforms don't support VDSO with time.monotonic
|
||||
because of errata, we can't rely on the kernel to provide a fast
|
||||
monotonic time.
|
||||
|
||||
https://lore.kernel.org/lkml/20170404171826.25030-1-marc.zyngier@arm.com/
|
||||
"""
|
||||
return time.clock_gettime(CLOCK_MONOTONIC_COARSE)
|
||||
|
||||
|
||||
monotonic_time_coarse = time.monotonic
|
||||
with suppress(Exception):
|
||||
if (
|
||||
platform.system() == "Linux"
|
||||
and abs(time.monotonic() - __monotonic_time_coarse()) < 1
|
||||
):
|
||||
monotonic_time_coarse = __monotonic_time_coarse
|
||||
|
@ -2,6 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
@ -719,3 +720,8 @@ def test_find_next_time_expression_tenth_second_pattern_does_not_drift_entering_
|
||||
assert (next_target - prev_target).total_seconds() == 60
|
||||
assert next_target.second == 10
|
||||
prev_target = next_target
|
||||
|
||||
|
||||
def test_monotonic_time_coarse():
|
||||
"""Test monotonic time coarse."""
|
||||
assert abs(time.monotonic() - dt_util.monotonic_time_coarse()) < 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user