From bda925764ae2f9b2bf55f6007f84f548f58c31fe Mon Sep 17 00:00:00 2001 From: tinder-xli Date: Mon, 13 Nov 2017 20:35:46 -0800 Subject: [PATCH] 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 --- .../fielddata/IndexFieldDataService.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/index/fielddata/IndexFieldDataService.java b/core/src/main/java/org/elasticsearch/index/fielddata/IndexFieldDataService.java index 2577d967e621e..7a240c8a7b19a 100644 --- a/core/src/main/java/org/elasticsearch/index/fielddata/IndexFieldDataService.java +++ b/core/src/main/java/org/elasticsearch/index/fielddata/IndexFieldDataService.java @@ -110,19 +110,24 @@ public > IFD getForField(MappedFieldType fieldType final String fieldName = fieldType.name(); IndexFieldData.Builder builder = fieldType.fielddataBuilder(); - 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); } }