gpt4 book ai didi

java - infinispan 文件存储大小与数据大小不成比例

转载 作者:行者123 更新时间:2023-12-02 05:58:13 27 4
gpt4 key购买 nike

我编写了一个小型 infinispan 缓存 PoC(代码如下)来尝试评估 infinispan 性能。在运行它时,我发现对于我的配置 infinispan 显然不会从磁盘中清除缓存条目的旧副本,导致磁盘空间消耗比预期高出几个数量级。

我该怎么做才能将磁盘使用量降低到大约实际数据的大小?

这是我的测试代码:

import org.infinispan.AdvancedCache;
import org.infinispan.manager.DefaultCacheManager;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Random;

public class App {
final static int ELEMENTS_PER_BIN = 1000;
final static int NUM_OF_BINS = 100;

public static void main(String[] args) throws Exception {
File storeFile = new File("store/store.dat");
if (storeFile.exists() && !storeFile.delete()) {
throw new IllegalStateException("unable to delete store file from previous run");
}

DefaultCacheManager cm = new DefaultCacheManager("infinispan.xml");
AdvancedCache<String, Bin> cache = cm.<String,Bin>getCache("store").getAdvancedCache();

Random rng = new Random(System.currentTimeMillis());

for (int i=0; i<ELEMENTS_PER_BIN; i++) {
for (int j=0; j<NUM_OF_BINS; j++) {
String key = "bin-"+j;
Bin bin = cache.get(key); //get from cache
if (bin==null) {
bin = new Bin();
}
bin.add(rng.nextLong()); //modify
cache.put(key, bin); //write back
}
}

long expectedSize = 0;

for (int j=0; j<NUM_OF_BINS; j++) {
String key = "bin-"+j;
Bin bin = cache.get(key);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(bin);
oos.flush();
oos.close();
expectedSize += baos.size();
baos.close();
}

long actualSize = new File("store/store.dat").length();

System.err.println(ELEMENTS_PER_BIN+" elements x "+NUM_OF_BINS+" bins. expected="+expectedSize+" actual="+actualSize+" in "+cache.size()+" elements. diff="+(actualSize/(double)expectedSize));
}

public static class Bin implements Serializable{
private long[] data = null;
public void add(long datum) {
data = data==null ? new long[1] : Arrays.copyOf(data, data.length+1); //expand capacity
data[data.length-1] = datum;
}
}
}

这是 infinispan 配置:

<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:6.0 http://www.infinispan.org/schemas/infinispan-config-6.0.xsd"
xmlns="urn:infinispan:config:6.0">
<namedCache name="store">
<eviction strategy="LRU" maxEntries="20"/>
<persistence passivation="false">
<singleFile location="store">
<async enabled="false"/>
</singleFile>
</persistence>
</namedCache>
</infinispan>

infinispan(应该是?)配置为直写式缓存,其中包含 RAM 中的 20 个最新元素以及磁盘上所有内容的实时副本。

运行上面的代码会得到以下结果:

1000 elements x 100 bins. expected=807300 actual=411664404 in 100 elements. diff=509.92741731698254

这意味着对于 788 KB 的数据,我最终得到的文件约为 392 MB!

我做错了什么?

有问题的 infinispan 版本是 6.0.2.Final

最佳答案

当您只存储越来越长的记录时,之前使用的空间不会被重复使用。 SingleFileStore 中没有碎片整理策略,可用空间保留为条目空间列表的映射,但相邻的可用空间不会合并。因此,新条目总是添加在文件的末尾,而开头是碎片且未使用的。

顺便说一下,为了找出预期的大小,您还应该:

  • 使用 JBoss 编码而不是 Java 序列化
  • 同时序列化 key
  • 序列化 Infinispan 元数据(例如条目生命周期、上次使用时间、可能的版本等...)

关于java - infinispan 文件存储大小与数据大小不成比例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22878059/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com