lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nightowl...@apache.org
Subject [lucenenet] 04/09: Lucene.Net.Search.FieldCacheImpl: Switched to ConcurrentDictionary for the innerCache to try to reduce locking (LUCENENET-610)
Date Thu, 30 Jan 2020 08:15:53 GMT
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit b4e6f0fa994797f9e743ec23b191d43a06942b86
Author: Shad Storhaug <shad@shadstorhaug.com>
AuthorDate: Mon Jan 27 03:35:31 2020 +0700

    Lucene.Net.Search.FieldCacheImpl: Switched to ConcurrentDictionary for the innerCache
to try to reduce locking (LUCENENET-610)
---
 src/Lucene.Net/Search/FieldCacheImpl.cs | 112 ++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 49 deletions(-)

diff --git a/src/Lucene.Net/Search/FieldCacheImpl.cs b/src/Lucene.Net/Search/FieldCacheImpl.cs
index eaa158e..87e6a95 100644
--- a/src/Lucene.Net/Search/FieldCacheImpl.cs
+++ b/src/Lucene.Net/Search/FieldCacheImpl.cs
@@ -2,11 +2,13 @@ using Lucene.Net.Index;
 using Lucene.Net.Support;
 using Lucene.Net.Support.IO;
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Runtime.CompilerServices;
+using System.Threading;
 
 namespace Lucene.Net.Search
 {
@@ -114,9 +116,11 @@ namespace Lucene.Net.Search
                 {
                     Cache cache = cacheEntry.Value;
                     Type cacheType = cacheEntry.Key;
+#if !FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
                     lock (cache.readerCache)
                     {
-                        foreach (KeyValuePair<object, IDictionary<CacheKey, object>>
readerCacheEntry in cache.readerCache)
+#endif
+                        foreach (var readerCacheEntry in cache.readerCache)
                         {
                             object readerKey = readerCacheEntry.Key;
                             if (readerKey == null)
@@ -130,7 +134,9 @@ namespace Lucene.Net.Search
                                 result.Add(new FieldCache.CacheEntry(readerKey, entry.field,
cacheType, entry.custom, mapEntry.Value));
                             }
                         }
+#if !FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
                     }
+#endif
                 }
                 return result.ToArray();
             }
@@ -208,9 +214,9 @@ namespace Lucene.Net.Search
             internal readonly FieldCacheImpl wrapper;
 
 #if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
-            internal ConditionalWeakTable<object, IDictionary<CacheKey, object>>
readerCache = new ConditionalWeakTable<object, IDictionary<CacheKey, object>>();
+            internal ConditionalWeakTable<object, ConcurrentDictionary<CacheKey, object>>
readerCache = new ConditionalWeakTable<object, ConcurrentDictionary<CacheKey, object>>();
 #else
-            internal WeakDictionary<object, IDictionary<CacheKey, object>> readerCache
= new WeakDictionary<object, IDictionary<CacheKey, object>>();
+            internal WeakDictionary<object, ConcurrentDictionary<CacheKey, object>>
readerCache = new WeakDictionary<object, ConcurrentDictionary<CacheKey, object>>();
 #endif
 
             protected abstract object CreateValue(AtomicReader reader, CacheKey key, bool
setDocsWithField);
@@ -219,10 +225,10 @@ namespace Lucene.Net.Search
             /// Remove this reader from the cache, if present. </summary>
             public virtual void PurgeByCacheKey(object coreCacheKey)
             {
+#if !FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
                 lock (readerCache)
-                {
+#endif
                     readerCache.Remove(coreCacheKey);
-                }
             }
 
             /// <summary>
@@ -231,79 +237,87 @@ namespace Lucene.Net.Search
             /// </summary>
             public virtual void Put(AtomicReader reader, CacheKey key, object value)
             {
+                ConcurrentDictionary<CacheKey, object> innerCache;
                 object readerKey = reader.CoreCacheKey;
+#if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
+                innerCache = readerCache.GetValue(readerKey, (readerKey) =>
+                {
+                    // First time this reader is using FieldCache
+                    wrapper.InitReader(reader);
+                    return new ConcurrentDictionary<CacheKey, object>
+                    {
+                        [key] = value
+                    };
+                });
+#else
                 lock (readerCache)
                 {
-                    if (!readerCache.TryGetValue(readerKey, out IDictionary<CacheKey,
object> innerCache) || innerCache == null)
+                    if (!readerCache.TryGetValue(readerKey, out innerCache) || innerCache
== null)
                     {
                         // First time this reader is using FieldCache
-                        innerCache = new Dictionary<CacheKey, object>();
-                        readerCache.AddOrUpdate(readerKey, innerCache);
+                        innerCache = new ConcurrentDictionary<CacheKey, object>
+                        {
+                            [key] = value
+                        };
+                        readerCache.Add(readerKey, innerCache);
                         wrapper.InitReader(reader);
                     }
-                    // LUCENENET NOTE: We declare a temp variable here so we 
-                    // don't overwrite value variable with the null
-                    // that will result when this if block succeeds; otherwise
-                    // we won't have a value to put in the cache.
-                    if (!innerCache.TryGetValue(key, out object temp))
-                    {
-                        innerCache[key] = value;
-                    }
-                    else
-                    {
-                        // Another thread beat us to it; leave the current
-                        // value
-                    }
                 }
+#endif
+                // If another thread beat us to it, leave the current value
+                innerCache.TryAdd(key, value);
             }
 
             public virtual object Get(AtomicReader reader, CacheKey key, bool setDocsWithField)
             {
-                IDictionary<CacheKey, object> innerCache;
-                object value;
+                ConcurrentDictionary<CacheKey, object> innerCache;
                 object readerKey = reader.CoreCacheKey;
+#if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
+                innerCache = readerCache.GetValue(readerKey, (readerKey) =>
+                {
+                    // First time this reader is using FieldCache
+                    wrapper.InitReader(reader);
+                    return new ConcurrentDictionary<CacheKey, object>
+                    {
+                        [key] = new FieldCache.CreationPlaceholder()
+                    };
+                });
+
+#else
                 lock (readerCache)
                 {
                     if (!readerCache.TryGetValue(readerKey, out innerCache) || innerCache
== null)
                     {
                         // First time this reader is using FieldCache
-                        innerCache = new Dictionary<CacheKey, object>();
-                        readerCache.AddOrUpdate(readerKey, innerCache);
+                        innerCache = new ConcurrentDictionary<CacheKey, object>
+                        {
+                            [key] = new FieldCache.CreationPlaceholder()
+                        };
+                        readerCache[readerKey] = innerCache;
                         wrapper.InitReader(reader);
-                        value = null;
-                    }
-                    else
-                    {
-                        innerCache.TryGetValue(key, out value);
-                    }
-                    if (value == null)
-                    {
-                        value = new FieldCache.CreationPlaceholder();
-                        innerCache[key] = value;
                     }
                 }
-                if (value is FieldCache.CreationPlaceholder)
+#endif
+                object value = innerCache.GetOrAdd(key, (cacheKey) => new FieldCache.CreationPlaceholder());
+                if (value is FieldCache.CreationPlaceholder progress)
                 {
                     lock (value)
                     {
-                        FieldCache.CreationPlaceholder progress = (FieldCache.CreationPlaceholder)value;
                         if (progress.Value == null)
                         {
                             progress.Value = CreateValue(reader, key, setDocsWithField);
-                            lock (readerCache)
-                            {
-                                innerCache[key] = progress.Value;
-                            }
-
-                            // Only check if key.custom (the parser) is
-                            // non-null; else, we check twice for a single
-                            // call to FieldCache.getXXX
-                            if (key.custom != null && wrapper != null)
+                            if (innerCache.TryUpdate(key, progress.Value, value))
                             {
-                                TextWriter infoStream = wrapper.InfoStream;
-                                if (infoStream != null)
+                                // Only check if key.custom (the parser) is
+                                // non-null; else, we check twice for a single
+                                // call to FieldCache.getXXX
+                                if (key.custom != null && wrapper != null)
                                 {
-                                    PrintNewInsanity(infoStream, progress.Value);
+                                    TextWriter infoStream = wrapper.InfoStream;
+                                    if (infoStream != null)
+                                    {
+                                        PrintNewInsanity(infoStream, progress.Value);
+                                    }
                                 }
                             }
                         }


Mime
View raw message