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

Java infinispan文件存储大小与数据大小不成比例,java,infinispan,Java,Infinispan,我编写了一个小型infinispan缓存PoC(下面的代码),以尝试评估infinispan的性能。在运行它时,我发现,对于我的配置infinispan,显然无法清除磁盘中缓存项的旧副本,导致磁盘空间消耗量超出预期的数量级 如何将磁盘使用率降低到实际数据的大致大小 以下是我的测试代码: import org.infinispan.AdvancedCache; import org.infinispan.manager.DefaultCacheManager; import java.io.By

我编写了一个小型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;
        }
    }
}
import org.infinispan.AdvancedCache;
导入org.infinispan.manager.DefaultCacheManager;
导入java.io.ByteArrayOutputStream;
导入java.io.File;
导入java.io.ObjectOutputStream;
导入java.io.Serializable;
导入java.util.array;
导入java.util.Random;
公共类应用程序{
最终静态整数元素每箱=1000;
容器的最终静态整数=100;
公共静态void main(字符串[]args)引发异常{
File storeFile=新文件(“store/store.dat”);
if(storeFile.exists()&&!storeFile.delete()){
抛出新的IllegalStateException(“无法从上一次运行中删除存储文件”);
}
DefaultCacheManager cm=新的DefaultCacheManager(“infinispan.xml”);
AdvancedCache=cm.getCache(“存储”).getAdvancedCache();
Random rng=新随机(System.currentTimeMillis());

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

顺便说一句,要找出预期尺寸,您还应:

  • 使用JBoss编组而不是Java序列化
  • 还要序列化密钥
  • 序列化Infinispan元数据(例如条目寿命、上次使用时间、可能的版本等)

我敢肯定,即使有这么多开销,x500的比例也是疯狂的:-)那么让我们来计算一下。100个箱子中的每一个都有1、2…1000的空间占用,因此每个箱子和它的历史(自由空间)是1+2+…+1000=1000*999/2=499500个值,你期望的是1000个值。这就是500倍比率的来源。我不是说这不疯狂,但你的使用模式是SingleFileStore不适合的。它期望条目大小的分布是恒定的。我理解500来自哪里。我的意思是什么就是说,即使我“正确地”计算了预期的大小,这个比例仍然是相同的(并且随着时间的推移而增加).我还认为我的用例应该比你想象的更常见-任何保留任何类型数据样本的用例都会涉及存储不断增加的值问题是这是否是一种好的做法-通常在读取时不需要查看所有数据(尤其是为更新而读取)。存储此类列表的建议方法是将它们分块到具有“下一个键”引用的有限大小的条目中。此外,如果您没有以同步方式增长所有条目,则较新(较短)的列表将占用较旧列表之后的剩余空间。
<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>