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

feat(sdk): Optimise how LinkedChunk::insert_gap_at works when inserting at first position #3251

Conversation

Hywan
Copy link
Member

@Hywan Hywan commented Mar 20, 2024

Imagine we have this linked chunk:

assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] ['d', 'e', 'f']);

Before the patch, when we were running:

let position_of_d = linked_chunk.item_position(|item| *item == 'd').unwrap();
linked_chunk.insert_gap_at((), position_of_d)?;

it was taking ['d', 'e', 'f'] to split it at index 0, so [] + ['d', 'e', 'f'], and then was inserting a gap in between, thus resulting into:

assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [] [-] ['d', 'e', 'f']);

The problem is that it creates a useless empty chunk. It's a waste of space, and rapidly, of computation. When used with EventCache, this problem occurs every time a backpagination occurs (because it executes a replace_gap_at to insert the new item, and then executes a insert_gap_at if the backpagination contains another prev_batch token).

With this patch, the result of the operation is now:

assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [-] ['d', 'e', 'f']);

The assert_items_eq! macro has been updated to be able to assert empty chunks. The test_insert_gap_at has been updated to test all edge cases.


@Hywan Hywan requested a review from a team as a code owner March 20, 2024 12:43
@Hywan Hywan requested review from bnjbvr and poljar and removed request for a team and bnjbvr March 20, 2024 12:43
Hywan added 2 commits March 20, 2024 13:47
… position.

Imagine we have this linked chunk:

```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] ['d', 'e', 'f']);
```

Before the patch, when we were running:

```rust
let position_of_d = linked_chunk.item_position(|item| *item == 'd').unwrap();
linked_chunk.insert_gap_at((), position_of_d)?;
```

it was taking `['d', 'e', 'f']` to split it at index 0, so `[]` + `['d',
'e', 'f']`, and then was inserting a gap in between, thus resulting
into:

```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [] [-] ['d', 'e', 'f']);
```

The problem is that it creates a useless empty chunk. It's a waste of
space, and rapidly, of computation. When used with `EventCache`, this
problem occurs every time a backpagination occurs (because it executes
a `replace_gap_at` to insert the new item, and then executes a
`insert_gap_at` if the backpagination contains another `prev_batch`
token).

With this patch, the result of the operation is now:

```rust
assert_items_eq!(linked_chunk, ['a'] [-] ['b', 'c'] [-] ['d', 'e', 'f']);
```

The `assert_items_eq!` macro has been updated to be able to assert
empty chunks. The `test_insert_gap_at` has been updated to test all
edge cases.
@Hywan Hywan force-pushed the feat-sdk-event-cache-linked-chunk-insert-gap-at-optim-index-0 branch from 48b8e99 to a248ec7 Compare March 20, 2024 12:47
Copy link
Contributor

@poljar poljar left a comment

Choose a reason for hiding this comment

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

Sorry, took a bit longer since I'm unfamiliar with the code. Left some complaints but overall looks sensible.

crates/matrix-sdk/src/event_cache/linked_chunk.rs Outdated Show resolved Hide resolved
crates/matrix-sdk/src/event_cache/linked_chunk.rs Outdated Show resolved Hide resolved
crates/matrix-sdk/src/event_cache/linked_chunk.rs Outdated Show resolved Hide resolved
crates/matrix-sdk/src/event_cache/linked_chunk.rs Outdated Show resolved Hide resolved
crates/matrix-sdk/src/event_cache/linked_chunk.rs Outdated Show resolved Hide resolved
// insert a new gap chunk, otherwise it would create an empty current items
// chunk. Let's handle this case in particular.
//
// Of course this optimisation applies if there is a previous chunk. Remember
Copy link
Contributor

Choose a reason for hiding this comment

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

From where should we remember this invariant? The docs don't really explain why a gap can't be the first chunk 😅.

I just saw an INVARIANT tag in the constructor which says the same, though doesn't explain the why.

Copy link
Member Author

Choose a reason for hiding this comment

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

Because it's easier ^^. I'll write a longer documentation if LinkedChunk proved to be OK, but for now, we are experimenting with it. I'm postponing these details for next week.

Copy link

codecov bot commented Mar 20, 2024

Codecov Report

Attention: Patch coverage is 63.63636% with 4 lines in your changes are missing coverage. Please review.

Project coverage is 83.67%. Comparing base (fa5ce1d) to head (962c0bf).
Report is 46 commits behind head on main.

Files Patch % Lines
crates/matrix-sdk/src/event_cache/linked_chunk.rs 63.63% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3251      +/-   ##
==========================================
+ Coverage   83.66%   83.67%   +0.01%     
==========================================
  Files         236      236              
  Lines       24470    24480      +10     
==========================================
+ Hits        20472    20483      +11     
+ Misses       3998     3997       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Hywan Hywan enabled auto-merge March 20, 2024 14:57
@Hywan Hywan merged commit c120da7 into matrix-org:main Mar 20, 2024
35 checks passed
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.

2 participants