Reduce synchronization on field data cache

The field data cache can come under heavy contention in cases when lots
of search threads are hitting it for doc values. This commit reduces the
amount of contention here by using a double-checked locking strategy to
only lock when the cache needs to be initialized.

Relates #27365
This commit is contained in:
tinder-xli 2017-11-13 20:35:46 -08:00 committed by Jason Tedor
parent 5c34533761
commit 2e863572f4
1 changed files with 17 additions and 12 deletions

View File

@ -114,19 +114,24 @@ public class IndexFieldDataService extends AbstractIndexComponent implements Clo
final String fieldName = fieldType.name();
IndexFieldData.Builder builder = fieldType.fielddataBuilder(fullyQualifiedIndexName);
IndexFieldDataCache cache;
synchronized (this) {
cache = fieldDataCaches.get(fieldName);
if (cache == null) {
String cacheType = indexSettings.getValue(INDEX_FIELDDATA_CACHE_KEY);
if (FIELDDATA_CACHE_VALUE_NODE.equals(cacheType)) {
cache = indicesFieldDataCache.buildIndexFieldDataCache(listener, index(), fieldName);
} else if ("none".equals(cacheType)){
cache = new IndexFieldDataCache.None();
} else {
throw new IllegalArgumentException("cache type not supported [" + cacheType + "] for field [" + fieldName + "]");
IndexFieldDataCache cache = fieldDataCaches.get(fieldName);
if (cache == null) {
//for perf reason, only synchronize when cache is null
synchronized (this) {
cache = fieldDataCaches.get(fieldName);
//double checked locking to make sure it is thread safe
//especially when other threads calling clear() or clearField()
if (cache == null) {
String cacheType = indexSettings.getValue(INDEX_FIELDDATA_CACHE_KEY);
if (FIELDDATA_CACHE_VALUE_NODE.equals(cacheType)) {
cache = indicesFieldDataCache.buildIndexFieldDataCache(listener, index(), fieldName);
} else if ("none".equals(cacheType)){
cache = new IndexFieldDataCache.None();
} else {
throw new IllegalArgumentException("cache type not supported [" + cacheType + "] for field [" + fieldName + "]");
}
fieldDataCaches.put(fieldName, cache);
}
fieldDataCaches.put(fieldName, cache);
}
}