Webkit的MemoryCache和DiskCache流程詳解
MemoryCache簡介:
MemoryCache顧名思義,就是将資源緩存到記憶體中,等待下次通路時不需要重新下載下傳資源,而直接從記憶體中擷取。Webkit早已支援memoryCache。
目前Webkit資源分成兩類,一類是主資源,比如HTML頁面,或者下載下傳項,一類是派生資源,比如HTML頁面中内嵌的圖檔或者腳本連結,分别對應代碼中兩個類:MainResourceLoader和SubresourceLoader。雖然Webkit支援memoryCache,但是也隻是針對派生資源,它對應的類為CachedResource,用于儲存原始資料(比如CSS,JS等),以及解碼過的圖檔資料。
MemoryCache流程分析:(注:以image為例,其他資源流程類似)
下面以image為例分析其加載過程
1. 解析html頁面的時候,解析到img标簽,調用
HTMLImageElement::create建立HTMLImageElement對象,該對象包含HTMLImageLoader對象m_imageLoader
2. 解析到img的src屬性,調用ImageLoader::updateFromElementIgnoringPreviousError
3. 調用ImageLoader::updateFromElement
4. 調用CachedResourceLoader::requestImage
5. 調用CachedResourceLoader::requestResource,根據緩存的情況policy字段确定是否可以從緩存擷取(use),或者需要revalidate,或者需要直接從網絡擷取(load)
6. 調用CachedResourceLoader::loadResource
7. 根據Resource的類型調用createResource建立對應的CachedResource
8. 調用MemoryCache::add在cache中查找是否有對應的cache條目,如果沒有建立之
9. 調用CachedImage::load
10.調用CachedResource::load
11.調用CachedResourceLoader::load
12.調用CachedResourceRequest::load
13.建立CachedResourceRequest 對象,它将作為SubresourceLoader的client
14.調用ResourceLoaderScheduler::scheduleSubresourceLoad
15.調用SubresourceLoader::create
16.調用ResourceLoadScheduler::requestTimerFired
17.調用ResourceLoader::start
18.調用ResourceHandle::create 發起請求
19.收到HTTP響應頭部,調用ResourceLoader::didReceiveResponse
20.調用SubresourceLoader::didReceiveResponse處理響應頭部,特别是同緩存相關的頭部,比如304的status code。如果是304則直接向緩存擷取,如果是200則通過網絡加載
21.調用ResourceLoader::didReceiveResponse
22.收到體部資料,調用ResourceLoader::didReceiveData
23.調用SubresourceLoader::didReceiveData
24.調用ResourceLoader::didReceiveData
25.調用ResourceLoader::addData将資料存儲到SharedBuffer裡面
26.調用CachedResourceRequest::didReceiveData
27.資料擷取完畢,調用ResourceLoader::didFinishLoading
28.調用SubresourceLoader::didFinishLoading
29.調用CachedResourceRequest::didFinishLoading
30.調用CachedResource::finish
31.調用CachedResourceLoader::loadDone
32.調用CachedImage::data,建立對應的Image對象,解碼
MemoryCache時序圖:
加入memoryCache:
從memoryCache擷取:
DiskCache簡介:
diskCache顧名思義,就是将資源緩存到磁盤中,等待下次通路時不需要重新下載下傳資源,而直接從磁盤中擷取,它的直接操作對象為CurlCacheManager。它與memoryCache最大的差別在于,當退出程序時,記憶體中的資料會被清空,而磁盤的資料不會,是以,當下次再進入該程序時,該程序仍可以從diskCache中獲得資料,而memoryCache則不行。
diskCache與memoryCache相似之處就是也隻能存儲一些派生類資源檔案。它的存儲形式為一個index.dat檔案,記錄存儲資料的url,然後再分别存儲該url的response資訊和content内容。Response資訊最大作用就是用于判斷伺服器上該url的content内容是否被修改。具體詳見:
http://baike.baidu.com/link?url=n5nx7f8fGB_-B3OieAvMvJIGeBNvipb9qGQhYO0YwwBLg6oxqv_05Up3JUJk4jZyAd-KiCM1Hmg4nR23B5BhSq
DiskCache流程分析:
1. webkit已啟動,就會建立CurlCacheManager對象
2. CurlCacheManager構造函數會調用CurlCacheManager::setCacheDirectory
3. 調用fileExists判斷檔案夾是否存在,如果存在繼續,否則調用makeAllDirectories建立檔案夾
4. 調用CurlCacheManager::loadIndex(),如果本地有緩存檔案,它就會從磁盤讀取出來,并将資料儲存在m_index這個變量中,該變量類型為HashMap<String,std::unique_ptr<CurlCacheEntry>> ,分别對應url和資料内容。
5. 調用headerCallback函數,傳回codestatus為304未修改,就會去調用CurlCacheManager::getCachedResponse(),如果是200,就會下載下傳資料,并将資料的url儲存在一個m_LRUEntryList中
6. 調用CurlCacheManager::readCachedData()
7. 調用CurlCacheEntry::readCachedData()
8. 調用CurlCacheEntry::loadFileToBuffer()将檔案中的内容讀取出來儲存在一個buffer中
9. 調用ResourceLoader::didReceiveData()将資料擷取,此時資料沒有通過網絡下載下傳,直接從本地擷取
10.Webkit退出時,調用CurlCacheManager::~CurlCacheManager()
11.調用CurlCacheManager::saveIndex(),該函數會去将m_LRUEntryList中的url擷取并寫入index.dat檔案中
MemoryCache時序圖: