문제

업데이트:Hey guys 답변 주셔서 감사합니다.마지막 밤 그리고 오늘 밤을 시도했는 몇 가지 다른 접근법 중 하나와 함께 유사한 중 하나 아래에 배치하여 제프(나도 이미 그가 무엇을 제안에 그 업데이트와 함께 넣어 내 자신의 단순한 LL 구현을 위한 추가적인 이익).여기에는 코드,이 시점에서 그것은 보이지 않는 particularily 정상이 되었습을 통해 이 수많은 시간을 변경하는 아무것도 수 있는 쇠고기는 최대 성능.

public class NewLRU2<K, V> where V : class
{
    int m_iMaxItems;
    Dictionary<K, LRUNode<K, V>> m_oMainDict;

    private LRUNode<K,V> m_oHead;
    private LRUNode<K,V> m_oTail;
    private LRUNode<K,V> m_oCurrent;

    public NewLRU2(int iSize)
    {
        m_iMaxItems = iSize;
        m_oMainDict = new Dictionary<K, LRUNode<K,V>>();

        m_oHead = null;
        m_oTail = null;
    }

    public V this[K key]
    {
        get
        {
            m_oCurrent = m_oMainDict[key];

            if (m_oCurrent == m_oHead)
            {
                //do nothing
            }
            else if (m_oCurrent == m_oTail)
            {
                m_oTail = m_oCurrent.Next;
                m_oTail.Prev = null;

                m_oHead.Next = m_oCurrent;
                m_oCurrent.Prev = m_oHead;
                m_oCurrent.Next = null;
                m_oHead = m_oCurrent;
            }
            else
            {
                m_oCurrent.Prev.Next = m_oCurrent.Next;
                m_oCurrent.Next.Prev = m_oCurrent.Prev;

                m_oHead.Next = m_oCurrent;
                m_oCurrent.Prev = m_oHead;
                m_oCurrent.Next = null;
                m_oHead = m_oCurrent;
            }

            return m_oCurrent.Value;
        }
    }

    public void Add(K key, V value)
    {
        if (m_oMainDict.Count >= m_iMaxItems)
        {   
            //remove old
            m_oMainDict.Remove(m_oTail.Key);

            //reuse old
            LRUNode<K, V> oNewNode = m_oTail;
            oNewNode.Key = key;
            oNewNode.Value = value;

            m_oTail = m_oTail.Next;
            m_oTail.Prev = null;

            //add new
            m_oHead.Next = oNewNode;
            oNewNode.Prev = m_oHead;
            oNewNode.Next = null;
            m_oHead = oNewNode;
            m_oMainDict.Add(key, oNewNode);
        }
        else
        {
            LRUNode<K, V> oNewNode = new LRUNode<K, V>(key, value);
            if (m_oHead == null)
            {
                m_oHead = oNewNode;
                m_oTail = oNewNode;
            }
            else
            {
                m_oHead.Next = oNewNode;
                oNewNode.Prev = m_oHead;
                m_oHead = oNewNode;
            }
            m_oMainDict.Add(key, oNewNode);
        }
    }

    public bool Contains(K key)
    {
        return m_oMainDict.ContainsKey(key);
    }
}


internal class LRUNode<K,V>
{
    public LRUNode(K key, V val)
    {
        Key = key;
        Value = val;
    }

    public K Key;
    public V Value;
    public LRUNode<K, V> Next;
    public LRUNode<K, V> Prev;
}

몇 가지가 있는 부분을 찾/느낌이 남았--같은 재사용하는 오래된 노드의하는 경우 추가 그러나 나를 얻을 수 있었다고 평가할 수 있는 향상 porformance 있습니다.도에 차이를 만들어서 실제적인 속성에서 노드를 공개 변수가 있지만,나는 어떻게 되는지와 함께 무료 세면용품 등이 있습니다.이 시점에서 위의 코드는 거의 전적으로 성능-제한된 사전 작업,그래서 나는 확실하지 않다 나는 훨씬 더 나의 반하게 됩니다.내가 계속 생각하는 그것의 일부 응답합니다.

설명서 원래의 게시물:안녕하세요.그래서 내가 기록했는 간단하량 LRU 구현에서 사용하기 위해 압축 라이브러리(나는 그것을 사용하여하는 바이트에서 문자열을 입력을 기반으로 해시,LZW 스타일),그리고 나는 방법을 찾고 있습니다.

도움이 되었습니까?

해결책

업데이트 #2

이렇게하면 링크 된 목록 제거에서 목록 트래버살의 필요성이 줄어 듭니다. 키와 값이 모두있는 lrucachenode를 소개합니다. 키는 캐시를 다듬을 때만 사용됩니다. 각 노드가 본질적으로 다음과 백 참조와 함께 Lrucachenode 인 자체 링크 된 목록 구현을 작성하면 더 나은 성능을 얻을 수 있습니다. 이것은 Linkedhashmap이하는 일입니다 (참조 이것들 질문).

public class LruCache<K, V>
{
    private readonly int m_iMaxItems;
    private readonly Dictionary<K, LinkedListNode<LruCacheNode<K, V>>> m_oMainDict;
    private readonly LinkedList<LruCacheNode<K, V>> m_oMainList;

    public LruCache(int iSize)
    {
        m_iMaxItems = iSize;
        m_oMainDict = new Dictionary<K, LinkedListNode<LruCacheNode<K, V>>>();
        m_oMainList = new LinkedList<LruCacheNode<K, V>>();
    }

    public V this[K key]
    {
        get
        {
            return BumpToFront(key).Value;
        }
        set
        {
            BumpToFront(key).Value = value;
        }
    }

    public void Add(K key, V value)
    {
        LinkedListNode<LruCacheNode<K, V>> newNode = m_oMainList.AddFirst(new LruCacheNode<K, V>(key, value));
        m_oMainDict.Add(key, newNode);

        if (m_oMainList.Count > m_iMaxItems)
        {
            m_oMainDict.Remove(m_oMainList.Last.Value.Key);
            m_oMainList.RemoveLast();
        }
    }

    private LruCacheNode<K, V> BumpToFront(K key)
    {
        LinkedListNode<LruCacheNode<K, V>> node = m_oMainDict[key];
        if (m_oMainList.First != node)
        {
            m_oMainList.Remove(node);
            m_oMainList.AddFirst(node);
        }
        return node.Value;
    }

    public bool Contains(K key)
    {
        return m_oMainDict.ContainsKey(key);
    }
}

internal sealed class LruCacheNode<K, V>
{
    private readonly K m_Key;
    private V m_Value;

    public LruCacheNode(K key, V value)
    {
        m_Key = key;
        m_Value = value;
    }

    public K Key
    {
        get { return m_Key; }
    }

    public V Value
    {
        get { return m_Value; }
        set { m_Value = value; }
    }
}

이것이 당신의 환경에서 개선되었는지 확인하기 위해 물건을 프로필해야합니다.

사소한 업데이트 : Bumptofront를 업데이트하여 Node가 이미 Tim Stewart의 의견 당 전면에 있는지 확인했습니다.

다른 팁

LRU 캐시의 요점이 캐시를 다듬고 가장 적은 시간을 버릴 수있는 것입니까? :-) 캐시를 다듬을 코드가 보이지 않습니다. 검색 사용 사례에 대한 고성능을 원할 가능성이 높기 때문에 트림 사용 사례가 덜 중요합니다. 목록 유지 보수를 트림 프로세스에 오프로드하지 않겠습니까?

IOW, 항목을 캐시에 던지지 만 검색시 타임 스탬프. 항목을 재정렬하지 말고 사용할 때마다 표시하십시오. 진정한 DateTime 타임 스탬프가 될 수 있거나 클래스에서 간단한 카운터가 될 수 있으며, 가장 많은 숫자가 가장 최근에 사용되었습니다. 그런 다음 트림 과정에서 나무 전체를 걷고 가장 오래된 스탬프로 항목을 제거하십시오.

하드웨어와 함께 캐시지 않고,말 128 요소,그리고 유지하기 위해 항목 1-128 개의해야 할 수 있습으로 그것 32x4,그래서 32 행 4 요소의 각.첫 번째 5 비트의 주소를 확인하는 것이는 32 개의 행이 주는 것이 지도하에,당신은 검색만 4 항목을 찾지 못한 경우 대체의 가장 오래된 4.

이것은 훨씬 빠르고,IIRC10%이내의 적중률은 1x128 캐시입니다.

번역,당신은 당신의 하나의 연결 리스트는 여러 사람이다,그래서 이었다 훨씬 빠릅니다.당신이 있어야의 방법을 결정하는 목록 또는 특정 항목에 매핑됩니다.

는 점으로 목록에서 성장 크기,당신이 얻을 감소하는 반환에서 유지하기 위해 노력하고 완벽한 정확도로 정확한 순서는 각 요소의 목록에 있습니다.을 수도 있습와 더 나은 순서 없는 목록을 임의로 대체하는 어떤 요소가 있을 때 캐시 놓치지 마세요.의 크기에 따라 달라집니다,당신의 목록과 페널티를 놓치의 비용을 유지하 목록입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top