From a8c274ddb0e50c591a9927dd3defc7bd82a4828d Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Sun, 7 Mar 2021 00:35:59 -0800 Subject: [PATCH] Add putIfAbsent optimistic fastpath (fixes #506) Put optimistically reads the existing value to avoid a map lambda and hash table lock. If absent, it then tries to add a new entry. If this fails when racing with another writer, a putIfAbsent can validate and return the existing value immediately. Previously it would do these steps after acquiring the entry lock during the update code path. This mirrors the fastpath when the entry was found and no update is needed for a putIfAbsent. That case will be more common, this only assists when populating, e.g. after expiration when many threads may try to reload the value. --- build.gradle | 10 ++++- caffeine/build.gradle | 4 -- .../caffeine/cache/BoundedLocalCache.java | 11 ++++++ checksum.xml | 14 +++++++ gradle.properties | 1 + gradle/dependencies.gradle | 39 ++++++++++--------- gradle/publish.gradle | 6 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 8 files changed, 55 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index a5100390fb..e8880c657d 100644 --- a/build.gradle +++ b/build.gradle @@ -153,6 +153,12 @@ tasks.coveralls { onlyIf { System.env.'CI' && !JavaVersion.current().isJava9Compatible() } } -dependencyUpdates.resolutionStrategy { - force testLibraries.truth +def isNonStable = { String version -> + def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } + def regex = /^[0-9,.v-]+(-r)?$/ + return !stableKeyword && !(version ==~ regex) +} + +dependencyUpdates.rejectVersionIf { + it.candidate.group == 'org.slf4j' && isNonStable(it.candidate.version) } diff --git a/caffeine/build.gradle b/caffeine/build.gradle index 430f044b94..55d37dccb5 100644 --- a/caffeine/build.gradle +++ b/caffeine/build.gradle @@ -66,10 +66,6 @@ dependencies { javaPoetImplementation libraries.googleJavaFormat } -java { - withSourcesJar() -} - compileCodeGenJava { gradle.taskGraph.whenReady { enabled = gradle.taskGraph.hasTask('uploadArchives') diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index 45d83607d4..f586d56214 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -2086,6 +2086,17 @@ public Map getAllPresent(Iterable keys) { if (prior == null) { afterWrite(new AddTask(node, newWeight)); return null; + } else if (onlyIfAbsent) { + // An optimistic fast path to avoid unnecessary locking + V currentValue = prior.getValue(); + if ((currentValue != null) && !hasExpired(prior, now)) { + if (!isComputingAsync(prior)) { + tryExpireAfterRead(prior, key, currentValue, expiry(), now); + setAccessTime(prior, now); + } + afterRead(prior, now, /* recordHit */ false); + return currentValue; + } } } else if (onlyIfAbsent) { // An optimistic fast path to avoid unnecessary locking diff --git a/checksum.xml b/checksum.xml index 488814600a..f6f92c2708 100644 --- a/checksum.xml +++ b/checksum.xml @@ -8,6 +8,7 @@ + @@ -45,6 +46,7 @@ + @@ -139,6 +141,7 @@ + @@ -216,9 +219,11 @@ + + @@ -301,6 +306,9 @@ D57AC7E2C3AB7135504C2ADED5E622032AB03905EF259645A0EE2B0D3B9868BC15131AD50027F47044F710DBA681AD2A54B669451C795E8189378AD2525D4E44 + + C1AB30AA9984AAF40E0DEF6474F535875ABCCA1568E6D495317D1092B782AC39D13505BBBD50877589610A59273AC89ADE0B68EEE0501961C1AF17CA5D509178 + DF5BFED7DFC327166FE0CB81BD6A9655F44CCB268E7E69204BD09955147CE9A97EBBCC28F9ACF315DBAF49E850A43CE8744F44E68D7BE816EACCAF0BEE41B203 @@ -376,6 +384,9 @@ 97823390838111768E99E68A9EB8E603E528A910850EF58B1A9198828C5DE9C8F4BE53238DBED56C46A2471E5F1871FA4CD1D34F86FA44B4E3643BD3D03901A9 + + A9789681117B1D01021884DB7D0F6367CA3B7F4AC6A4630BC6769DFDF6D1003E49CD7A894D803BFA6244AEE5135F610EEAA4E2E1AD67F8C5196C8B7A1CEEE451 + B3BFAD07E6A3D4D73CBCE802D8614CF4AC84E589166D243D41028DC077F84C027DF4D514F145360405F37DA73A8F2E7B65D90877A9EE1151174D2440530F9051 @@ -460,6 +471,9 @@ 5A630269AE2E19E48529A5D768DD9C01DCC9A91247A9D24CC777F0D2B79DBA06AC40AEAC4560C57BFCB6BBBD423621313013B742B78C24C8861490C957A4DC92 + + 6B9620FFEA84B67D27132B6BD8D2EB080C519383CC3187474CABD10EB398BEB259D25974386508AADA1194A2BDAB5D223FAB584AC84E6B03D007EDEBFCBD9A68 + BC7BC2A514F8CA104A392ECF8736F4A3D316EE988FA91299D33B0AF46134B38E14E4A5061449D17B2DF7A521643E6C02DFA37CC277ED7CAB7CE83C28C00E9719 diff --git a/gradle.properties b/gradle.properties index 3e97df2e51..073816bf8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,6 @@ org.gradle.jvmargs=-Xmx2g -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=0 -noverify -XX:+HeapDumpOnOutOfMemoryError systemProp.org.gradle.internal.publish.checksums.insecure=true +org.gradle.parallel=true org.gradle.daemon=true checksumIgnore=true nexusUsername= diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index f0d59eae9f..babb48a267 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -25,16 +25,16 @@ */ ext { versions = [ - akka: '2.6.12', + akka: '2.6.13', cache2k: '2.1.1.Alpha', - checkerFramework: '3.10.0', + checkerFramework: '3.11.0', coherence: '20.06', commonsCompress: '1.20', - commonsLang3: '3.11', + commonsLang3: '3.12.0', commonsMath3: '3.6.1', concurrentlinkedhashmap: '1.4.2', config: '1.4.1', - ehcache3: '3.9.1', + ehcache3: '3.9.2', errorprone: '2.5.1', errorproneJavac: '9+181-r4173-1', elasticSearch: '7.11.1', @@ -49,7 +49,7 @@ ext { javaObjectLayout: '0.14', javapoet: '1.13.0', jcache: '1.1.1', - jmh: '1.27', + jmh: '1.28', joor: '0.9.13', jsr330: '1', nullaway: '0.8.0', @@ -62,28 +62,29 @@ ext { univocityParsers: '2.9.1', ycsb: '0.17.0', xz: '1.8', - zstd: '1.4.8-4', + zstd: '1.4.8-7', ] testVersions = [ awaitility: '4.0.3', easymock: '4.2', + guice: '5.0.1', hamcrest: '2.2', jcacheTck: '1.1.1', - jctools: '3.2.0', + jctools: '3.3.0', junit: '4.13.2', - mockito: '3.7.7', + mockito: '3.8.0', paxExam: '4.13.4', - testng: '7.3.0', - truth: '0.24', + testng: '7.4.0', + truth: '1.1.2', felix: '7.0.0', - felixScr: '2.1.24', + felixScr: '2.1.26', osgiUtilFunction: '1.1.0', osgiUtilPromise: '1.1.1', ] pluginVersions = [ - bnd: '5.2.0', - checkerFramework: '0.5.16', - checkstyle: '8.40', + bnd: '5.3.0', + checkerFramework: '0.5.17', + checkstyle: '8.41', coveralls: '2.8.4', errorprone: '1.3.0', jacoco: '0.8.6', @@ -91,14 +92,14 @@ ext { jmhReport: '0.9.0', nexusPublish: '1.0.0', nullaway: '1.0.2', - pmd: '6.31.0', + pmd: '6.32.0', semanticVersioning: '1.1.0', shadow: '6.1.0', sonarqube: '3.1.1', - spotbugs: '4.2.0', - spotbugsPlugin: '4.6.1', + spotbugs: '4.2.2', + spotbugsPlugin: '4.6.2', stats: '0.2.2', - versions: '0.36.0', + versions: '0.38.0', ] annotationProcessorVersions = [ autoValue: '1.7.4', @@ -181,7 +182,7 @@ ext { exclude group: 'junit' exclude group: 'guice' }, - 'com.google.inject:guice:4.2.3' + "com.google.inject:guice:${testVersions.guice}" ], truth: "com.google.truth:truth:${testVersions.truth}", ] diff --git a/gradle/publish.gradle b/gradle/publish.gradle index a456b24941..64045edd4f 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -73,9 +73,3 @@ signing { useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) sign publishing.publications.mavenJava } - -javadoc { - if (JavaVersion.current().isJava9Compatible()) { - options.addBooleanOption('html5', true) - } -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 86db1ea852..2dec187ac6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME