2014-04-05 105 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不適用的。它預計入場規模的分佈將保持不變。 –