-
-
Notifications
You must be signed in to change notification settings - Fork 73
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
high resource usage in the housekeeper #154
Comments
Hi. Thank you for reporting the issue. Which OS and CPU architecture did you use? Perhaps Linux x86_64? And you used a multi-core machine, right? When moka cache is not busy (including idle), its housekeeper task will run every 0.3 seconds. If cache is idle, it will spend very little time to run because there is no work to do. I see it takes only 0.05% of the space in the flamegraph. I do not have answer yet, but I found the followings:
If I understand correctly, the system spent lots of time (?) in Maybe If so, I could try different platforms without |
It's on linux x86_64 yes |
A quick update: I am currently investigating why the system spent lots of time in Linux I created a testing environment at Amazon EC2, but have not had time to write a test program to reproduce the issue:
I read relevant codes in scheduled-thread-pool, parking_lot and parking_lot_core crates. I also read some blog articles to learn very basic of Linux futex. My current theory (not verified) is that spurious wakeups are occurring in
|
maybe it's a function of how busy the CPUs are yes. In my initial tests I limit the number of cores used by the router like this: https://github.com/apollographql/router/blob/main/apollo-router/src/executable.rs#L139-L146 |
Hi. Sorry for the slow progress. I was busy on finalizing Moka v0.9.0. I released it so I hope I have more time now. I wrote a simple program using scheduled-thread-pool crate with a modified parking_lot crate to check if there were spurious wakeups. However, I could not observe/reproduce the issue with that simple program. I think I will change my direction now. Instead of keep investigating this, I will add an option to remove the thread pools from Some people have already suggested me not to have thread pools by default, and make the cache to use client threads to drive the housekeeping jobs. I checked Moka cache usage in Apollo router, and found that it does not use any advanced features that Moka provides. So removing the thread pools for that specific use case will be very easy. I also found that you are moving away from Moka for the generic response cache layer (the cache-tools branch). Is this right? How about the APQ? Will you continue using Moka or not? |
the cache-tools branch is about factoring the various cache implementations in the router (there were 5 different ones when I started that work 😅 ) around one cache interface that can have multiple levels, in memory and external (redis, memcached). If there's one point that would motivate me to move away from moka, it's that it feels too complicated for me to go and fix quickly during an incident. But that's not an inconvenient of the library itself, you chose to cover a lot of ground in one coherent implementation. An example here: with the |
Hi. Thank you very much for sharing your thoughts. I am not aware of any library that handles the multi level (tiers) of caches in Rust, but I hope you will find one. I have not got idea how the tiered cache in the cache-tool branch would work. I will read the code closely and try to figure out. In the latest version of Moka (v0.9.0), I added support for eviction listener callback function. That feature was requested by multiple users. I wondered if it will be useful when implementing a tiered cache. The listener can be used to move an entry evicted from Moka cache to an external cache. So I wrote an example tiered cache implementation here, which uses Moka as the primary cache and Redis as the secondary cache: I am not sure if it can fit your needs; I guess not. I also found some issues (limitations) in the current API and internal design. I listed them up in the "Limitations" section of the README. I hope we can solve them in the future. I agree that Moka cache's implementation is complicated. I chose to go in the direction of providing convenient features requested by users. I also put my knowledge and ten-year experience in distributed key-value and object stores to Moka cache to make it more performant. But this also makes it more complicated. My hope is that it becomes mature enough so that nobody have to go into and quickly fix it. On the other hand, a few users have asked for a much simpler version of cache; like a I am thinking to move it to a separate crate to make it clear that it is a simpler version. Maybe I will make it even simpler than now. I hope you might be interested in it. |
I am working on it here: #165 You can try it by doing the followings: Modify [dependencies]
moka = { git = "https://github.com/moka-rs/moka", branch = "disable-housekeeper-threads" } When creating a cache instance, set use moka::sync::Cache;
let cache = Cache::builder()
.max_capacity(MAX_CAPACITY)
.thread_pool_enabled(false)
.build(); For backward compatibility, |
I have published Moka v0.9.3 with this feature. (doc) I will keep this issue open to investigate the original issue. |
Closing as complete.
v0.12.0 has major breaking changes. Please read the MIGRATION-GUIDE.md for details. |
hi, we're using moka in a query cache in the Apollo router, and we are seeing high CPU usage in the housekeeper code, as shown in that flamegraph of a benchmark that uses one core and does not insert or get anything from the moka cache(the large tower on the left is the housekeeper):
With 4 cores, It is much lower, but still 2.45% of sampled time, for a cache that is doing nothing:
do you have an idea why it would cost that much to run the housekeeper?
The text was updated successfully, but these errors were encountered: