什麼是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互斥鎖進行執行緒安全保護。