当前位置: 首页 > 知识库问答 >
问题:

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

吕鸿文
2023-03-14

我编写了一个小型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个元件x 100个箱子。100个元素中的预期值=807300实际值=411664404。差异=509.92741731698254

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

我做错了什么?

有问题的infinispan版本是6.0.2。最终

共有1个答案

时恩
2023-03-14

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

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

  • 使用JBoss编组代替Java序列化
  • 也序列化密钥
  • 序列化Infinispan元数据(如条目寿命、上次使用时间、可能的版本等)
 类似资料:
  • 我有大约500MB的H2数据库。 H2的版本是1.2.147。 数据库的存储引擎是PageStore。 JDBC URL如下所示。 jdbc:h2:file://C:/h2/client;如果存在=真;MVCC=真;数据库\u事件\u侦听器。H2DBMonitor';AUTO_SERVER=TRUE;对数=2 我做了一个版本的H2 1.4.192没有改变数据库的存储引擎。 当我的客户使用数据库时,

  • 我使用Infinispan缓存来存储值。代码每10分钟写入一次缓存,缓存大小约为400mb。它的生存时间约为2小时,最大条目数为1600万条,尽管目前在我的测试中,条目数没有超过200万条左右(我可以通过检查jconsole中的MBean/指标来了解这一点)。 当我启动jboss时,java堆大小是1.5Gb到2Gb。为jboss分配的最大内存的-Xmx设置是4Gb。 当我禁用Infinispan

  • 什么是 Firebase 存储上传文件大小限制?我在网站上找不到该信息。

  • 我正在使用AngularFire2成功将图像上传到Firebase Storage。 我有以下上传代码。 我想解决几个问题。 如何设置文件大小限制?这意味着我希望用户能够上传小于10mb的文件。 如何限制文件编号?这意味着我希望一个用户只能上传3个文件。 如果没有firebase服务器规模的解决方案,请推荐一些客户端规模的解决方案。 谢谢

  • 问题内容: 以下代码是我编写的PHP Web服务的一部分。它需要一些上载的Base64数据,对其进行解码,然后将其附加到文件中。这一切都很好。 问题是,当我在追加操作之后读取文件大小时,会得到文件在追加操作之前的大小。 我究竟做错了什么? 系统是: PHP 5.2.14 阿帕奇2.2.16 Linux内核2.6.18 问题答案: 在基于Linux的系统上,提取的数据是“ statcached”。

  • 大小和比例 你能够通过精灵的width和height属性来改变它的大小。这是怎么把width调整成80像素,height调整成120像素的例子: cat.width = 80; cat.height = 120; 在setup函数里面加上这两行代码,像这样: function setup() { //Create the `cat` sprite let cat = new Sprite(