Jive與Ofbiz的Cache機制比較 請大家討論

PinkFloyd發表於2003-10-31
Jive與Ofbiz都用實現了Cache機制,兩者的原理都很類似,就是把所要快取的物件加到HashMap雜湊對映表中,用兩個連結串列分別維持著快取物件

和每個快取物件的生命週期。如果一個快取物件被訪問到,那麼就把它放到連結串列的最前面,然後不定時地把要快取的物件加入連結串列中,把過期

物件刪除,如此反覆。

在Jive(Jive2.6.0)中用到了Cache\Cacheable\CacheObject\CacheSizes\DefaultCache\LinkdList\LinkdListNode等類;
而在Ofbiz中,只用了一個類:UtilCache!!

在此比較一下他們的實現差異:

1、在Jive中有一個Cacheable介面,只有一個方法getCachedSize()

public interface Cacheable extends Serializable {
    public int getCachedSize();
}
<p class="indent">

所有需要Cache的物件都必須implements該介面並實現getCachedSize(),其目的是為了在快取的時候得到物件的大小。
當呼叫DefaultCache中的put方法的時候,會得到該物件的大小:

    public synchronized Object put(Object key, Object value)
    {
        remove(key);
        int objectSize = calculateSize(value);
        if(maxCacheSize > 0 && (double)objectSize > (double)maxCacheSize * 0.9)
        {
            Log.warn("Cache: " + name + " -- object with key " + key + " is too large to fit in cache. Size is " + 

objectSize);
            return value;
        } else
        {
            cacheSize += objectSize;
            CacheObject cacheObject = new CacheObject(value, objectSize);
            map.put(key, cacheObject);
            LinkedListNode lastAccessedNode = lastAccessedList.addFirst(key);
            cacheObject.lastAccessedListNode = lastAccessedNode;
            LinkedListNode ageNode = ageList.addFirst(key);
            ageNode.timestamp = System.currentTimeMillis();
            cacheObject.ageListNode = ageNode;
            cullCache();
            return value;
        }
    }

    protected int calculateSize(Object object)
    {
        if(object instanceof Cacheable)
            return ((Cacheable)object).getCachedSize();
	......
    }
<p class="indent">

而在Ofbiz中根本都不關心每個物件的Size,只關心總體的HashMap的Size,他的程式碼如下:

    public synchronized void put(Object key, Object value) {
        if (key == null)
            return;

        if (maxSize > 0) {
            // when maxSize is changed, the setter will take care of filling the LRU list
            if (cacheLineTable.containsKey(key)) {
                keyLRUList.remove(key);
                keyLRUList.addFirst(key);
            } else {
                keyLRUList.addFirst(key);
            }
        }

        if (expireTime > 0) {
            cacheLineTable.put(key, new UtilCache.CacheLine(value, useSoftReference, System.currentTimeMillis()));
        } else {
            cacheLineTable.put(key, new UtilCache.CacheLine(value, useSoftReference));
        }
        if (maxSize > 0 && cacheLineTable.size() > maxSize) {
            Object lastKey = keyLRUList.getLast();
            remove(lastKey);
        }
    }
<p class="indent">

個人覺得,Ofbiz中處理得更簡潔,其實不就是判斷快取是否> maxSize嗎!用HashMap.Size()我覺得足以了,而且對於Jive的方式,每個需要

Cache的物件必須implements Cache介面,較麻煩。
當然是否有其他妙處就不得而知了,還請各位高人指點。

2、連結串列的問題也挺有意思,Jive為了實現雙向聯表用了兩個類:LinkdList\LinkdListNode,記錄最近訪問的物件列表和按時間順序排列的物件列表。
而在Ofbiz中用的是java.util.LinkedList:
public LinkedList keyLRUList = new LinkedList();
功能上好像也沒有什麼兩樣,不知道Jive問什麼還要如此破費周折?還請各位高人指點。

3、Ofbiz中物件過時清除功能寫得很一般,他是在get方法中實現的:

    public Object get(Object key) {

        UtilCache.CacheLine line = (UtilCache.CacheLine) cacheLineTable.get(key);

        if (hasExpired(line)) {//如果過期
            remove(key);
            line = null;
        }

        if (line == null) {
            // remove掉後還要告訴我過期!!
            missCount++;
            return null;
        }
    }
<p class="indent">

Jive中實現的就巧妙多了,而且在這上面寫得較精彩.

個人認為兩者實現的功能相當,Ofbiz程式碼更簡單,就是不知道兩者的效能究竟怎樣,請各位高人多多指教,請討論。

sailingyangjian@hoatmail.com

相關文章