日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

YYCache 源码学习(二):YYDiskCache

發(fā)布時(shí)間:2024/4/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YYCache 源码学习(二):YYDiskCache 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
整體思路

從作者的《YYCache 設(shè)計(jì)思路》一文中可以看出,作者在設(shè)計(jì)YYDiskCache之前做了充分的測(cè)試:iPhone 6 64G 下,SQLite 寫入性能比直接寫文件要高,但讀取性能取決于數(shù)據(jù)大小:當(dāng)單條數(shù)據(jù)小于 20K 時(shí),數(shù)據(jù)越小 SQLite 讀取性能越高;單條數(shù)據(jù)大于 20K 時(shí),直接寫為文件速度會(huì)更快一些。

YYDiskCache的磁盤緩存結(jié)合使用了文件儲(chǔ)存和數(shù)據(jù)庫(kù)儲(chǔ)存。

個(gè)人理解:在進(jìn)行磁盤緩存的時(shí)候,會(huì)判斷要儲(chǔ)存數(shù)據(jù)的大小,如果數(shù)據(jù)小于20K,則直接存入數(shù)據(jù)庫(kù)(數(shù)據(jù)儲(chǔ)存到inline_data字段,此時(shí)filename為空)。如果數(shù)據(jù)大于20K,先把數(shù)據(jù)以文件形式進(jìn)行存儲(chǔ),然后再在數(shù)據(jù)庫(kù)中儲(chǔ)存對(duì)應(yīng)的文件名(此時(shí)inline_data為NULL,filename為文件地址),具體的可以結(jié)合下文中提到的磁盤緩存的文件結(jié)構(gòu)來(lái)看。

磁盤緩存的核心類是YYKVStorage,他主要封裝了文件儲(chǔ)存操作和SQLite數(shù)據(jù)庫(kù)的操作。YYDiskCache是對(duì)YYKVStorage的封裝,拋出的API和內(nèi)存緩存相似,都有數(shù)據(jù)讀寫和修剪內(nèi)存。

磁盤緩存的文件結(jié)構(gòu)
/*File:/path//manifest.sqlite/manifest.sqlite-shm/manifest.sqlite-wal/data//e10adc3949ba59abbe56e057f20f883e/e10adc3949ba59abbe56e057f20f883e/trash//unused_file_or_folderSQL:create table if not exists manifest (key text,filename text,size integer,inline_data blob,modification_time integer,last_access_time integer,extended_data blob,primary key(key)); create index if not exists last_access_time_idx on manifest(last_access_time);*/

這個(gè)結(jié)構(gòu)我們不需要多說(shuō)什么,只提一個(gè)小點(diǎn),作者在path路徑下面設(shè)計(jì)了一個(gè)/data/和一個(gè)/trash/。刪除文件是一個(gè)比較耗時(shí)的操作,在刪除文件的時(shí)候,先進(jìn)行文件的移動(dòng),然后在一個(gè)子線程中處理要?jiǎng)h掉的文件,提高了整體的效率。

實(shí)現(xiàn) LRU

磁盤緩存對(duì)緩存淘汰算法的實(shí)現(xiàn)就比較簡(jiǎn)單了,因?yàn)槊看未鎯?chǔ)都有對(duì)應(yīng)的數(shù)據(jù)庫(kù)記錄,而且表中設(shè)計(jì)了last_access_time這個(gè)字段,我們可以直接使用數(shù)據(jù)庫(kù)的排序語(yǔ)句就可以找到最不常用的文件了。

代碼分析

1.

- (sqlite3_stmt *)_dbPrepareStmt:(NSString *)sql {if (![self _dbCheck] || sql.length == 0 || !_dbStmtCache) return NULL;sqlite3_stmt *stmt = (sqlite3_stmt *)CFDictionaryGetValue(_dbStmtCache, (__bridge const void *)(sql));if (!stmt) {int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL);if (result != SQLITE_OK) {if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db));return NULL;}CFDictionarySetValue(_dbStmtCache, (__bridge const void *)(sql), stmt);} else {sqlite3_reset(stmt);}return stmt; }

這個(gè)方法是提前生成了sql語(yǔ)句的句柄,可以理解成提前把sql語(yǔ)句編譯成字節(jié)碼留給后面的執(zhí)行函數(shù)(當(dāng)前不執(zhí)行)。同時(shí),作者使用
_dbStmtCache對(duì)語(yǔ)句進(jìn)行緩存,下次使用時(shí)可以更快度的加載出來(lái)。

2.

- (BOOL)_dbClose {if (!_db) return YES;int result = 0;BOOL retry = NO;BOOL stmtFinalized = NO;if (_dbStmtCache) CFRelease(_dbStmtCache);_dbStmtCache = NULL;do {retry = NO;result = sqlite3_close(_db);// 狀態(tài)為busy或者lockif (result == SQLITE_BUSY || result == SQLITE_LOCKED) {if (!stmtFinalized) {stmtFinalized = YES;sqlite3_stmt *stmt;//sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);//表示從數(shù)據(jù)庫(kù)pDb中對(duì)應(yīng)的pStmt語(yǔ)句開始一個(gè)個(gè)往下找出相應(yīng)prepared語(yǔ)句,如果pStmt為nil,那么就從pDb的第一個(gè)prepared語(yǔ)句開始。while ((stmt = sqlite3_next_stmt(_db, nil)) != 0) {//釋放數(shù)據(jù)庫(kù)中的prepared語(yǔ)句資源sqlite3_finalize(stmt);retry = YES;}}} else if (result != SQLITE_OK) {if (_errorLogsEnabled) {NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result);}}} while (retry);_db = NULL;return YES; }

這個(gè)是關(guān)閉數(shù)據(jù)庫(kù)的方法,_dbStmtCache中緩存了我們使用的句柄,所以首先要釋放掉了_dbStmtCache。

在真正關(guān)閉數(shù)據(jù)庫(kù)的代碼中使用了do-while循環(huán),因?yàn)橐淮卧L問數(shù)據(jù)庫(kù)并不一定成功,數(shù)據(jù)庫(kù)可能是busy或者lock的狀態(tài),所以要使用一個(gè)循環(huán)來(lái)多次訪問。

如果為能關(guān)閉數(shù)據(jù)庫(kù),作者使用了sqlite3_next_stmt一個(gè)個(gè)的找出prepared語(yǔ)句,并使用sqlite3_finalize釋放了prepared資源(防止內(nèi)存泄露)。

其他的就沒什么好說(shuō)的了,主要就是一些sql語(yǔ)句的用法,這些大家看一下,碰到陌生的api谷歌一下就有了 ~ 具體的文件的操作,比較常用,看起來(lái)就容易很多。

總結(jié)

以上是生活随笔為你收集整理的YYCache 源码学习(二):YYDiskCache的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。