-
Notifications
You must be signed in to change notification settings - Fork 7
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
Optimise ranges.any_overlapping
#184
Conversation
3eeb353
to
b09a2f6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, well done! 👏
CHANGELOG.md
Outdated
@@ -2,6 +2,8 @@ | |||
|
|||
## Unreleased | |||
|
|||
- Optimise the `ranges.any_overlapping` function [#184](https://github.com/octoenergy/xocto/pull/184). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Optimise the `ranges.any_overlapping` function [#184](https://github.com/octoenergy/xocto/pull/184). | |
- Improve the performance of the `ranges.any_overlapping` function (with some benchmark showing a >100x speed up) [#184](https://github.com/octoenergy/xocto/pull/184). |
or any similar phrasing would give a better idea of the actual change.
xocto/ranges.py
Outdated
return True | ||
range_set.add(range) | ||
stack: list[Range[T]] = [] | ||
for range in sorted(ranges): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests don't cover non-consecutive overlapping ranges which is important to highlight that this sorted()
call is necessary.
class TestAnyOverlapping:
...
@pytest.mark.parametrize(
"ranges_",
[
[
ranges.Range(0, 2),
ranges.Range(4, 5), # Added this to ensure the overlapping ranges are not adjacent.
ranges.Range(1, 3),
],
[
ranges.Range(
0, 2, boundaries=ranges.RangeBoundaries.INCLUSIVE_INCLUSIVE
),
ranges.Range(2, 4),
],
],
)
def test_returns_true_if_and_ranges_overlap_non_consecutive(self, ranges_):
assert ranges.any_overlapping(ranges_)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes nice, added
xocto/ranges.py
Outdated
stack: list[Range[T]] = [] | ||
for range in sorted(ranges): | ||
if len(stack) == 0: | ||
stack.append(range) | ||
else: | ||
if stack[-1].intersection(range): | ||
return True | ||
else: | ||
stack.append(range) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to keep a stack as we're only looking at the last item:
stack: list[Range[T]] = [] | |
for range in sorted(ranges): | |
if len(stack) == 0: | |
stack.append(range) | |
else: | |
if stack[-1].intersection(range): | |
return True | |
else: | |
stack.append(range) | |
prev_range: Range[T] | None = None | |
for range in sorted(ranges): | |
if prev_range is not None and prev_range & range: | |
return True | |
prev_range = range |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True! That even helped the performance a little more 👍
99c0097
to
fcf46fb
Compare
This is > 100x faster now..!
fcf46fb
to
2670ac0
Compare
This PR optimises the
ranges.any_overlapping
function. It usespytest-benchmark
to measure the improvement. The resulting function is >100x faster for this benchmark..!Kraken: This function is often used to determine whether there are overlaps in meter readings etc and has a significant impact on costing performance.