Lucene.Net-内存溢出问题解决

    技术2022-05-19  41

      Lucene在索引数据比较少的时候内存问题不是很明显,但如果索引文件有几个G的时候,内存就会出现溢出问题.这个问题是由于Lucene的内部Bug引起的,如果在搜索时设置了排序,则它会缓存相关数据,但在下一次搜索时,它没有清除内部的一些缓存数据,所以会造成内存溢出.这个问题的解决办法就是改Lucene的源代码.         修改步骤如下:         1.修改Lucene源代码中Index目录中的IndexReader.cs文件,在其中加上如下代码:            public string m_cacheKey = null; (这一行代码主要用于Lucene内部用缓存的键值),以后清除缓存就用这个键值.        2.修改Lucene源代码中Search目录中的IndexSearcher.cs文件,修改其中的Close方法代码如下:           public override void  Close()  {            //清除缓存数据            if (!string.IsNullOrEmpty(reader.m_cacheKey))            {                if (null != FieldSortedHitQueue.Comparators)                {                    FieldSortedHitQueue.Comparators.ReleaseCache(reader.m_cacheKey);                }                Lucene.Net.Search.FieldCache_Fields.DEFAULT.ReleaseFieldCache(reader.m_cacheKey);                Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.ReleaseExtendedFieldCache(reader.m_cacheKey);                 // 立即回收垃圾                GC.Collect();            }                                //关闭读取器   if (closeReader)    reader.Close();  }              3.修改Lucene源代码中Search目录中的FieldCache.cs文件,修改其中的接口public interface FieldCache,并添加接口方法,方法代码如下:           //用于清除缓存        void ReleaseFieldCache(string strCacheKey);             4.修改Lucene源代码中Search目录中的FieldCacheImpl.cs文件,添加下列方法, 代码如下:             //用于清除缓存        public void ReleaseFieldCache(string strCacheKey)        {            bytesCache.ReleaseCache(strCacheKey);            shortsCache.ReleaseCache(strCacheKey);            intsCache.ReleaseCache(strCacheKey);            floatsCache.ReleaseCache(strCacheKey);            stringsCache.ReleaseCache(strCacheKey);            stringsIndexCache.ReleaseCache(strCacheKey);            autoCache.ReleaseCache(strCacheKey);            customCache.ReleaseCache(strCacheKey);        }             修改内部类:internal abstract class Cache,添加方法如下:            //用于清除缓存            public void ReleaseCache(string strCacheKey)            {                if (null != readerCache)                {                    lock (readerCache.SyncRoot)                    {                        if (null != readerCache[strCacheKey])                        {                            ((System.Collections.Hashtable)readerCache[strCacheKey]).Clear();                        }                                            }                }            }               修改方法Get:                public virtual System.Object Get(IndexReader reader, System.Object key)   {    System.Collections.IDictionary innerCache;    System.Object value_Renamed;    lock (readerCache.SyncRoot)    {                    //改键值为静态值                    innerCache = (System.Collections.IDictionary)readerCache[reader.m_cacheKey];     //innerCache = (System.Collections.IDictionary) readerCache[reader];      if (innerCache == null)     {      innerCache = new System.Collections.Hashtable();                        //改键值为静态值                        readerCache[reader.m_cacheKey] = innerCache;      //readerCache[reader] = innerCache;      value_Renamed = null;     }     else     {      value_Renamed = innerCache[key];     }     if (value_Renamed == null)     {      value_Renamed = new CreationPlaceholder();      innerCache[key] = value_Renamed;     }    }    if (value_Renamed is CreationPlaceholder)    {     lock (value_Renamed)     {      CreationPlaceholder progress = (CreationPlaceholder) value_Renamed;      if (progress.value_Renamed == null)      {       progress.value_Renamed = CreateValue(reader, key);       lock (readerCache.SyncRoot)       {        innerCache[key] = progress.value_Renamed;       }      }      return progress.value_Renamed;     }    }    return value_Renamed;   }                 5.修改Lucene源代码中Search目录中的ExtendedFieldCache.cs文件,修改其中的接口public interface ExtendedFieldCache : FieldCache,并添加接口方法,方法代码如下:          //用于清除缓存        void ReleaseExtendedFieldCache(string strCacheKey);           6.修改Lucene源代码中Search目录中的ExtendedFieldCacheImpl.cs文件,添加下列方法,代码如下:          //用于清除缓存        public void ReleaseExtendedFieldCache(string strCacheKey)        {            longsCache.ReleaseCache(strCacheKey);            doublesCache.ReleaseCache(strCacheKey);            autoCache.ReleaseCache(strCacheKey);        }     通过上述6个步骤,内存溢出问题就可以解决了,但还有一个需要注意的就是在更新索引时,一定要调用如下代码,才能清掉缓存: //清缓排序缓存数据IndexSearcher.Close(); IndexReader.Close();


    最新回复(0)