• Ios Lru 实例对比-YYCache 与 afn 的对比


    YYCache 的结构

    @interface _YYLinkedMapNode : NSObject {
        @package
        __unsafe_unretained _YYLinkedMapNode *_prev; // retained by dic
        __unsafe_unretained _YYLinkedMapNode *_next; // retained by dic
        id _key;
        id _value;
        NSUInteger _cost;
        NSTimeInterval _time;
    }
    @end
    @implementation _YYLinkedMapNode
    @end
    /**
     A linked map used by YYMemoryCache.
     It's not thread-safe and does not validate the parameters.
     Typically, you should not use this class directly.
     */
    @interface _YYLinkedMap : NSObject {
        @package
        CFMutableDictionaryRef _dic; // do not set object directly
        NSUInteger _totalCost;
        NSUInteger _totalCount;
        _YYLinkedMapNode *_head; // MRU, do not change it directly
        _YYLinkedMapNode *_tail; // LRU, do not change it directly
        BOOL _releaseOnMainThread;
        BOOL _releaseAsynchronously;
    }
    
    /// Insert a node at head and update the total cost.
    /// Node and node.key should not be nil.
    - (void)insertNodeAtHead:(_YYLinkedMapNode *)node;
    
    /// Bring a inner node to header.
    /// Node should already inside the dic.
    - (void)bringNodeToHead:(_YYLinkedMapNode *)node;
    
    /// Remove a inner node and update the total cost.
    /// Node should already inside the dic.
    - (void)removeNode:(_YYLinkedMapNode *)node;
    
    /// Remove tail node if exist.
    - (_YYLinkedMapNode *)removeTailNode;
    
    /// Remove all node in background queue.
    - (void)removeAll;
    _YYLinkedMapNode *_prev为该节点的头指针,指向前一个节点
    _YYLinkedMapNode *_next为该节点的尾指针,指向下一个节点
    头指针和尾指针将一个个子节点串连起来,形成双向链表

    核心实现方法:
    - (void)bringNodeToHead:(_YYLinkedMapNode *)node {
        if (_head == node) return; // 如果当前节点是链头,则不需要移动
        
        // 链表中存了两个指向链头(_head)和链尾(_tail)的指针,便于链表访问
        if (_tail == node) {
            _tail = node->_prev; // 若当前节点为链尾,则更新链尾指针
            _tail->_next = nil; // 链尾的尾节点这里设置为nil
        } else {
            // 比如:A B C 链表, 将 B拿走,将A C重新联系起来
            node->_next->_prev = node->_prev; // 将node的下一个节点的头指针指向node的上一个节点,
            node->_prev->_next = node->_next; // 将node的上一个节点的尾指针指向node的下一个节点
        }
        node->_next = _head; // 将当前node节点的尾指针指向之前的链头,因为此时node为最新的第一个节点
        node->_prev = nil; // 链头的头节点这里设置为nil
        _head->_prev = node; // 之前的_head将为第二个节点
        _head = node; // 当前node成为新的_head
    }
    总结:yyCache 是使用了NSdictory + 双向链表来保证数据的最新
    AFN
    结构
    //单个图片存储的数据结构

    @interface AFCachedImage : NSObject

    @property (nonatomic, strong) UIImage *image;

    @property (nonatomic, strong) NSString *identifier;

    @property (nonatomic, assign) UInt64 totalBytes;

    @property (nonatomic, strong) NSDate *lastAccessDate;

    @property (nonatomic, assign) UInt64 currentMemoryUsage;

    @end

    //每次获取图片 都会更新时间戳

    - (UIImage*)accessImage {

        self.lastAccessDate = [NSDate date];

        return self.image;

    }

    //存储的缓存池---缓存的数据 + 当前缓存的内存容量

    @interface AFAutoPurgingImageCache ()

    @property (nonatomic, strong) NSMutableDictionary <NSString* , AFCachedImage*> *cachedImages;

    @property (nonatomic, assign) UInt64 currentMemoryUsage;

    @property (nonatomic, strong) dispatch_queue_t synchronizationQueue;

    @end

    核心实现

    如果当前存储的缓存超过设置的阖值就会触发

      if (self.currentMemoryUsage > self.memoryCapacity) {

                UInt64 bytesToPurge = self.currentMemoryUsage - self.preferredMemoryUsageAfterPurge;

                NSMutableArray <AFCachedImage*> *sortedImages = [NSMutableArray arrayWithArray:self.cachedImages.allValues];

                NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastAccessDate"

                                                                               ascending:YES];

                [sortedImages sortUsingDescriptors:@[sortDescriptor]];

                UInt64 bytesPurged = 0;

                for (AFCachedImage *cachedImage in sortedImages) {

                    [self.cachedImages removeObjectForKey:cachedImage.identifier];

                    bytesPurged += cachedImage.totalBytes;

                    if (bytesPurged >= bytesToPurge) {

                        break ;

                    }

                }

                self.currentMemoryUsage -= bytesPurged;

            }

    总结:

    AFN的实现其实就是把缓存对象存储成一个个模型,然后统一在缓存池中根据时间戳排序处理





  • 相关阅读:
    057.Python前端Django模型ORM多表查询
    056.Python前端Django模型ORM多表基本操作
    055.Python前端Django模型ORM
    054.Python之Ubuntu安装Pycharm
    053.Python前端Django框架模板层
    052.Python前端Django框架路由层和视图层
    基数排序
    链表k个节点反向
    链表排序
    函数返回局部指针变量是否可行?
  • 原文地址:https://www.cnblogs.com/pp-pping/p/12401611.html
Copyright © 2020-2023  润新知