Apache Ignite 在使用驱逐策略时出现 OOM
Apache Ignite goes OOM while using Eviction Policy
我正在尝试使用 LruEvictionPolicy 通过 Apache Ignite 1.6 缓存数据。我写了一些测试代码来观察缓存行为(用于进程缓存中的 Apache Ignite / Redis / Memcached / .NET)。我正在使用 Win10 / VS2015。
static void Main(string[] args)
{
// 64Bit -> size in memory for an atring = 26 + length * 2
// using 512KB string
StringBuilder builder = new StringBuilder(262131);
for (int i = 0; i < 262131; i++)
{
builder.Append('G');
}
ICache cache;
IList<bool> cacheMemTest;
cache = new IgniteCache();
cacheMemTest = TestCache(cache, builder.ToString(), 10);
DrawResult(GetFilestreamForName("IgniteCache"), cacheMemTest);
}
private static IList<bool> TestCache(ICache cache, string testValue, int delay)
{
int numOfElements = 10000;
for (int i = 0; i < numOfElements; i++)
{
var currentString = String.Copy(testValue);
cache.AddValue(i.ToString(), currentString);
currentString = null;
GC.Collect();
}
IList<bool> boolList = new List<bool>(numOfElements);
for (int i = 0; i < numOfElements; i++)
{
boolList.Add(cache.HasElement(i.ToString()));
}
return boolList;
}
IgniteCach class 看起来像这样:
class IgniteCache : ICache, IDisposable
{
private IIgnite _ignite;
private Apache.Ignite.Core.Cache.ICache<string, string> _cache;
public IgniteCache()
{
var conf = new IgniteConfiguration();
//conf.JvmInitialMemoryMb = 512;
//conf.JvmMaxMemoryMb = 1024;
conf.JvmOptions = new string[] { "-XX:+UseParNewGC",
"-XX:+UseConcMarkSweepGC",
"-XX:+UseTLAB",
"-XX:NewSize=128m",
"-XX:MaxNewSize=128m",
"-XX:MaxTenuringThreshold=0",
"-XX:SurvivorRatio=1024",
"-XX:+UseCMSInitiatingOccupancyOnly",
"-XX:CMSInitiatingOccupancyFraction=60" };
var cacheConf = new CacheConfiguration();
cacheConf.CopyOnRead = false;
cacheConf.EagerTtl = false;
cacheConf.AtomicityMode = CacheAtomicityMode.Atomic;
cacheConf.WriteBehindEnabled = false;
cacheConf.EvictionPolicy = new Apache.Ignite.Core.Cache.Eviction.LruEvictionPolicy()
{
MaxMemorySize = 1073741824
};
cacheConf.Name = "cache";
cacheConf.CacheMode = CacheMode.Local;
cacheConf.Backups = 0;
cacheConf.OffHeapMaxMemory = -1;
cacheConf.EnableSwap = false;
conf.CacheConfiguration = new List<CacheConfiguration>() { cacheConf };
conf.DiscoverySpi = new TcpDiscoverySpi
{
IpFinder = new TcpDiscoveryStaticIpFinder
{
Endpoints = new[] { "127.0.0.1:47500" }
},
SocketTimeout = TimeSpan.FromSeconds(0.3)
};
_ignite = Ignition.Start(conf);
TimeSpan timeSpan = new TimeSpan(6, 0, 0);
_cache = _ignite.GetCache<string, string>("cache").WithExpiryPolicy(new Apache.Ignite.Core.Cache.Expiry.ExpiryPolicy(timeSpan, timeSpan, timeSpan));
}
public void AddValue(string key, string values)
{
_cache.Put(key, values);
}
public void Dispose()
{
_ignite.Dispose();
}
public string GetValue(string key)
{
if (HasElement(key))
{
return _cache.Get(key);
}
return null;
}
public bool HasElement(string key)
{
return _cache.ContainsKey(key);
}
}
当使用和"conf.JvmMaxMemoryMb = 1024;"我会运行内存不足,LruEvictionPolicy似乎什么都不做。删除 JVM 最大。内存限制程序将 运行 分配到 ~5GB 直到结束。现在我正在检查结果:大约 2/5 的缓存数据仍在缓存中。这就是我的 wanted/expected 行为,但使用了太多内存。
有没有办法减少使用的内存?
简答:不要将 CopyOnRead
设置为 false
。默认为true
。
更长的解释:
将 CopyOnRead
设置为 false
会导致在内部存储序列化和反序列化的值。这在某些情况下可能会提高性能,但会增加内存使用量。
此外,当 CopyOnRead 为 false
(https://issues.apache.org/jira/browse/IGNITE-3347) 时,EvictionPolicy
计算内存大小存在错误。
此外,不要指望将 JvmMaxMemoryMb
和 EvictionPolicy.MaxMemorySize
设置为相同的值会起作用:Ignite 需要备用内存用于内部用途和 JVM GC 高效工作。
我正在尝试使用 LruEvictionPolicy 通过 Apache Ignite 1.6 缓存数据。我写了一些测试代码来观察缓存行为(用于进程缓存中的 Apache Ignite / Redis / Memcached / .NET)。我正在使用 Win10 / VS2015。
static void Main(string[] args)
{
// 64Bit -> size in memory for an atring = 26 + length * 2
// using 512KB string
StringBuilder builder = new StringBuilder(262131);
for (int i = 0; i < 262131; i++)
{
builder.Append('G');
}
ICache cache;
IList<bool> cacheMemTest;
cache = new IgniteCache();
cacheMemTest = TestCache(cache, builder.ToString(), 10);
DrawResult(GetFilestreamForName("IgniteCache"), cacheMemTest);
}
private static IList<bool> TestCache(ICache cache, string testValue, int delay)
{
int numOfElements = 10000;
for (int i = 0; i < numOfElements; i++)
{
var currentString = String.Copy(testValue);
cache.AddValue(i.ToString(), currentString);
currentString = null;
GC.Collect();
}
IList<bool> boolList = new List<bool>(numOfElements);
for (int i = 0; i < numOfElements; i++)
{
boolList.Add(cache.HasElement(i.ToString()));
}
return boolList;
}
IgniteCach class 看起来像这样:
class IgniteCache : ICache, IDisposable
{
private IIgnite _ignite;
private Apache.Ignite.Core.Cache.ICache<string, string> _cache;
public IgniteCache()
{
var conf = new IgniteConfiguration();
//conf.JvmInitialMemoryMb = 512;
//conf.JvmMaxMemoryMb = 1024;
conf.JvmOptions = new string[] { "-XX:+UseParNewGC",
"-XX:+UseConcMarkSweepGC",
"-XX:+UseTLAB",
"-XX:NewSize=128m",
"-XX:MaxNewSize=128m",
"-XX:MaxTenuringThreshold=0",
"-XX:SurvivorRatio=1024",
"-XX:+UseCMSInitiatingOccupancyOnly",
"-XX:CMSInitiatingOccupancyFraction=60" };
var cacheConf = new CacheConfiguration();
cacheConf.CopyOnRead = false;
cacheConf.EagerTtl = false;
cacheConf.AtomicityMode = CacheAtomicityMode.Atomic;
cacheConf.WriteBehindEnabled = false;
cacheConf.EvictionPolicy = new Apache.Ignite.Core.Cache.Eviction.LruEvictionPolicy()
{
MaxMemorySize = 1073741824
};
cacheConf.Name = "cache";
cacheConf.CacheMode = CacheMode.Local;
cacheConf.Backups = 0;
cacheConf.OffHeapMaxMemory = -1;
cacheConf.EnableSwap = false;
conf.CacheConfiguration = new List<CacheConfiguration>() { cacheConf };
conf.DiscoverySpi = new TcpDiscoverySpi
{
IpFinder = new TcpDiscoveryStaticIpFinder
{
Endpoints = new[] { "127.0.0.1:47500" }
},
SocketTimeout = TimeSpan.FromSeconds(0.3)
};
_ignite = Ignition.Start(conf);
TimeSpan timeSpan = new TimeSpan(6, 0, 0);
_cache = _ignite.GetCache<string, string>("cache").WithExpiryPolicy(new Apache.Ignite.Core.Cache.Expiry.ExpiryPolicy(timeSpan, timeSpan, timeSpan));
}
public void AddValue(string key, string values)
{
_cache.Put(key, values);
}
public void Dispose()
{
_ignite.Dispose();
}
public string GetValue(string key)
{
if (HasElement(key))
{
return _cache.Get(key);
}
return null;
}
public bool HasElement(string key)
{
return _cache.ContainsKey(key);
}
}
当使用和"conf.JvmMaxMemoryMb = 1024;"我会运行内存不足,LruEvictionPolicy似乎什么都不做。删除 JVM 最大。内存限制程序将 运行 分配到 ~5GB 直到结束。现在我正在检查结果:大约 2/5 的缓存数据仍在缓存中。这就是我的 wanted/expected 行为,但使用了太多内存。
有没有办法减少使用的内存?
简答:不要将 CopyOnRead
设置为 false
。默认为true
。
更长的解释:
将 CopyOnRead
设置为 false
会导致在内部存储序列化和反序列化的值。这在某些情况下可能会提高性能,但会增加内存使用量。
此外,当 CopyOnRead 为 false
(https://issues.apache.org/jira/browse/IGNITE-3347) 时,EvictionPolicy
计算内存大小存在错误。
此外,不要指望将 JvmMaxMemoryMb
和 EvictionPolicy.MaxMemorySize
设置为相同的值会起作用:Ignite 需要备用内存用于内部用途和 JVM GC 高效工作。