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

[Enhancement] Using lru cache to limit the number of starlet filesystem instance #55845

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xiangguangyxg
Copy link
Contributor

@xiangguangyxg xiangguangyxg commented Feb 12, 2025

Why I'm doing:

When there are too many partitions, the starlet filesystem instances also has a lot, this may take too many memory.

What I'm doing:

Using lru cache to limit the number of starlet filesystem instance.
Add be config starlet_filesystem_instance_cache_capacity to config the lru cache capacity, default 10000.

Fixes #55765

What type of PR is this:

  • BugFix
  • Feature
  • Enhancement
  • Refactor
  • UT
  • Doc
  • Tool

Does this PR entail a change in behavior?

  • Yes, this PR will result in a change in behavior.
  • No, this PR will not result in a change in behavior.

If yes, please specify the type of change:

  • Interface/UI changes: syntax, type conversion, expression evaluation, display information
  • Parameter changes: default values, similar parameters but with different default values
  • Policy changes: use new policy to replace old one, functionality automatically enabled
  • Feature removed
  • Miscellaneous: upgrade & downgrade compatibility, etc.

Checklist:

  • I have added test cases for my bug fix or my new feature
  • This pr needs user documentation (for new or modified features or behaviors)
    • I have added documentation for my new feature or new function
  • This is a backport pr

Bugfix cherry-pick branch check:

  • I have checked the version labels which the pr will be auto-backported to the target branch
    • 3.4
    • 3.3
    • 3.2
    • 3.1
    • 3.0

Copy link
Contributor

@kevincai kevincai left a comment

Choose a reason for hiding this comment

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

Could have a different issue after current implementation. e.g. A few of the shards/tablets deleted, the filesystem will never be used again. However if the LRU cache still has plenty of slots, the filesystem instance in the cache will not be evicted at all which in turns causes the related objects are not released unless a service restart.

be/src/common/config.h Outdated Show resolved Hide resolved
@xiangguangyxg
Copy link
Contributor Author

xiangguangyxg commented Feb 13, 2025

Could have a different issue after current implementation. e.g. A few of the shards/tablets deleted, the filesystem will never be used again. However if the LRU cache still has plenty of slots, the filesystem instance in the cache will not be evicted at all which in turns causes the related objects are not released unless a service restart.

@kevincai Yes it has the issue. Once a cache slot is used, It will not be released actively, but will be evicted passively. That is a bit like the starcache.

@kevincai
Copy link
Contributor

Could have a different issue after current implementation. e.g. A few of the shards/tablets deleted, the filesystem will never be used again. However if the LRU cache still has plenty of slots, the filesystem instance in the cache will not be evicted at all which in turns causes the related objects are not released unless a service restart.

@kevincai Yes it has the issue. Once a cache slot is used, It will not be released actively, but will be evicted passively. That is a bit like the starcache.

sounds like a LRU with auto expiration perfectly match the use scenario.

Copy link
Contributor

@kevincai kevincai left a comment

Choose a reason for hiding this comment

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

do we want to get the LRU with expiration done in this PR or do it later?

be/src/http/action/update_config_action.cpp Outdated Show resolved Hide resolved
be/src/service/staros_worker.cpp Outdated Show resolved Hide resolved
kevincai
kevincai previously approved these changes Feb 13, 2025
@kevincai
Copy link
Contributor

think about add unit test to ensure this new behavior via syncpoint or failpoint to mockup underlying new_filesystem(). check the correctness of the caching and lru eviction.

wyb
wyb previously approved these changes Feb 14, 2025
@wyb wyb enabled auto-merge (squash) February 14, 2025 02:17
auto-merge was automatically disabled February 14, 2025 09:55

Head branch was pushed to by a user without write access

@xiangguangyxg xiangguangyxg dismissed stale reviews from wyb and kevincai via 8fe6945 February 14, 2025 09:55
@xiangguangyxg
Copy link
Contributor Author

think about add unit test to ensure this new behavior via syncpoint or failpoint to mockup underlying new_filesystem(). check the correctness of the caching and lru eviction.

Added active cache deletion and unit test.

@xiangguangyxg xiangguangyxg force-pushed the fs_instance branch 3 times, most recently from a844b28 to fda98ea Compare February 17, 2025 02:02
if (!fs_or.ok()) {
return fs_or.status();
}
return fs_or->second;
Copy link
Contributor

Choose a reason for hiding this comment

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

the cache key shared_ptr is not held by anyone, so after this function call returned, the shared_ptr cache key will be expired, and the fs instance will be removed from the cache immediately. This is the expected behavior, right? Better add comments here to make this behavior explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, if not hit the fs cache, the new fs instance will be removed from the cache immediately.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added comments.

absl::StatusOr<std::pair<std::shared_ptr<std::string>, std::shared_ptr<fslib::FileSystem>>> StarOSWorker::find_fs_cache(
const std::string& key) {
if (key.empty()) {
return absl::NotFoundError(key + " not found");
Copy link
Contributor

Choose a reason for hiding this comment

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

this will yield an " not found" message, which is odd. make the error message more accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

auto value = static_cast<CacheValue*>(_fs_cache->value(handle));
_fs_cache->release(handle);

return std::make_pair(value->key.lock(), value->fs);
Copy link
Contributor

Choose a reason for hiding this comment

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

what if the value->key is expired? the value->key.lock() will return an empty shared_ptr.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this behavior is ok ? do you mean an error status should be returned in this situation ?

Copy link
Contributor

Choose a reason for hiding this comment

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

it will be ok, but then the caller will get a shared_ptr of the empty string. Shall reset the value->key or reset the value item with a valid item there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the caller will get an empty key shared_ptr and a valid fs instance in this situation. It means the cache item is about to be removed but it is not yet removed by other thread. If we reset the value->key, It will also be removed by other thread.

Copy link
Contributor

Choose a reason for hiding this comment

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

so what should do? take it as cache miss and rebuild the fs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the current code is like taking it as cache miss but reuse the fs instance.

Copy link
Contributor Author

@xiangguangyxg xiangguangyxg Feb 18, 2025

Choose a reason for hiding this comment

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

added some comments to explain this situation.

Copy link

[Java-Extensions Incremental Coverage Report]

pass : 0 / 0 (0%)

Copy link

[FE Incremental Coverage Report]

pass : 0 / 0 (0%)

Copy link

[BE Incremental Coverage Report]

fail : 59 / 76 (77.63%)

file detail

path covered_line new_line coverage not_covered_line_detail
🔵 be/src/http/action/update_config_action.cpp 1 6 16.67% [373, 374, 375, 376, 378]
🔵 be/src/service/staros_worker.cpp 57 69 82.61% [87, 88, 89, 144, 240, 272, 273, 274, 278, 386, 387, 418]
🔵 be/src/service/staros_worker.h 1 1 100.00% []

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[shared-data] create table failed with hdfs storage volume
3 participants