NSCache快取怎麼來的

翾燚發表於2019-06-29

什麼是NSCache

NSCache主要用來儲存臨時資料(鍵值對),當記憶體資源不夠時,系統會自動釋放部分資料。它有三個特點:
• NSCache為了保持不佔用過多的系統記憶體,它有多種自動回收記憶體策略;當系統記憶體出現不足時,它會回收部分記憶體使系統正常運轉,這種回收是不可控的。
• 可以在多執行緒中對NSCache進行訪問,同時不需要加鎖,因為它是執行緒安全的。
• 與NSMutableDictionary不同,NSCache不會copy其內部的鍵物件。

由上邊的特點看出,NSCache是一個很好的記憶體快取類,通過它我們可以實現資料的快取功能。常見的開源框架中也有NSCache的使用,AFN的圖片快取,SDWebImage等。


NSCache測試

下面驗證NSCache的特性,包含三個部分。NSCache的快取能力有多大?多執行緒訪問下是否安全?是否會copy其內部物件?

1. 快取能力
NSCache提供了totalCostLimit和countLimit屬性讓外界能夠對其進行快取大小和快取數量進行限制,但是不精確。網上其他的帖子說到大約NSCache的快取能力是500M,現在我們對其驗證。

    NSCache *cache = [[NSCache alloc] init];
    
    int a = 0;
    while (YES) {
        NSString *string = @"一長串字串"; // 大約1000個左右字元
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
        NSString *key = [NSString stringWithFormat:@"%d", a];
        [cache setObject:data forKey:key];
        a++;
    }

通過上述的程式碼執行在iPhone6上,記憶體升到600M多點直接崩潰,那麼極限是500多應該是正確的。同時在快速達到記憶體極限時,系統是來不及釋放回收的,使用時應當注意,而且上邊的程式碼是死迴圈,速度非常快。

2. 多執行緒訪問

多執行緒訪問單獨讀取是不會造成問題的,除非訪問執行緒數過多,這裡我們模擬多執行緒同時寫入的情況。

    NSCache *cache = [[NSCache alloc] init];
    NSString *string = @"一長串字串"; // 大約1000個左右字元
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [cache setObject:[NSString stringWithFormat:@"%d%@",i,string] forKey:@"MulPth"];
            NSLog(@"object is %@", [cache objectForKey:@"MulPth"]);
        });
    }

string若設定為特別短的字串,效果可能不是很明顯,所以將快取能力中的字串拷貝過來測試,從列印結果看,時間戳有明顯差異,同時順序也不是0123456789,而其餘的內容一致,可以得出是執行緒安全的。
本質上,NSCache在其內部使用了pthread_mutex互斥鎖進行執行緒安全保護。

相關文章