private int UncacheChunks(int maxUncacheCount = 10) { var uncachedCount = 0; if (Interlocked.CompareExchange(ref _uncachingChunks, 1, 0) == 0) { try { var usedMemoryPercent = ChunkUtil.GetUsedMemoryPercent(); if (usedMemoryPercent <= (ulong)_config.ChunkCacheMinPercent) { return(0); } if (Log.Level == LogLevel.Info) { Log.Debug("Current memory usage {0}% exceed the chunkCacheMinPercent {1}%, try to uncache chunks.", usedMemoryPercent, _config.ChunkCacheMinPercent); } var chunks = _chunks.Values.Where(x => x.IsCompleted && !x.IsMemoryChunk && x.HasCachedChunk).OrderBy(x => x.LastActiveTime).ToList(); foreach (var chunk in chunks) { if ((DateTime.Now - chunk.LastActiveTime).TotalSeconds >= _config.ChunkInactiveTimeMaxSeconds) { if (chunk.UnCacheFromMemory()) { Thread.Sleep(100); //即便有内存释放了,由于通过API读取到的内存使用数可能不会立即更新,所以等待一定时间后检查内存是否足够 uncachedCount++; if (uncachedCount >= maxUncacheCount || ChunkUtil.GetUsedMemoryPercent() <= (ulong)_config.ChunkCacheMinPercent) { break; } } } } if (Log.Level == LogLevel.Info) { if (uncachedCount > 0) { Log.Debug("Uncached {0} chunks, current memory usage: {1}%", uncachedCount, ChunkUtil.GetUsedMemoryPercent()); } else { Log.Debug("No chunks uncached."); } } } catch (Exception ex) { Log.Error("Uncaching chunks has exception.", ex); } finally { Interlocked.Exchange(ref _uncachingChunks, 0); } } return(uncachedCount); }