2014-04-05 110 views
0

我写了一个小的infinispan缓存PoC(代码如下)来尝试和评估infinispan的性能。运行它时,我发现对于我的配置,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个元素×100个箱。预计= 807300实际= 411664404中的100 元素。差异= 509.92741731698254

这意味着,对于788千字节的数据我结束了〜392 MB的文件!

我在做什么错?

问题的Infinispan的版本,当你只存储越来越长的记录,以前使用的空间没有被重用是6.0.2.Final

回答

1

。 SingleFileStore中没有碎片整理策略,可用空间保留为入口空间列表的映射,但相邻的空闲空间不会合并。 因此,新条目总是添加在文件的末尾,并且开始处于分段和未使用状态。

顺便说一句,寻找出应有的大小,你还应该:

  • 使用JBoss编组站而不是Java序列化
  • 序列化的关键,以及
  • 连载Infinispan的元数据(如入门寿命,最后使用时间,可能的版本等...)
+0

即使所有的开销x500比率是疯了即使:-) – radai

+0

让我们来做数学,然后。对于100个垃圾桶中的每一个垃圾箱,您都会获得1,2 ... 1000的空间,因此每个垃圾桶和它的历史记录(可用空间)为1 + 2 + ... + 1000 = 1000 * 999/2 = 499500个值,其中你期望1000个值。这就是500倍的比例。 –

+0

我不会说它不是疯狂的,但是您的使用模式是SingleFileStore不适用的。它预计入场规模的分布将保持不变。 –