Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make unit converter use a factory to avoid looking up the ratios each conversion #93706

Merged
merged 34 commits into from May 29, 2023

Conversation

bdraco
Copy link
Member

@bdraco bdraco commented May 28, 2023

Proposed change

With statistics we are doing the same conversion for each data point, and we currently have to do lookups every time to do the convert. Since its the same to/from unit over and over we can use a factory pattern to avoid all but the first set of lookups (unless its already in the LRU).

I added LRUs to avoid building the converters over and over since we also use this in sensor to convert units. It most cases we end up with ~20-30 tiny cached converter functions which uses less memory than most of our python modules.

After this change, all the unit conversion no longer show in all the statistics profiling because they are too small to be included. The flame on 1939 no longer has a sub-flame for the conversion:

Screenshot 2023-05-28 at 11 03 07 AM

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
  • Untested files have been added to .coveragerc.

To help with the load of incoming pull requests:

With statistics we are doing the same conversion over and over
and we have do do lookups every time to do the convert. Since
its the same to/from unit over and over we can use a factory
pattern to avoid all the lookups
@home-assistant
Copy link

Hey there @home-assistant/core, mind taking a look at this pull request as it has been labeled with an integration (recorder) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of recorder can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign recorder Removes the current integration label and assignees on the pull request, add the integration domain after the command.

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

LRU stats after 1 minute

2023-05-28 15:55:08.674 CRITICAL (SyncWorker_16) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory at 0x7fc6cf1b7e20> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=105, misses=7, maxsize=128, currsize=7)
2023-05-28 15:55:08.675 CRITICAL (SyncWorker_16) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory_allow_none at 0x7fc6cf1b7f60> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=3, misses=1, maxsize=128, currsize=1)
2023-05-28 15:55:08.675 CRITICAL (SyncWorker_16) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.get_unit_ratio at 0x7fc6cef940e0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=81, misses=8, maxsize=128, currsize=8)
2023-05-28 15:55:08.676 CRITICAL (SyncWorker_16) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory at 0x7fc6cef945e0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=364, misses=5, maxsize=8, currsize=5)
2023-05-28 15:55:08.676 CRITICAL (SyncWorker_16) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory_allow_none at 0x7fc6cef94720> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=0, misses=0, maxsize=8, currsize=0)

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

LRU stats from another production system after 2 minutes

2023-05-28 15:56:41.949 CRITICAL (SyncWorker_6) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory at 0x7f67fa4fbce0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=807, misses=22, maxsize=128, currsize=22)
2023-05-28 15:56:41.950 CRITICAL (SyncWorker_6) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory_allow_none at 0x7f67fa4fbe20> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
2023-05-28 15:56:41.950 CRITICAL (SyncWorker_6) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.get_unit_ratio at 0x7f67fa4fbf60> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=79, misses=24, maxsize=128, currsize=24)
2023-05-28 15:56:41.951 CRITICAL (SyncWorker_6) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory at 0x7f67fa2dc4a0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=621, misses=4, maxsize=8, currsize=4)
2023-05-28 15:56:41.951 CRITICAL (SyncWorker_6) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory_allow_none at 0x7f67fa2dc5e0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=335, misses=1, maxsize=8, currsize=1)

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

new_convert

Converter implementation for use outside of stats doesn't show any measurable performance regression

@bdraco bdraco changed the title Make a unit converter use a factory Make unit converter use a factory to avoid looking up the ratios each conversion May 28, 2023
@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

Tests for gdacs are failing because they aren't using pytest.approx for the float conversion

We could do two operations to reduce the floating point conversion loss but that might be a bit overkill to preserve decimal places beyond the actual precision

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

refactored to retain the exact same floating point conversion behavior

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

still effectively the same after refactor to make it more dry and avoid the double conversion float loss
2ndpass

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

stats profile looks great as well. also gone from there.

@bdraco
Copy link
Member Author

bdraco commented May 28, 2023

lru stats look excellent

2023-05-28 22:12:32.744 CRITICAL (SyncWorker_5) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory at 0x7f96c0287d80> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=3946, misses=27, maxsize=128, currsize=27)
2023-05-28 22:12:32.744 CRITICAL (SyncWorker_5) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.converter_factory_allow_none at 0x7f96c0287f60> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=17, misses=2, maxsize=128, currsize=2)
2023-05-28 22:12:32.745 CRITICAL (SyncWorker_5) [homeassistant.components.profiler] Cache stats for lru_cache <function BaseUnitConverter.get_unit_ratio at 0x7f96c00640e0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=1287, misses=2, maxsize=128, currsize=2)
2023-05-28 22:12:32.745 CRITICAL (SyncWorker_5) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory at 0x7f96c00645e0> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=3006, misses=4, maxsize=8, currsize=4)
2023-05-28 22:12:32.746 CRITICAL (SyncWorker_5) [homeassistant.components.profiler] Cache stats for lru_cache <function TemperatureConverter.converter_factory_allow_none at 0x7f96c0064720> at /usr/src/homeassistant/homeassistant/util/unit_conversion.py: CacheInfo(hits=55, misses=1, maxsize=8, currsize=1)

@bdraco bdraco marked this pull request as ready for review May 28, 2023 22:13
@bdraco bdraco requested review from a team and epenet as code owners May 28, 2023 22:13
@bdraco
Copy link
Member Author

bdraco commented May 29, 2023

Test failure is unrelated

Copy link
Member

@frenck frenck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @bdraco 👍

../Frenck

@frenck frenck merged commit 2f1f32f into dev May 29, 2023
52 checks passed
@frenck frenck deleted the convert_factory branch May 29, 2023 18:50
@bdraco
Copy link
Member Author

bdraco commented May 29, 2023

Thanks. This one will make quite a difference for some use cases where the display and stored units differ

@github-actions github-actions bot locked and limited conversation to collaborators May 30, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants