Skip to content

Refactorfor for less allocation.#13

Open
AureliaDolo wants to merge 2 commits intodarnuria:mainfrom
AureliaDolo:no_alloc
Open

Refactorfor for less allocation.#13
AureliaDolo wants to merge 2 commits intodarnuria:mainfrom
AureliaDolo:no_alloc

Conversation

@AureliaDolo
Copy link
Copy Markdown

@AureliaDolo AureliaDolo commented Aug 2, 2023

Fix #7

@AureliaDolo
Copy link
Copy Markdown
Author

There may be some redundant if branches.

I'm considering whether the first item special case could be dropped.

@AureliaDolo AureliaDolo changed the title Refactorfor less allocation. Refactorfor for less allocation. Aug 2, 2023
@AureliaDolo
Copy link
Copy Markdown
Author

I don't think I can do the same for sub_interval_unchecked as the interval to subtract may span across all elements in self.intervals

Copy link
Copy Markdown

@bnjbvr bnjbvr left a 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 ✨ mostly nits and stylistic comments below. I think the logic is sane (one way to double-check that would be to have fun with a small fuzzer for this function :D). It might be nice to add a doc comment for this function expliciting the invariant that the new interval won't overlap with any existing interval.

Comment thread src/lib.rs Outdated
Comment on lines +131 to +134
if idx == self.intervals.len() {
// previously treated
unreachable!()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: unnecessary because the .get().unwrap() next line will panic the same way

Comment thread src/lib.rs Outdated
unreachable!()
}
// we can unwrap as the case interval is after the last element is treated before
let next = self.intervals.get(idx).unwrap();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: could be simplified as &mut self.intervals[idx]

Comment thread src/lib.rs
/// Add an interval but does not check assume interval is correctly formed
fn add_interval_unchecked(&mut self, interval: &(u64, u64)) {
let mut interval = *interval;
let interval = *interval;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Consider adding a debug_assert! that no intervals in self.intervals overlap with the one to add, since it's an undocumented invariant?

Comment thread src/lib.rs
// it may merge with next

let before = self.intervals[idx];
let after = self.intervals[idx + 1];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe comment that there is a next interval all the time (otherwise we would have fallen under another branch under the if let Some() = last part above)

Comment thread src/lib.rs Outdated
self.intervals.push(interval);
return;
}
if let Some(&first) = self.intervals.first() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: you can use first_mut here (and remove the & in front of &first)...

Comment thread src/lib.rs Outdated
// unwrapping is ok as intervals is not empty

let last = self.intervals.last_mut().unwrap();
*last = (last.0, interval.1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ditto, only updating the right bound

Comment thread src/lib.rs Outdated
new.push(interval);
new.sort();
self.intervals = new;
if let Some(&last) = self.intervals.last() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ditto, last_mut() can be used here

Comment thread src/lib.rs Outdated
let next = self.intervals.get(idx).unwrap();
// interval merges with next
if next.0 == interval.1 {
*self.intervals.get_mut(idx).unwrap() = (interval.0, next.1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

(and no need to take get_mut here with the above suggestion, and we're only modifying the left bound here)

Comment thread src/lib.rs Outdated

// interval merges with before and after
if interval.0 == before.1 && interval.1 == after.0 {
*self.intervals.get_mut(idx).unwrap() = (before.0, after.1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Worth trying to use &mut self.intervals[idx] for definition of before above, and modify it in place here.

Comment thread src/lib.rs
Comment on lines +160 to +169
} else if
// interval merges with after
interval.1 == after.0 {
unreachable!("should have been treated in the error branch before");
// *self.intervals.get_mut(idx + 1).unwrap() = (interval.0, after.1);
} else {
// interval does not merge
unreachable!("should have been treated in the error branch before");
// self.intervals.insert(idx + 1, interval)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: please remove commented code + maybe merge those two elses, since they share the same panic message?

@AureliaDolo AureliaDolo force-pushed the no_alloc branch 3 times, most recently from e0cec53 to 5ded370 Compare January 22, 2024 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate better algorithms for inserting interval and removing

2 participants