-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Implement automatic garbage collection for the disk cache #5139
Comments
I will look into implementing this, unless someone else is faster than me. |
I don't have time to work on this right now. @davido, if you don't get around to working on this in the next 2-3 weeks, I'm happy to pick this up. |
During migration from Buck to Bazel we lost action caches activation per default. For one, local action cache wasn't implemented in Bazel, for another, there was no option to specify HOME directory. I fixed both problems and starting with Bazel 0.14.0 both features are included in released Bazel version: [1], [2]. There is still one not implemented option, limit the cache directory with max size: [3]. But for now the advantage to activate the caches per default far outweigh the disadvantage of unlimited growth of size of cache directory beyound imaginary max size of say 10 GB. In meantime we add a warning to watch the size of the directory cache and periodically clean cache directory: $ rm -rf ~/.gerritcodereview/bazel-cache/cas/* [1] https://bazel-review.googlesource.com/#/c/bazel/+/16810 [2] bazelbuild/bazel#4852 [3] bazelbuild/bazel#5139 Change-Id: I42e8f6fb9770a5976751ffef286c0fe80b75cf93
Not finished, but had an initial stab: RNabel/bazel@baseline-0.16.1...RNabel:feature/5139-implement-disk-cache-size (this is mostly plumbing and figuring out where to put the logic it definitely doesn't work) I figured the simplest solution is an LRU relying on the file system for access times and modification times. Unfortunately, access times are not available on windows through Bazel's file system abstraction. One alternative would be a simple database, but that feels like overkill here. @davido, what do you think is the best solution here? Also happy to write up a brief design doc for discussion. |
What do you guys think about just running a local proxy service that has this functionality already implemented? For exampe: https://github.com/Asana/bazels3cache or https://github.com/buchgr/bazel-remote? One could then point Bazel to it using --remote_http_cache=http://localhost:XXX. We could even think about Bazel automatically launching such a service if it is not running already. |
I think @aehlig solved this problem for the repository cache. Maybe you can
borrow his implementation here as well.
@buchgr, I feel this is core Bazel functionality and in my humble opinion
outsourcing it isn’t the right direction. People at my company are often
amazed Bazel doesn’t have this fully supported out of the box.
…On Tue, 11 Sep 2018 at 13:14 Robin Nabel ***@***.***> wrote:
Not finished, but had an initial stab: RNabel/bazel@
baseline-0.16.1...RNabel:feature/5139-implement-disk-cache-size
<RNabel@baseline-0.16.1...RNabel:feature/5139-implement-disk-cache-size>
(this is mostly plumbing and figuring out where to put the logic it
definitely doesn't work)
I figured the simplest solution is an LRU relying on the file system for
access times and modification times. Unfortunately, access times are not
available on windows through Bazel's file system abstraction. One
alternative would be a simple database, but that feels like overkill here.
@davido <https://github.com/davido>, what do you think is the best
solution here? Also happy to write up a brief design doc for discussion.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#5139 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUIF_yJPnfWAoPzJufI6WwjckenYmNUks5uZ4zygaJpZM4TvSgK>
.
|
@ittaiz, what solution are you talking about? What we have so far for the repository cache is that the file gets touched on every cache hit (see e0d8035), so that deleting the oldest files would be a cleanup; the latter, however, is not yet implemented, for lack of time. For the repository cache, it is also a slightly different story, as clean up should always be manual; upstream might have disappeared, to the cache might be last copy of the archive available to the user—and we don't want to remove that on the fly. |
I would be interested to learn more about why you think so. |
@aehlig sorry, my bad. You are indeed correct.
@buchgr,
I think so because I think a disk cache is a really basic feature of Bazel
and the fact that it doesn’t work like this by default is IMHO a leaky
abstraction (of how exactly the cached work) and influenced greatly by the
fact that googlers work mainly (almost exclusively?) with remote execution.
I’ve explained bazel to tens maybe hundreds of people. All of them were
surprised disk cache isn’t out of the box (eviction wise and also plans
wise like we discussed).
…On Tue, 11 Sep 2018 at 16:24 Jakob Buchgraber ***@***.***> wrote:
outsourcing it isn’t the right direction
I would be interested to learn more about why you think so.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5139 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUIF-CT0FTFJOrIqJUvj5rmeKlfT502ks5uZ7mKgaJpZM4TvSgK>
.
|
@ittaiz However, I am not convinced that Bazel should have a disk cache built in but |
Thanks for the clarification and I appreciate the discussion.
I think that users don’t want to operate many different tools and servers
locally. They want a build tool that works.
The main disadvantage I see is that it sounds like you’re offering a
cleaner design at the user’s expense.
…On Thu, 13 Sep 2018 at 22:56 Jakob Buchgraber ***@***.***> wrote:
@ittaiz <https://github.com/ittaiz>
the disk cache is indeed a leaky abstraction that was mainly added because
it was easy to do so. I agree that if Bazel should have a disk cache in
the long
term, then it should also support read/write through to a remote cache and
garbage collection.
However, I am not convinced that Bazel should have a disk cache built in
but
instead this functionality could also be handled by another program running
locally. So I am trying to better understand why this should be part of
Bazel.
Please note that there are no immediate plans to remove it and we will not
do
so without a design doc of an alternative. I am mainly interested in
kicking off
a discussion.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5139 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUIF8ewS8x09uklzku9r6-aS6zUeLqYks5uarh4gaJpZM4TvSgK>
.
|
I partly agree. I'd argue in many companies that would change as you would typically have an IT department configuring workstations and laptops.
I think that also depends. I'd say that if one only wants to use the local disk cache then I agree that providing two flags is as friction less as it gets. However, I think it's possible that most disk cache users will also want to do remote caching/execution and that for them this might not be noteworthy additional work. So I think there are two possible future scenarios for the disk cache:
I think 1) makes sense if we think that the disk cache will be a standalone feature that a lot of people will find useful on its own and if so I think its worth the effort to implement this in Bazel. For 2) I am not so sure as I can see several challenges that might be better solved in a separate process:
So I think it might make sense for us to think about having a standard local caching proxy that's a separate process and that can be operated independently and/or that Bazel can launch automatically for improved usability might be an idea worth thinking about. |
Is there any plan to roll out the "virtual remote filesystem" soon? I am interested to learn more about it and can help if needed. We are hitting network speed bottleneck. |
yep, please follow #6862 |
any plan of implementing the max size feature or a garbage collector for the local cache? |
This is a much needed feature in order to use Remote Builds without the Bytes, since naively cleaning up the disk cache results in build failures. |
This will be used by the implementation of garbage collection for the disk cache, as discussed in #5139 and the linked design doc. I judge this to be preferred over https://github.com/xerial/sqlite-jdbc for the following reasons: 1. It's a much smaller dependency. 2. The JDBC API is too generic and becomes awkward to use when dealing with the peculiarities of SQLite. 3. We can (more easily) compile it from source for all host platforms, including the BSDs. PiperOrigin-RevId: 628046749 Change-Id: I17bd0547876df460f48af24944d3f7327069375f
How far are we from getting this done? rc1 is scheduled for next Monday, but judging by the urgency and remaining work, we can push it out a bit. |
This will be used by the implementation of garbage collection for the disk cache, as discussed in bazelbuild#5139 and the linked design doc. I judge this to be preferred over https://github.com/xerial/sqlite-jdbc for the following reasons: 1. It's a much smaller dependency. 2. The JDBC API is too generic and becomes awkward to use when dealing with the peculiarities of SQLite. 3. We can (more easily) compile it from source for all host platforms, including the BSDs. PiperOrigin-RevId: 628046749 Change-Id: I17bd0547876df460f48af24944d3f7327069375f
Unfortunately, I ran into some difficulties and this is not ready yet. I'm aiming to build up to a minimally useful implementation within the next few days. If this FR is the only reason we would delay rc1, it would be fine to get it out today, under the (not so unreasonable?) assumption that there will be an rc2 that the remaining changes can still make it into. |
Here is my workaround. find /path/to/bazel-cache -amin +1440 -delete 2>/dev/null || true The command searches for files in the /path/to/bazel-cache directory that have not been accessed in the last 1440 minutes (24 hours) and deletes them. |
It won't help you to "trim to size" if you need to fit cache below a certain threshold of disk space. |
@peaceiris I don't know for certain, but our experience strongly suggests that any process that deletes files directly from the cache like that is doomed to cause strange failures sooner or later. It may depend on specifically what tasks bazel runs; we've found that code coverage jobs are especially brittle. |
Yes, I think that's right. So we're looking forward to implementing this feature in Bazel. |
Unfortunately we won't have enough time for this in 7.2.0; postponing to 7.3.0 |
Thx, but this is not a good walkaround for this problem because you cannot promise what files you will delete here and different cache files have connections. If somebody plans to try it, please stay careful. |
7.3.0 is not that far as we think. Is there a way to try this with nightly builds or so? |
Unfortunately we didn't have time for this in 7.3.0 either -- @tjgq has been occupied by other work. This may need to wait until 7.4.0 or even 8.0.
We do have rolling releases, which are cut every ~2 weeks. But I'm not sure if this feature in particular is ready for even preliminary testing. |
I really appreciate everyone who is looking into this, and I left comments in the design doc. I am in a similar boat as @ittaiz and trying to help a 100-person company improve their build infrastructure. Having a default local cache, with GC, enabled by default, is all very valuable for Bazel in this environment. I was also surprised that it doesn't already work this way. |
Status update: Bazel 8 is going to ship with built-in garbage collection, with knobs to set a maximum size in bytes, a maximum age for cache entries, or both. However, contrary to previously announced plans, we're going to provide an offline implementation, whereby garbage collection occurs in the background while the Bazel server is idle. It therefore remains possible for the set limits to be exceeded during the course of a build, which is a necessary tradeoff to preserve build performance. We will also provide an official tool to run a garbage collection manually, for users who prefer to have more control. The documentation page at https://bazel.build/remote/caching#disk-cache will soon be updated with the details. The more sophisticated online implementation described in #5139 (comment) is, unfortunately, extremely challenging to implement across all supported operating systems, while providing hard size guarantees, allowing multiple Bazel processes to share the same disk cache, and preserving current build performance in all scenarios. It's unclear to me at this point that all of these goals can be simultaneously fulfilled. |
Thanks for the update.
And maybe document what will happen if the sizes isn't set right. Hopefully something like, "he current upload will be lost, but there won't be any curruption and nothing will crash. So the only consequence is the recomputation of some entry". |
I think the best rule of thumb we can give is: prior to starting a build, you must have enough disk space to fit the entirety of the build outputs twice (one time for the contents of If you do run out of space during a build, it's always safe to retry it after you have (manually) recovered some space. Bazel is designed to produce a correct build result regardless of the starting conditions. |
*** Reason for rollback *** The experiment with using sqlite didn't pan out. We might find other uses for it in the future, but we can always resurrect it from version control; no need to saddle Bazel with the additional dependency until then. *** Original change description *** Implement a JNI wrapper around SQLite. This will be used by the implementation of garbage collection for the disk cache, as discussed in #5139 and the linked design doc. I judge this to be preferred over https://github.com/xerial/sqlite-jdbc for the following reasons: 1. It's a much smaller dependency. 2. The JDBC API is too generic and becomes awkward to use when dealing with the peculiarities of SQLite. 3. We can (more easily) compile it from source for all host platforms, including the BSDs. *** PiperOrigin-RevId: 679600756 Change-Id: Ic3748fa30404a31504426c523c9b9a60ec451863
+1 to this general perspective. Developers will generally maintain enough free disk space that they don't need to be right at the limit all the time. As such, Bazel doesn't need to go overboard on the disk space limit, whenever it cuts into other desiderata. |
*** Reason for rollback *** The experiment with using sqlite didn't pan out. We might find other uses for it in the future, but we can always resurrect it from version control; no need to saddle Bazel with the additional dependency until then. *** Original change description *** Implement a JNI wrapper around SQLite. This will be used by the implementation of garbage collection for the disk cache, as discussed in bazelbuild#5139 and the linked design doc. I judge this to be preferred over https://github.com/xerial/sqlite-jdbc for the following reasons: 1. It's a much smaller dependency. 2. The JDBC API is too generic and becomes awkward to use when dealing with the peculiarities of SQLite. 3. We can (more easily) compile it from source for all host platforms, including the BSDs. *** PiperOrigin-RevId: 679600756 Change-Id: Ic3748fa30404a31504426c523c9b9a60ec451863
*** Reason for rollback *** The experiment with using sqlite didn't pan out. We might find other uses for it in the future, but we can always resurrect it from version control; no need to saddle Bazel with the additional dependency until then. *** Original change description *** Implement a JNI wrapper around SQLite. This will be used by the implementation of garbage collection for the disk cache, as discussed in #5139 and the linked design doc. I judge this to be preferred over https://github.com/xerial/sqlite-jdbc for the following reasons: 1. It's a much smaller dependency. 2. The JDBC API is too generic and becomes awkward to use when dealing with the peculiarities of SQLite. 3. We can (more easily) compile it from source for all host platforms, including the BSDs. *** PiperOrigin-RevId: 679600756 Change-Id: Ic3748fa30404a31504426c523c9b9a60ec451863
@tjgq So sqlite won't be used for GC, right? |
@dkashyn-sfdc Correct. I experimented with speeding up filesystem scans by using a sqlite database as an index, but it's very tricky to do while observing all of the constraints I mentioned above, and in the end I felt that it had an unfavorable complexity/utility ratio (so it will ship without an index, just a parallelized filesystem scan). |
To close the loop: in addition to shipping in 8.0.0, this feature has also been cherry-picked into 7.4.0, and the documentation has been updated accordingly. |
Break out from #4870.
Bazel can use a local directory as a remote cache via the
--disk_cache
flag.We want it to also be able to automatically clean the cache after a size threshold
has been reached. It probably makes sense to clean based on least recently used
semantics.
@RNabel would you want to work on this?
@RNabel @davido
The text was updated successfully, but these errors were encountered: