From 1ffcc5981803bd2adb8178daa0e34c353a2ca824 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 29 Dec 2016 03:10:10 +0000 Subject: gc is also a unwanted cache, so use it. With this, memcache with short expires is no longer needed --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 83 ++++++++++++++++++---- 1 file changed, 71 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/CoreModules/Asset') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index b6dd565..7bb88b9 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -78,6 +78,7 @@ namespace OpenSim.Region.CoreModules.Asset private static ulong m_RequestsForInprogress; private static ulong m_DiskHits; private static ulong m_MemoryHits; + private static ulong m_weakRefHits; #if WAIT_ON_INPROGRESS_REQUESTS private Dictionary m_CurrentlyWriting = new Dictionary(); @@ -92,7 +93,7 @@ namespace OpenSim.Region.CoreModules.Asset private bool m_MemoryCacheEnabled = false; // Expiration is expressed in hours. - private double m_MemoryExpiration = 0.001; + private double m_MemoryExpiration = 0.016; private const double m_DefaultFileExpiration = 48; private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); @@ -107,6 +108,9 @@ namespace OpenSim.Region.CoreModules.Asset private List m_Scenes = new List(); private object timerLock = new object(); + private Dictionary weakAssetReferences = new Dictionary(); + private object weakAssetReferencesLock = new object(); + public FlotsamAssetCache() { m_InvalidChars.AddRange(Path.GetInvalidPathChars()); @@ -255,12 +259,23 @@ namespace OpenSim.Region.CoreModules.Asset } } } + if (m_MemoryCacheEnabled) + m_MemoryCache = new ExpiringCache(); + + lock(weakAssetReferencesLock) + weakAssetReferences = new Dictionary(); } } //////////////////////////////////////////////////////////// // IImprovedAssetCache // + private void UpdateWeakReference(string key, AssetBase asset) + { + WeakReference aref = new WeakReference(asset); + lock(weakAssetReferencesLock) + weakAssetReferences[key] = aref; + } private void UpdateMemoryCache(string key, AssetBase asset) { @@ -327,6 +342,7 @@ namespace OpenSim.Region.CoreModules.Asset if (asset != null) { //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); + UpdateWeakReference(asset.ID, asset); if (m_MemoryCacheEnabled) UpdateMemoryCache(asset.ID, asset); @@ -354,6 +370,25 @@ namespace OpenSim.Region.CoreModules.Asset } } + private AssetBase GetFromWeakReference(string id) + { + AssetBase asset = null; + WeakReference aref; + + lock(weakAssetReferencesLock) + { + if (weakAssetReferences.TryGetValue(id, out aref)) + { + asset = aref.Target as AssetBase; + if(asset == null) + weakAssetReferences.Remove(id); + else + m_weakRefHits++; + } + } + return asset; + } + /// /// Try to get an asset from the in-memory cache. /// @@ -477,12 +512,21 @@ namespace OpenSim.Region.CoreModules.Asset m_Requests++; AssetBase asset = null; + asset = GetFromWeakReference(id); - if (m_MemoryCacheEnabled) + if (m_MemoryCacheEnabled && asset == null) + { asset = GetFromMemoryCache(id); + if(asset != null) + UpdateWeakReference(id,asset); + } if (asset == null && m_FileCacheEnabled) + { asset = GetFromFileCache(id); + if(asset != null) + UpdateWeakReference(id,asset); + } if (m_MemoryCacheEnabled && asset != null) UpdateMemoryCache(id, asset); @@ -494,6 +538,12 @@ namespace OpenSim.Region.CoreModules.Asset GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l)); } + if(asset == null) + { + + + } + return asset; } @@ -553,7 +603,10 @@ namespace OpenSim.Region.CoreModules.Asset } if (m_MemoryCacheEnabled) - m_MemoryCache.Clear(); + m_MemoryCache = new ExpiringCache(); + + lock(weakAssetReferencesLock) + weakAssetReferences = new Dictionary(); } private void CleanupExpiredFiles(object source, ElapsedEventArgs e) @@ -911,28 +964,34 @@ namespace OpenSim.Region.CoreModules.Asset List outputLines = new List(); double invReq = 100.0 / m_Requests; + + double weakHitRate = m_weakRefHits * invReq; + int weakEntries = weakAssetReferences.Count; double fileHitRate = m_DiskHits * invReq; + double TotalHitRate = weakHitRate + fileHitRate; + + outputLines.Add( + string.Format("Total requests: {0}", m_Requests)); + outputLines.Add( + string.Format("unCollected Hit Rate: {0}% ({1} entries)", weakHitRate.ToString("0.00"),weakEntries)); outputLines.Add( - string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests)); + string.Format("File Hit Rate: {0}%", fileHitRate.ToString("0.00"))); if (m_MemoryCacheEnabled) { double HitRate = m_MemoryHits * invReq; - outputLines.Add( - string.Format("Memory Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests)); - - HitRate += fileHitRate; + string.Format("Memory Hit Rate: {0}%", HitRate.ToString("0.00"))); - outputLines.Add( - string.Format("Total Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests)); + TotalHitRate += HitRate; } + outputLines.Add( + string.Format("Total Hit Rate: {0}%", TotalHitRate.ToString("0.00"))); outputLines.Add( string.Format( - "Unnecessary requests due to requests for assets that are currently downloading: {0}", - m_RequestsForInprogress)); + "Requests overlap during file writing: {0}", m_RequestsForInprogress)); return outputLines; } -- cgit v1.1 From c78da183b233f80ba436f677ecbbe32a477bd676 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 29 Dec 2016 03:25:12 +0000 Subject: expire also from weak references --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region/CoreModules/Asset') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 7bb88b9..e7f4981 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -580,6 +580,9 @@ namespace OpenSim.Region.CoreModules.Asset if (m_MemoryCacheEnabled) m_MemoryCache.Remove(id); + + lock(weakAssetReferencesLock) + weakAssetReferences.Remove(id); } catch (Exception e) { -- cgit v1.1 From feca9fd15385a5e2df27b5a3cc4ea3253be00909 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 29 Dec 2016 11:53:38 +0000 Subject: Add an option to update the file access time even when an asset is found in cache. When the cache is shared between multiple sims, it is often more efficient to have a single expire job run from cron. Updating file access times is vital to the functioning of such setups. --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'OpenSim/Region/CoreModules/Asset') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index e7f4981..5400c91 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -110,6 +110,7 @@ namespace OpenSim.Region.CoreModules.Asset private Dictionary weakAssetReferences = new Dictionary(); private object weakAssetReferencesLock = new object(); + private bool m_updateFileTimeOnCacheHit = false; public FlotsamAssetCache() { @@ -156,6 +157,8 @@ namespace OpenSim.Region.CoreModules.Asset m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration); m_MemoryExpiration *= 3600.0; // config in hours to seconds + + m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit); #if WAIT_ON_INPROGRESS_REQUESTS m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); @@ -513,12 +516,24 @@ namespace OpenSim.Region.CoreModules.Asset AssetBase asset = null; asset = GetFromWeakReference(id); + if (asset != null && m_updateFileTimeOnCacheHit) + { + string filename = GetFileName(id); + UpdateFileLastAccessTime(filename); + } if (m_MemoryCacheEnabled && asset == null) { asset = GetFromMemoryCache(id); if(asset != null) + { UpdateWeakReference(id,asset); + if (m_updateFileTimeOnCacheHit) + { + string filename = GetFileName(id); + UpdateFileLastAccessTime(filename); + } + } } if (asset == null && m_FileCacheEnabled) -- cgit v1.1 From f021c64eb060046bff6e91384e1bbca0384b7d61 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 29 Dec 2016 12:34:09 +0000 Subject: Refactor: Rename IImprovedAssetCache to IAssetCache as the old IAssetCache is long gone. --- OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | 6 +++--- OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs | 6 +++--- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 8 ++++---- OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'OpenSim/Region/CoreModules/Asset') diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index ebec9d2..382b5f2 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs @@ -91,7 +91,7 @@ namespace OpenSim.Region.CoreModules.Asset /// /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")] - public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule + public class CenomeMemoryAssetCache : IAssetCache, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -192,7 +192,7 @@ namespace OpenSim.Region.CoreModules.Asset expirationTime); } - #region IImprovedAssetCache Members + #region IAssetCache Members public bool Check(string id) { @@ -308,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Asset public void AddRegion(Scene scene) { if (m_enabled) - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); } /// diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index f720748..d78b082 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -40,7 +40,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Asset { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CoreAssetCache")] - public class CoreAssetCache : ISharedRegionModule, IImprovedAssetCache + public class CoreAssetCache : ISharedRegionModule, IAssetCache { private static readonly ILog m_log = LogManager.GetLogger( @@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Asset public void AddRegion(Scene scene) { if (m_Enabled) - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); } public void RemoveRegion(Scene scene) @@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Asset } //////////////////////////////////////////////////////////// - // IImprovedAssetCache + // IAssetCache // public bool Check(string id) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 5400c91..fcd4252 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -55,7 +55,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Asset { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")] - public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService + public class FlotsamAssetCache : ISharedRegionModule, IAssetCache, IAssetService { private static readonly ILog m_log = LogManager.GetLogger( @@ -219,7 +219,7 @@ namespace OpenSim.Region.CoreModules.Asset { if (m_Enabled) { - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); m_Scenes.Add(scene); } } @@ -228,7 +228,7 @@ namespace OpenSim.Region.CoreModules.Asset { if (m_Enabled) { - scene.UnregisterModuleInterface(this); + scene.UnregisterModuleInterface(this); m_Scenes.Remove(scene); lock(timerLock) { @@ -271,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Asset } //////////////////////////////////////////////////////////// - // IImprovedAssetCache + // IAssetCache // private void UpdateWeakReference(string key, AssetBase asset) { diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 5f76ac2..7343f4f 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -41,7 +41,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Asset { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GlynnTuckerAssetCache")] - public class GlynnTuckerAssetCache : ISharedRegionModule, IImprovedAssetCache + public class GlynnTuckerAssetCache : ISharedRegionModule, IAssetCache { private static readonly ILog m_log = LogManager.GetLogger( @@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Asset public void AddRegion(Scene scene) { if (m_Enabled) - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); } public void RemoveRegion(Scene scene) @@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Asset } //////////////////////////////////////////////////////////// - // IImprovedAssetCache + // IAssetCache // public bool Check(string id) -- cgit v1.1 From 07b48fd58c343d18b8ce64179e344439070511e8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 29 Dec 2016 15:47:46 +0000 Subject: Add negative caching to flotsam cache. Prevents scripts from hammering the asset server --- .../Region/CoreModules/Asset/CenomeAssetCache.cs | 5 ++++ OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs | 5 ++++ .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 27 ++++++++++++++++++++++ .../CoreModules/Asset/GlynnTuckerAssetCache.cs | 5 ++++ 4 files changed, 42 insertions(+) (limited to 'OpenSim/Region/CoreModules/Asset') diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index 382b5f2..14b0280 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs @@ -221,6 +221,11 @@ namespace OpenSim.Region.CoreModules.Asset } + public void CacheNegative(string id) + { + // We don't do negative caching + } + /// /// Clear asset cache. /// diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index d78b082..82bc5cc 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -124,6 +124,11 @@ namespace OpenSim.Region.CoreModules.Asset m_Cache.Store(asset.ID, asset); } + public void CacheNegative(string id) + { + // We don't do negative caching + } + public AssetBase Get(string id) { return (AssetBase)m_Cache.Get(id); diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index fcd4252..84e13a0 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -92,9 +92,15 @@ namespace OpenSim.Region.CoreModules.Asset private ExpiringCache m_MemoryCache; private bool m_MemoryCacheEnabled = false; + private ExpiringCache m_negativeCache; + private bool m_negativeCacheEnabled = true; + private bool m_negativeCacheSliding = false; + // Expiration is expressed in hours. private double m_MemoryExpiration = 0.016; private const double m_DefaultFileExpiration = 48; + // Negative cache is in seconds + private int m_negativeExpiration = 120; private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); @@ -139,6 +145,7 @@ namespace OpenSim.Region.CoreModules.Asset if (name == Name) { m_MemoryCache = new ExpiringCache(); + m_negativeCache = new ExpiringCache(); m_Enabled = true; m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); @@ -158,6 +165,9 @@ namespace OpenSim.Region.CoreModules.Asset m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration); m_MemoryExpiration *= 3600.0; // config in hours to seconds + m_negativeCacheEnabled = assetConfig.GetBoolean("NegativeCacheEnabled", m_negativeCacheEnabled); + m_negativeExpiration = assetConfig.GetInt("NegativeCacheTimeout", m_negativeExpiration); + m_negativeCacheSliding = assetConfig.GetBoolean("NegativeCacheSliding", m_negativeCacheSliding); m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit); #if WAIT_ON_INPROGRESS_REQUESTS @@ -355,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Asset } } + public void CacheNegative(string id) + { + if (m_negativeCacheEnabled) + { + if (m_negativeCacheSliding) + m_negativeCache.AddOrUpdate(id, null, TimeSpan.FromSeconds(m_negativeExpiration)); + else + m_negativeCache.AddOrUpdate(id, null, m_negativeExpiration); + } + } + /// /// Updates the cached file with the current time. /// @@ -514,6 +535,10 @@ namespace OpenSim.Region.CoreModules.Asset { m_Requests++; + object dummy; + if (m_negativeCache.TryGetValue(id, out dummy)) + return null; + AssetBase asset = null; asset = GetFromWeakReference(id); if (asset != null && m_updateFileTimeOnCacheHit) @@ -622,6 +647,8 @@ namespace OpenSim.Region.CoreModules.Asset if (m_MemoryCacheEnabled) m_MemoryCache = new ExpiringCache(); + if (m_negativeCacheEnabled) + m_negativeCache = new ExpiringCache(); lock(weakAssetReferencesLock) weakAssetReferences = new Dictionary(); diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 7343f4f..195bdaa 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -126,6 +126,11 @@ namespace OpenSim.Region.CoreModules.Asset m_Cache.AddOrUpdate(asset.ID, asset); } + public void CacheNegative(string id) + { + // We don't do negative caching + } + public AssetBase Get(string id) { Object asset = null; -- cgit v1.1