標籤:android style blog http io ar os 使用 sp
1.使用緩衝的目的緩衝是存取資料的臨時地,因為取未經處理資料代價太大了,加了緩衝,可以取得快些。緩衝可以認為是未經處理資料的子集,它是從未經處理資料裡複製出來的,並且為了能被取回,被加上了標誌。
在android開發中,經常要訪問網路資料比如大量網狀圖片,如果每次需要同一張圖片都去網路擷取,這代價顯然太大了。可以考慮設定本地檔案快取和記憶體緩衝,儲存從網路取得的資料;本地檔案快取空間並非是無限大的,容量越大讀取效率越低,可設定一個折中緩衝容量比如10M,如果緩衝已滿,我們需要採用合適的替換策略換掉一個已有的資料對象,並替之已一個新的資料對象;記憶體緩衝作為最先被讀取的資料,應該儲存那些經常使用的資料對象,且記憶體容量有限,記憶體緩衝的容量也應該限定。依照這樣的做法,取得一個圖片(總圖片數為N)的流程應該是這樣的:
a.先在記憶體緩衝取(設儲存K個),若取到則返回(命中率為K/N,時間為tA),否則進行b;
b.在本地檔案快取(設能儲存M個)中取,若取到則返回並更新記憶體緩衝(命中率為(M-K)/N,時間為tB),否則進行c;
c.通過網路下載圖片,並更新本地檔案快取和記憶體緩衝(命中率為(N-M)/N,時間為tC);
取一張圖片的時間期望為:W = tA * (K/N) + tB * (M-K)/N + tC * (N-M)/N ,其中tA < tB < tC ,為使W代價小,即儘可能快的取得資料,我們應該提高記憶體緩衝的命中率和本地檔案快取的命中率,但兩者的容量都是有限制的,所以必須使用適合替換演算法來更新兩者所儲存的對象。選擇合適的替換演算法是緩衝的痛點所在。
2.常見緩衝演算法Least Frequently Used(LFU)
對每個緩衝對象計算他們被使用的頻率。把最不常用的緩衝對象換走。
Least Recently User(LRU)
把最近最少使用的緩衝對象給換走。總是需要去瞭解在什麼時候,用了哪個緩衝對象。如果有人想要瞭解為什麼總能把最近最少使用的對象踢掉,是非常困難的。瀏覽器就是使用了LRU作為緩衝演算法。新的對象會被放在緩衝的頂部,當緩衝達到了容量極限,我會把底部的對象踢走,而技巧就是:我會把最新被訪問的緩衝對象,放到緩衝池的頂部。
所以,經常被讀取的緩衝對象就會一直呆在緩衝池中。可以用資料或者鏈表實現。其改進演算法有LRU2 和 2Q。
Least Recently Used 2(LRU2)
把被兩次訪問過的對象放入緩衝池,當緩衝池滿了之後,我會把有兩次最少使用的緩衝對象踢走。因為需要跟蹤對象2次,訪問負載就會隨著緩衝池的增加而增加。如果用在大容量的緩衝池中,就會有問題。另外,還需跟蹤那麼不在緩衝的對象,因為他們還沒有被第二次讀取。這比LRU好。
Two Queues(2Q)
把被訪問的資料放到LRU的緩衝中,如果該對象再一次被訪問,就把他轉移到第二個更大的LRU緩衝。替換掉緩衝對象是為了保持第一個緩衝池是第二個緩衝池的1/3。當緩衝的訪問負載是固定的時候,把 LRU 換成 LRU2,就比增加緩衝的容量更好。這種機制使得該演算法比 LRU2 更好。
Adaptive Replacement Cache(ARC)
這種演算法介於 LRU 和 LFU 之間,由2個 LRU 組成,第一個,也就是 L1,包含的條目是最近只被使用過一次的,而第二個 LRU,也就是L2,包含的是最近被使用過兩次的條目。因此,L1 放的是新的對象,而 L2 放的是常用的對象。該演算法是是效能最好的緩衝演算法之一,能夠自調,並且是低負載的。儲存著曆史對象,這樣,就可以記住那些被移除的對象,同時,也可以看到被替換掉的對象是否可以留下,取而代之的是替換別的對象。該演算法記憶力很差,但是很快,適用性也強。
Most Recently Used(MRU)
該演算法與 LRU是對應的。它替換掉最近最多被使用的對象,你一定會問為什麼。原因是,當一次訪問過來的時候,有些事情是無法預測的,並且在緩衝系統中找出最少最近使用的對象是一項時間複雜度非常高的運算。該演算法在資料庫記憶體緩衝中很見!每當一次緩衝記錄的使用,會把它放到棧的頂端。當棧滿了的時候,會把棧頂的對象給換成新進來的對象!
First in First out(FIFO)
這是一個低負載的演算法,並且對緩衝對象的管理要求不高。通過一個隊列去跟蹤所有的緩衝對象,最近最常用的緩衝對象放在後面,而更早的緩衝對象放在前面,當緩衝容量滿時,排在前面的緩衝對象會被踢走,然後把新的緩衝對象加進去。很快,但是不適用。
Second Chance
改進的FIFO演算法,比 FIFO 好的地方是改善了 FIFO 的成本。一樣是在觀察隊列的前端,但是很FIFO的立刻替換不同,它會檢查即將要被踢出的對象有沒有之前被使用過的標誌(1一個bit表示),如果沒有被使用過,就把他換出;否則,把這個標誌位清除,然後把這個緩衝對象當做新增緩衝對象排入佇列。你可以想象就這就像一個環隊列。當再一次在隊頭碰到這個對象時,由於它已經沒有標誌位,可以立刻就它換出。在速度上比FIFO快。
CLock
這是一個更好的FIFO,也比 second chance更好。因為它不會像second chance那樣把有標誌的緩衝對象放到隊列的尾部,但是也可以達到second chance的效果。它持有一個裝有緩衝對象的環形列表,頭指標指向列表中最老的緩衝對象。當緩衝miss發生並且沒有新的緩衝空間時,它會根據指標指向的緩衝對象的標誌位去決定應該怎麼做。如果標誌是0,直接用新的緩衝對象替代這個緩衝對象;如果標誌位是1,把頭指標遞增,然後重複這個過程,直到新的緩衝對象能夠被放入。
Simple time-based
通過絕對的時間周期去失效那些緩衝對象。對於新增的對象,儲存特定的時間。很快,但不適用。
Extended time-based expiration
通過相對時間去失效緩衝對象的;對於新增的緩衝對象,儲存特定的時間,比如是每5分鐘,每天的12點。
Sliding time-based expiration
被管理的緩衝對象的生命起點是在這個緩衝的最後被訪問時間算起。很快,不太適用。
緩衝演算法主要考慮到了下面幾點:
成本。如果緩衝對象有不同的成本,應該把那些難以獲得的對象儲存下來。
容量。如果緩衝對象有不同的大小,應該把那些大的緩衝對象清除,這樣就可以讓更多的小緩衝對象進來了。
時間。一些緩衝還儲存著緩衝的到期時間。電腦會失效他們,因為他們已經到期了。
3.增強使用者體驗的圖片緩衝架構詳見 android上的一個網路介面和圖片緩衝架構enif 。
- 上一篇謹慎去擷取控制項的高和寬,以防帶來不必要的效能問題
- 下一篇web service和rpc的區別
android上的緩衝、緩衝演算法和緩衝架構