当前位置:网站首页>[glide] cache implementation - memory and disk cache
[glide] cache implementation - memory and disk cache
2022-07-04 17:00:00 【Jkwen2022】
brief introduction
This article is mainly a preliminary understanding of Glide Cache mode and implementation of , It is mainly divided into the following parts :
- Glide Cache mode of
- Principle of memory and disk cache
- Specific implementation of cache algorithm
Glide Cache mode of
Glide There are two main cache methods , Memory cache and disk cache . Memory cache , Depending on whether the data is currently in use , And then you can subdivide it into Active and Not Active. Disk cache , According to whether deformation has been carried out , And then you can subdivide it into Resource Cache「 Refers to the cache after deformation 」 and Data Cache「 Refers to the source data cache 」. Here is a brief introduction to memory and disk cache .
//GlideBuilder.java
@NonNull
Glide build(@NonNull Context context) {
// Omitted code ...
// Implementation of memory cache
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
// Factory implementation of disk cache
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
// Omitted code ...
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
experiments);
}
/* memeory cache The implementation of LruResourceCache, After creation, they will be passed in as parameters Engine and Glide object . disk cache factory The implementation of InternalCacheDiskCacheFactory, After creation, it is only passed in as a parameter Engine object . The default disk cache finally created by the factory is DiskLruCacheWrapper. */
Principle of memory and disk cache
from LruResourceCache and DiskLruCacheWrapper In terms of implementation , Its cache principle adopts LRU Algorithm , Combined with the specific point of source code implementation ,
First, let's look at the principle of memory caching ,
public class LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache {
//MemoryCache Defines the behavior of memory caching , What specific behaviors ?
/* 1. Cache operations :put(Key key, Resource<?> resource) 2. Delete operation :remove(Key key) 3. Emptying operation :clearMemory() */
//LruCache<K, V> yes LRU Implementation class of , Through internal LinkedHashMap Realize the maintenance of cached data ,
// This class has implemented put, get, remove, clear Wait for the operation , As subclasses ,
// To achieve getSize(Y item) Method to specify the size of a single cached data .LruCache The method implementation of this class is the key .
// As LruResourceCache In itself , There is not much left to do .
}
Let's look at the principle of disk caching ,
public class DiskLruCacheWrapper implements DiskCache {
//DiskCache Defines the behavior of disk caching , Same as MemeoryCache similar , It also defines some operation methods
/* 1. Cache operations :put(Key key, Writer writer) 2. Delete operation :delete(Key key) 3. Emptying operation :clear() 4. The retrieval :get(Key key), This step is in MemoryCache There is no definition in , But in LruCache Is defined and implemented . In addition to the above behavior operations , This interface also defines two interfaces , One is the factory interface for creating disk cache , One is used to cache read and write operations Writer. */
// Same as LruCache similar , This is a disk cache LRU Implementation class .
private DiskLruCache diskLruCache;
private synchronized DiskLruCache getDiskCache() throws IOException {
if (diskLruCache == null) {
//diskLruCache Object passing open Method creation
diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
}
return diskLruCache;
}
}
DiskLruCache It will be better than memory cache LruCache More complicated , Performance in :1. Involving thread pool operation ,2. It involves file reading and writing . But although there are differences , emphasis ( use LinkedHashMap Implement cache collection ) It's the same .
Specific implementation of cache algorithm
Based on the analysis of Glide Before the cache algorithm is implemented , Let's have a brief understanding of LRU Algorithm .
LRU(Least Recently Used) This algorithm is a page replacement algorithm , Add a field for each page to record the usage time , When the storage space is full , Use the time field according to the comparison , Delete the least recently used pages , To store new pages .
In principle :1. Storage space is limited , That is to say, there is an initial value of storage space .2. Need a data structure to meet the content replacement , That is to find the least recently used elements .
LruCache Of put Method implementation analysis ,
public class LruCache<T, Y> {
private final Map<T, Entry<Y>> cache = new LinkedHashMap<>(100, 0.75f, true);
public LruCache(long size) {
// What the constructor does is to initialize the number of storage space elements ( That is, how many pages can be put in total , If it is full, it will be replaced )
// Be careful !!! This size Is the total size of storage space , The unit is and getSize It's consistent
/* Glide use MemorySizeCalculator Of memoryCacheSize Field to which it is assigned , Calculation of this value It will vary according to the screen size of the device . The unit is byte */
this.initialMaxSize = size;
this.maxSize = size;
}
@Nullable
public synchronized Y put(@NonNull T key, @Nullable Y item) {
// adopt getSize Method to get item The space size of the element , With byte In units of
final int itemSize = getSize(item);
if (itemSize >= maxSize) {
// The implementation of this is handed over to subclasses
onItemEvicted(key, item);
return null;
}
if (item != null) {
currentSize += itemSize;
}
// utilize LinkedHashMap Type of cache Deposit in item value
// Judge according to the return value cache Is there any old element in the that needs to be removed
@Nullable Entry<Y> old = cache.put(key,
item == null ? null : new Entry<>(item, itemSize));
if (old != null) {
currentSize -= old.size;
if (!old.value.equals(item)) {
onItemEvicted(key, old.value);
}
}
// Check whether there is enough space , If not enough, replace the element space
evict();
return old != null ? old.value : null;
}
private void evict() {
trimToSize(maxSize);
}
protected synchronized void trimToSize(long size) {
Map.Entry<T, Entry<Y>> last;
Iterator<Map.Entry<T, Entry<Y>>> cacheIterator;
while (currentSize > size) {
cacheIterator = cache.entrySet().iterator();
// I got it directly here cache The first element in ,
// the reason being that LinkedHashMap, In this way, the least used recently is the first
// Cycle release , Until there is enough space
last = cacheIterator.next();
final Entry<Y> toRemove = last.getValue();
currentSize -= toRemove.size;
final T key = last.getKey();
cacheIterator.remove();
onItemEvicted(key, toRemove.value);
}
}
// Static classes used to wrap storage elements , Contains specific elements and their space size
static final class Entry<Y> {
final Y value;
final int size;
@Synthetic
Entry(Y value, int size) {
this.value = value;
this.size = size;
}
}
}
DiskLruCache Of put Method implementation analysis ,
public final class DiskLruCache implements Closeable {
// Through InternalCacheDiskCacheFactory Default size specified when creating 250MB
private long maxSize;
private final LinkedHashMap<String, Entry> lruEntries =
new LinkedHashMap<String, Entry>(0, 0.75f, true);
public final class Editor {
private final Entry entry;
private final boolean[] written;
private boolean committed;
public File getFile(int index) throws IOException {
synchronized (DiskLruCache.this) {
if (entry.currentEditor != this) {
throw new IllegalStateException();
}
if (!entry.readable) {
written[index] = true;
}
File dirtyFile = entry.getDirtyFile(index);
directory.mkdirs();
return dirtyFile;
}
}
}
}
// On disk cache processing , Behavior operation is through DiskLruCacheWrapper Object operation , Take a look DiskLruCacheWrapper class
//DiskLruCacheWrapper
public class DiskLruCacheWrapper implements DiskCache {
private DiskLruCache diskLruCache;
@Override
public void put(Key key, Writer writer) {
//SafeKeyGenerator Make sure you can get one safeKey
String safeKey = safeKeyGenerator.getSafeKey(key);
try {
try {
DiskLruCache diskCache = getDiskCache();
// adopt diskCache obtain safeKey Corresponding value
Value current = diskCache.get(safeKey);
if (current != null) {
return;
}
// obtain safeKey Corresponding editor
DiskLruCache.Editor editor = diskCache.edit(safeKey);
try {
File file = editor.getFile(0);
// adopt Writer Write file data to file in
if (writer.write(file)) {
// If the write is successful , Is executed commit
editor.commit();
}
}
}
}
}
DiskLruCache Than LruCache The implementation of will be more complicated , For the time being, let's have a brief understanding , Further analysis will be carried out later .
边栏推荐
- Accounting regulations and professional ethics [7]
- ~89 deformation translation
- ECCV 2022放榜了:1629篇论文中选,录用率不到20%
- 智慧物流園區供應鏈管理系統解决方案:數智化供應鏈賦能物流運輸行業供應鏈新模式
- Start by counting
- [Acwing] 58周赛 4489. 最长子序列
- [North Asia data recovery] a database data recovery case where the disk on which the database is located is unrecognized due to the RAID disk failure of HP DL380 server
- Research Report on market supply and demand and strategy of tetramethylpyrazine industry in China
- [North Asia data recovery] a database data recovery case where the partition where the database is located is unrecognized due to the RAID disk failure of HP DL380 server
- Object.keys()的用法
猜你喜欢
Go development: how to use go singleton mode to ensure the security of high concurrency of streaming media?
照明行业S2B2B解决方案:高效赋能产业供应链,提升企业经济效益
Understand ThreadLocal in one picture
Capvision Rongying's prospectus in Hong Kong was "invalid": it was strictly questioned by the CSRC and required supplementary disclosure
What is torch NN?
[North Asia data recovery] a database data recovery case where the disk on which the database is located is unrecognized due to the RAID disk failure of HP DL380 server
MFC implementation of ACM basic questions encoded by the number of characters
新的职业已经出现,怎么能够停滞不前 ,人社部公布建筑新职业
Understand Alibaba cloud's secret weapon "dragon architecture" in the article "science popularization talent"
矿产行业商业供应链协同系统解决方案:构建数智化供应链平台,保障矿产资源安全供应
随机推荐
FIREBIRD使用经验总结
China's roof ladder market trend report, technological innovation and market forecast
[Acwing] 58周赛 4489. 最长子序列
"Cannot initialize Photoshop because the temporary storage disk is full" graphic solution
表单传递时,如何隐式将值传过去
egg. JS learning notes
Understand ThreadLocal in one picture
How to contribute to the source code of ongdb core project
Years of training, towards Kata 3.0! Enter the safe container experience out of the box | dragon lizard Technology
智慧物流園區供應鏈管理系統解决方案:數智化供應鏈賦能物流運輸行業供應鏈新模式
Daily notes~
Li Kou today's question -1200 Minimum absolute difference
Vscode setting outline shortcut keys to improve efficiency
Integration of ongdb graph database and spark
Research Report on market supply and demand and strategy of China's well completion equipment industry
go-micro教程 — 第二章 go-micro v3 使用Gin、Etcd
C implementation defines a set of intermediate SQL statements that can be executed across libraries
APOC自定义函数和过程
Lv166 turned over
Statistical learning: logistic regression and cross entropy loss (pytoch Implementation)