-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support prompt expiration via an optional scheduler thread (fixes #195)
Typically the cache using an amortized maintenance routine to periodically keep the eviction policies up to date. For size this is to replay hits or evict, for expiration this is to discover stale entries, and for reference caching this is to find GC'd keys or values. Each policy uses O(1) algorithms to be cheap, batches the work to avoid lock contention, and performs this routine maintenance as a side effect of normal cache operations. If there is no activity on the cache then the routine maintenance is not triggered, as that requires a background scheduling thread. Generally this is okay as the memory was already in consumed, no activity may indicate low system usage, and the cache is a transient data store. However, some do want to trigger business logic and leverage the cache as a timing subsystem, e.g. using the `RemovalListener` to notify another component. The cache itself does not create or manage threads, but can defer work to a configured `Executor`. Similarly now it can now schedule the maintenance routine on a configured `Scheduler`, default disabled. The cache will still perform maintenance periodically and this scheduler only augments it to add additional liveliness. The scheduling is based on the expiration time only; users may use `Cache.cleanUp()` for fixed periods to assist reference caching, etc as desired. The cache will rate limit the scheduler so that it runs at a reasonable pace and never thrashes. For example, if the next expiration times are tiny durations apart (e.g. 200ms), the cache will not run the maintenance task 5x/s. It will instead ensure a 1 second delay (2^30ns) between scheduled runs (not accounting for the lack of real-time guarantees by a Scheduler impl). Similarly an additional delay may occur due to the priority queues being held in best-effort order. The scheduling for variable expiration is based on the TimerWheel's bucket expiration, which cascades events. For example a timer of 1h 13m 5s would schedule to run in 1h, which would cascade the 1hr bucket into the minute buckets. The next schedule would be at 13m, followed by 5s. Java 9+ users should prefer using `Scheduler.systemScheduler()` rather than creating their own dedicated threads. This leverages the JVM-wide scheduling thread, primarily intended for `CompletableFuture.orTimeout(duration)`. In Java 8 this method returns `Scheduler.disabledScheduler` instead.
- Loading branch information
Showing
28 changed files
with
1,111 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddPacer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright 2019 Ben Manes. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.github.benmanes.caffeine.cache.local; | ||
|
||
import static com.github.benmanes.caffeine.cache.Specifications.PACER; | ||
|
||
import javax.lang.model.element.Modifier; | ||
|
||
import com.github.benmanes.caffeine.cache.Feature; | ||
import com.squareup.javapoet.FieldSpec; | ||
import com.squareup.javapoet.MethodSpec; | ||
|
||
/** | ||
* @author [email protected] (Ben Manes) | ||
*/ | ||
public final class AddPacer extends LocalCacheRule { | ||
|
||
@Override | ||
protected boolean applies() { | ||
return !(Feature.usesExpiration(context.parentFeatures) | ||
|| !Feature.usesExpiration(context.generateFeatures)); | ||
} | ||
|
||
@Override | ||
protected void execute() { | ||
context.constructor.addStatement("this.pacer = ($1L == $2L)\n? null\n: new Pacer($1L)", | ||
"builder.getScheduler()", "Scheduler.disabledScheduler()"); | ||
context.cache.addField(FieldSpec.builder(PACER, "pacer", Modifier.FINAL).build()); | ||
context.cache.addMethod(MethodSpec.methodBuilder("pacer") | ||
.addModifiers(context.publicFinalModifiers()) | ||
.addStatement("return pacer") | ||
.returns(PACER) | ||
.build()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.