Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

dureuill
Copy link
Contributor

@dureuill dureuill commented Jan 11, 2023

Pull Request

Related issue

Relevant to #1841, fixes #3382

What does this PR do?

User standpoint

  • Limit the number of concurrently opened indexes (currently, the number of indexes that can be concurrently opened is computed at startup)
  • When too many an index is opened, the least recently used one is closed and its virtual memory released.
  • This allows a user to have an arbitrary number of indexes of an arbitrary size

Implementation standpoint

  • Added a LRU cache map in index-scheduler::lru. A more complete implementation (eg with helper functions not used here) is available but would better fit a dedicated crate.
  • Use the LRU cache map in the IndexScheduler. To simplify the lifecycle of indexes, they are never removed from the cache when they are in the middle of a resize or delete operation. To achieve this, an intermediate Vec stores the UUIDs of the indexes that are in the middle of such an operation.
  • Upon creating the index scheduler object, compute the total virtual memory that is adressable by using a dichotomic search on the max size of an index. Use this as a base to compute the number of indexes that can be open with 2TiB per index. If the virtual memory address space is lower than 2TiB, then only allow for 1 index of a fraction of that size.

@dureuill dureuill marked this pull request as draft January 11, 2023 18:19
@dureuill dureuill force-pushed the resize-full-indexes branch from d0037d8 to 952d0d1 Compare January 12, 2023 10:01
@dureuill dureuill force-pushed the use-lru branch 2 times, most recently from 911d88f to 1603e29 Compare January 12, 2023 14:30
@dureuill dureuill force-pushed the resize-full-indexes branch from 952d0d1 to a69fbf8 Compare January 25, 2023 08:23
@dureuill dureuill force-pushed the use-lru branch 2 times, most recently from 3f51ffb to e5aeaea Compare January 25, 2023 09:42
@dureuill dureuill added this to the v1.1.0 milestone Jan 25, 2023
@dureuill
Copy link
Contributor Author

I feel like with the tests I did, this PR is now ready for review.

@dureuill dureuill marked this pull request as ready for review January 30, 2023 09:31
@dureuill dureuill force-pushed the resize-full-indexes branch from a69fbf8 to e1cc4e3 Compare February 7, 2023 12:43
@github-actions
Copy link

github-actions bot commented Feb 7, 2023

Uffizzi Preview deployment-14601 was deleted.

Copy link
Member

@Kerollmops Kerollmops left a comment

Choose a reason for hiding this comment

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

Thank you very much, maybe some small changes to do.

@dureuill
Copy link
Contributor Author

dureuill commented Feb 9, 2023

  • Change default index size to 10GiB
  • Default to 100 concurrent indexes in Unixes, 10 in Windows

Comment on lines +528 to +172
if tries >= 100 {
panic!("Too many attempts to close index {name} prior to deletion.")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understood in which case this can happen, and what follows if we panic here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what follows if we panic here?

I expect we will respawn a scheduler thread after some logging but you're right that I should check that.

I'm not sure I understood in which case this can happen

This should be a comment (I will add it), but I see 2 situations this can happen:

  1. There's a bug in the code, and the index is never adequately closed. I believe this actually happened during development, this could happen again during refactoring. It is better to eventually get an error message rather than a full on "infinite loop"
  2. There's a reader that won't relinquish the Index object for more than 600 seconds.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a comment stating the situations where the panic could possibly occur.

I also tested manually triggering a panic at this location. It fails the deletion task, and kills the batch thread, which is renewed for each task, so no other side effect.

Comment on lines 606 to 262
if tries > 100 {
panic!("Too many spurious wake ups while the index is being resized");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a comment stating the situations where the panic could possibly occur.

I also tested manually triggering the panic and trying to search/add documents in an index. In both cases it kills an "actix arbiter" thread and fails the request (not in a very graceful manner, I basically get curl: (56) Recv failure: Connection reset by peer).

It looks like actix respawns the arbiter threads, so we're not at risk of running out of threads in this situation.

@dureuill
Copy link
Contributor Author

Added an update with the following:

  • We compute an "index budget" when the Index scheduler is created, to know how much cumulated virtual memory we can allocate through memmap before exhausting the virtual address space. A fraction of the budget is then split to determine how many indexes can be opened simultaneously in the cache with a size of 2TiB. If that number is 0, then there can be only one index in the cache with a size of whatever budget is available.
  • As computing the budget adds 2 seconds at startup, it is disabled in tests.

This should result in the following:

  • No more performance hit due to index resize, except for users with indexes bigger than 2 TiB (if this impedes your use case, please contact us)
  • Much lower risk of filling the entirety of the cache
  • Adapts to machines with smaller virtual memory address space

I will do a second prototype with these changes soon.


remaining TODO

  • Some comments on the PR left unaddressed
  • "Invasive" logs that are good for the prototype but should be removed before merging
  • Handle the methods that attempt to open all indexes at once
  • Check that the added dynamic budget computation doesn't impede usage for Cloud

@dureuill
Copy link
Contributor Author

dureuill commented Feb 20, 2023

Pushed an update that handles the methods that attempt to open all indexes at once.

There is now a try_for_each_index method that allows to iterate on all indexes. For callers that only needed the names, there is also a new index_names method that doesn't open the indexes at all.

The stats, indexes, dumps routes as well as snapshot creation/import and dump import seem to be fixed by this change.


There is some performance effect to calling stats on a meilisearch with 1000+ indexes: about 8s on Mac (0.8s for 100 indexes, unnoticeable for 10 indexes), about 0.5s on Linux (unnoticeable for 100 indexes or below). I cannot compare with v1 because we couldn't have more than 200 indexes there so the stats route would fail. Interestingly on mac the time for the route to answer decreases when limiting the total virtual memory with ulimit. Possibly the allocator is simply slow for big allocations, whereas Linux' is very fast by comparison on that use case.

Copy link
Member

@Kerollmops Kerollmops left a comment

Choose a reason for hiding this comment

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

Thank you very much!

@dureuill
Copy link
Contributor Author

dureuill commented Feb 23, 2023

TODO:

  • It appears that indexes are not being registered correctly as BeingDeleted currently, this needs checking
  • Rebase on main
  • Squash redundant commits

Follow-ups for subsequent PRs (to be added in the tracking issue and/or opened as different issues):

  • Increased Windows/macOS startup time. This could be mitigated by first trying a budget value that should be "good enough" and skipping the dichotomy if it passes.
  • Degraded stats performance. This could be mitigated by caching the stats of indexes (eg in the tasks db).
  • Finer-grained error handling in the dichotomy: make a difference between allocation errors (continue the dichotomy after marking this value as "bad") and other kinds of errors (stop the dichotomy and report the error to the caller)

Copy link
Member

@Kerollmops Kerollmops left a comment

Choose a reason for hiding this comment

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

Beautiful work @dureuill 🎉 I think we can merge this PR and address your comment (☝️) in other PRs. I let you bors merge.

@dureuill
Copy link
Contributor Author

Thank you for the review @Kerollmops!

bors merge

@bors
Copy link
Contributor

bors bot commented Feb 23, 2023

Build succeeded:

@bors bors bot merged commit ca25904 into main Feb 23, 2023
@bors bors bot deleted the use-lru branch February 23, 2023 15:03
@meili-bot meili-bot added the v1.1.0 PRs/issues solved in v1.1.0 released on 2023-04-03 label Apr 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v1.1.0 PRs/issues solved in v1.1.0 released on 2023-04-03
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Don't limit the number or size of indexes
4 participants