我用EhCache缓存了2.5 Gb的数据。我有32个不同大小的文件,但是总数据量是2.5 Gb。我用12G堆内存运行我的代码,但是整个数据集不能容纳12G的数据,它溢出到磁盘。你能告诉我配置中出了什么问题吗,或者EhCache总是占用那么多内存。所有的缓存我都把整数作为键,列表作为值(分隔文件的记录)
使用的JVM参数%JAVA\u HOME%\bin\JAVA。exe-server-d64-Xms12G-Xmx12G-XX:UseG1GC-XX:-省略StackTraceInFastThrow
下面是我用于缓存的代码片段
//Spring Configuration
@Bean(destroyMethod = "shutdown",name="batchCache")
public net.sf.ehcache.CacheManager ehCacheManager() {
DiskStoreConfiguration diskStoreConfiguration = new DiskStoreConfiguration();
diskStoreConfiguration.setPath("C:\\DiskCache");
net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
config.setName("NAV_BATCH");
config.addDiskStore(diskStoreConfiguration);
//config.setMaxBytesLocalHeap(MemoryUnit.GIGABYTES.toBytes(10));
net.sf.ehcache.CacheManager mgr = net.sf.ehcache.CacheManager.newInstance(config);
mgr.clearAll();
return mgr;
}
//Code to Obtain Cache manager
private CacheManager cacheManager = (CacheManager) ApplicationContextProvider.getApplicationContext().getBean("batchCache");
//Class level copy of Cache
private Cache cache;
protected Cache getCache(){
if(null == cache){
Cache managerCache = cacheManager.getCache(cacheName);
if(null == managerCache){
cache = createCache();
}else{
cache = managerCache;
}
}
return cache;
}
//Key is Integer and Values is List of String always
protected void putListRecordsInCache(Object key,List<Object> values){
Element element = new Element(key, values);
getCache().put(element);
}
public List<T> getValues(Object key){
Element e = getCache().get(key);
List<T> dataList = new LinkedList<>();
if(null == e){
return dataList;
}
List<String> lines = (List<String>) e.getObjectValue();
for(String line:lines){
T t = getMapper().convertValuesToObject(line, null);
dataList.add(t);
}
return dataList;
}
private Cache createCache(){
Cache managerCache = cacheManager.getCache(cacheName);
if(null == managerCache){
managerCache = new Cache(cacheConfig(cacheName) );
//managerCache = (Cache) cacheManager.addCacheIfAbsent(managerCache);
cacheManager.addCache(managerCache);
}
return managerCache;
}
private CacheConfiguration cacheConfig(String name) {
CacheConfiguration config = new CacheConfiguration();
config.name(name)
.memoryStoreEvictionPolicy("LRU")
.eternal(true)
.pinning(new PinningConfiguration().store(Store.LOCALMEMORY))
.logging(false)
.sizeOfPolicy(new SizeOfPolicyConfiguration().maxDepth(100000).maxDepthExceededBehavior("CONTINUE"))
.persistence(new PersistenceConfiguration().strategy(Strategy.LOCALTEMPSWAP))
.statistics(true);
;
long size = -1;
try {
size = Files.size(FileSystems.getDefault().getPath(getDataFileLocation(), getFileName()));
//System.out.println(new Date()+",Size of file "+getDataFileLocation()+"/"+getFileName()+" is "+size+" bytes");
} catch (IOException e) {
e.printStackTrace();
}
if(size > 0){
long cachesize = size*4;
config.maxBytesLocalHeap(cachesize, MemoryUnit.BYTES);
}else{
if(isValueGloballyCached){
config.maxBytesLocalHeap(100, MemoryUnit.MEGABYTES);
}else{
config.maxBytesLocalHeap(500, MemoryUnit.MEGABYTES);
}
}
return config;
}
下面是内存和CPU配置文件屏幕截图
我认为ehcache中有一个属性。xml,即maxBytesLocalOffheap,在您的情况下可能很有用。
请通过http://blog.terracotta.org/2015/04/13/ehcache-storage-tier-model-with-offheap/
如果ehache版本低于2.3,那么您需要运行手动线程来查找过期的内容,以便在堆中有足够的空间。
i、 后台线程定期执行getKeysWithExpiryCheck()。
我还遇到过ehcache使用太多内存以及在非常简单的测试示例上出现“MappedByteBufferSource异步刷新线程”错误的问题。根据你需要多少功能,我个人会使用BigArrayList。它可以像普通的ArrayList一样使用,并将使用LRU策略为您处理从磁盘到内存的所有I/O。您可以将对象列表作为元素存储在BigArrayList中,并像处理普通ArrayList一样对其进行操作。根据元素的大小和可用内存,您可能需要尝试在内存中存储多少元素。它的优点是易于使用,而且确实有效。
问题不是“Ehcache使用了太多内存”。这个问题更像是“以高效的方式在内存中缓存巨大的文件”。
此外,您希望随机访问文件的每一行。
java字符串对象为您要存储的每个字符串添加38个字节,每个字符串为您的整数
键存储16个字节(8个用于看守4个用于整数到16个字节)。对于32位环境,这将向您的最大文件添加约550mb。在64位环境中,情况会变得更糟。
我猜,你添加了大约1GB的对象开销到你的594 mb文件中,我没有考虑ehache使用的Element
对象。如果你研究那个对象,你会很清楚内存浪费在哪里。
所以,我想我已经弄清楚了为什么你的2.5GB文件会占用这么多内存。
我将文件的文本存储在一个String
对象中,并创建一个单独的int[]
(而不是intger[]
)数组,用于保存每行的偏移量。
因此,获取行1000
的文本将是:
// text of the the file
String text;
// int array of offset.
int[] offset;
// todo: check if there is line 1000
int start = offset[999];
int end = offset.length > 1000 ? offset[1000] : text.length();
String line1000 = text.substring(start, end);
如果采用这种方法,每个文件都会得到一个字符串和一个int数组。字符串
对象保存文本,数组保存偏移量。
我在Python3.5上使用selenium,在ububtu vps上使用chrome webdriver,当我运行一个非常基本的脚本(导航到站点,输入登录字段,单击)时,内存占用增加了400MB,cpu占用增加到100%。我可以做些什么来降低这个数字,或者如果没有的话,有什么其他的办法吗? 我正在python中测试selenium,但我计划在java中使用它进行一个项目,其中内存使用对我来说是一
如EhCache留档所述: 实际上,这意味着持久性内存中缓存将启动,其所有元素都将在磁盘上。[...]因此,Ehcache设计不会在启动时将它们全部加载到内存中,而是根据需要懒惰地加载它们。 我希望内存缓存启动时将所有元素都存储在内存中,我该如何实现? 这是因为我们的网站对缓存执行了大量的访问,所以我们第一次访问网站时,它的响应时间非常长。
我正在使用框架用iPhone摄像头捕捉视频,我的代码: 在之前,一切都很顺利,内存被限制在3M,但在之后,内存使用量每秒增加0.06M,几分钟后,应用程序会因为内存警告而崩溃。似乎占用了太多内存,并且可能存在内存泄漏问题。 那么如何减少内存使用量呢? iOS版本:7.1.1
我并不了解Java特别是Java调试,但在Jenkins中使用Monitoring进行堆转储,然后在Eclipse中使用MAT对其进行解码,显示总内存使用量为169.4MB,而在Jenkins中Monitoring似乎经常使用内存,GCs也经常运行。-XMX是4G。 为什么我只有169.4MB的mat?可能是因为在进行转储之前,Jenkins执行了GC吗?如果是,我是否可以避免它以看到完整的内存转
我们在应用程序中使用ehcache。请看以下配置: 既然我们已经配置为eternal="true ",那么它会永远创建缓存吗?。磁盘空间有可能用完吗? 对磁盘存储的性能会有什么影响?。肯定比内存缓存慢,但是影响有多大。 如果磁盘中存储了更多缓存,是否会导致执行多个文件操作的IO问题? 请建议生产级应用的最佳实践。假设我们有一个3 GB的堆内存和25000个并发用户访问应用程序。但是,我们的应用程序
我有一个tomcat用ignite进行会话聚类。我有一个示例登录调用,它为一个用户创建一个会话,在成功登录之后,我看到下面的日志打印出来,其中堆大小波动很大。 我的问题是 为什么整个堆大小是波动的?。 感谢任何指点。 问候你,阿拉温德