LRU 緩存的魔力

原文首發於 https://leonchen1024.com/2018/12/23/S1ep1-The-macgic-of-LRU-Cache/

場景

假設這麼一個情況,當你需要多次展示同一個圖片的時候,如果你重複從硬盤中加載圖片的話,那麼會造成資源的浪費,甚至可能會OOM.

這個時候我們可以使用 cache 來避免這種情況,我們只從硬盤中加載一次到內存中,然後在需要的時候反覆使用這個照片.

但是,當這個 cache 裏的資源已經裝滿的時候,那麼我們就必須移除cache裏面的某些數據,來給要加入的數據騰出空間.

解決方案

在這種情況下,我們應該選擇移除哪些資源纔是最有優的呢?顯而易見的,我們應該移除之後不會用到的資源,還有就是間隔最久纔會用到的資源.這裏有一個詳細的最優算法如下:

T = m * T_m + T_h + E

其中:

T = 平均內存引用時間

m = 沒選中的概率 = 1 - (選中的概率)

T_m = 當沒選中的時候主內存訪問的時間(或者,如果是多級緩存的時候,還要算上更低級的緩存內存引用時間的平均值)

T_h = 延遲 : 當選中該資源的時候緩存引用的時間

E = 各種副作用,比如多處理器系統中的 排隊效應

原文首發於 https://leonchen1024.com/2018/12/23/S1ep1-The-macgic-of-LRU-Cache/
LRU

要得到一個完美的方法是很複雜的,這裏我們介紹一個常用的算法,叫做 LRU cache (least recently used),它的原理很簡單,就是把使用的元素提到隊列的開始,這樣最近使用的資源將會在開始的地方,而那些長期未被使用的資源將會在後面,然後當空間不夠的時候將會從後面開始釋放資源.LRU 的思路是最近使用的資源他們就推測他在未來也有更大的可能性會被使用.

LRU 並不是一個普通的容器.他需要一些策略來實現他的要求.

  • LruCache 由鍵值對組成 , 形如 LruCache<key,value>

  • 它需要有一個最大值,要注意它的取值,太小的話那麼緩存不了多少東西,會導致頻繁的重新讀取,導致失去緩存的意義,太大的話可能會導致 oom.所以最好是根據你的應用當前可用的內存來決定這個大小.

  • //set the max memory used by lru
    
    ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    int availMemInBytes = am.getMemoryClass() * 1024 * 1024;
    //8 is a common value , we can twist it by how much memory can we app used,
    //and what kind of the phone we run on.
    LruCache bitmapCache = new LruCache<String,Bitmap>(availMemInBytes / 8);
    

    其中 8 是一個比較通用的值,當然你可以根據你的應用所佔用的內存來進行調整,還有運行的機型的限制等.

  • 我們還需要知道里面存儲的每一個對象的值的大小.比如我們可以
    Public class ThumbnailCache extends LruCache<String,Bitmap>{
    @Override
    protected int sizeOf(String key,Bitmap value){
    //return the size of the in-memory bitmap,
    //counted against maxSizeBytes
    return value.getByteCount();
    }
    }

  • 當我們從 LruCache 中獲取數據的時候,需要對數據已經被回收或者沒有進入過緩存的情況做處理.
    // get data from Lru and put data to Lru

    Bitmap bmpToDraw = mCache.get(filename);
    if(bmpToDraw == null){
        bmpToDraw = BitmapFactory.decodeFile(filename);
        mCache.put(filename,bmpToDraw);
    }
    

還要注意的一點是,當你存進一個較大的對象的時候,有時候 LruCache 會同時清理多個資源來給這個對象騰出位置.

原文首發於 https://leonchen1024.com/2018/12/23/S1ep1-The-macgic-of-LRU-Cache/

Resource

https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE

About Me

我的博客 leonchen1024.com

我的 GitHub https://github.com/LeonChen1024

微信公衆號

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章