actionscript-3 - 缓存具有多个参数的方法结果的最佳方法 - 对象作为字典中的键?

标签 actionscript-3 caching optimization

在方法的开头,我想检查之前是否使用这些确切的参数调用了该方法,如果是,则返回当时返回的结果。

起初,使用一个参数,我使用了一个字典,但现在我需要检查 3 个参数(一个字符串、一个对象和一个 bool 值)。

我尝试制作一个自定义对象,如下所示:

var cacheKey:Object = { identifier:identifier, type:type, someBoolean:someBoolean };

//if key already exists, return it (not working)
if (resultCache[cacheKey]) return resultCache[cacheKey];

//else: create result ...

//and save it in the cache
resultCache[cacheKey] = result;

但这不起作用,因为第二次调用该函数时,新的 cacheKey 是 不一样 对象作为第一个,即使它的属性是相同的。

所以我的问题是:是否有一种数据类型可以检查用作匹配键的键的对象的属性?

还有什么是我最好的选择?也为 key 创建缓存? :/

最佳答案

注意技术方案有两个方面:相等比较索引 .

悬崖笔记版本:

  • 做定制很容易相等比较
  • 为了执行索引 ,你需要知道的不仅仅是一个对象是否等于另一个——你需要知道哪个对象比另一个“大”。
  • 如果您的所有属性都是基元,您应该将它们压缩成一个字符串并使用 Object跟踪它们(不是 Dictionary )。
  • 如果您需要比较某些单个属性的引用相等性,您将编写一个函数来确定哪一组属性比另一组大,然后创建自己的使用比较函数输出的集合类实现自己的基于二叉搜索树的索引。
  • 如果唯一参数集的数量在数百或更少,并且您确实需要引用比较您的 Object参数,只需使用一个数组和 some方法对所有缓存的键进行简单的比较。只有您知道实际方法的成本有多高,因此由您决定可接受的查找成本(取决于提供给函数的唯一参数的数量)。

  • 平等比较

    地址 相等比较编写一些代码来比较对象的属性值是很容易的,而不是为了引用相等性。以下函数强制执行严格的集合比较,因此两个对象必须包含具有相同值的完全相同的属性(不允许任何一个对象上的附加属性):
    public static propsEqual(obj1:Object, obj2:Object):Boolean {
        for(key1:* in obj1) {
            if(obj2[key1] === undefined)
                return false;
            if(obj2[key1] != obj2[key1])
                return false;
        }
        for(key2:* in obj2) 
            if(obj1[key2] === undefined)
                return false;
        return true;
    }
    

    您可以通过消除第二个 for 循环来加快速度,但要权衡 {A:1, B:2}将被视为等于 {A:1, B:2, C:'An extra property'} .

    索引

    在您的情况下,问题在于您丢失了 索引那一个 Dictionary提供引用相等或 Object提供字符串键。您必须将每组新的函数参数与之前看到的参数的整个列表进行比较,例如使用 Array.some .我用的领域currentArgs以及避免每次生成新闭包的方法。
    private var cachedArgs:Array = [];
    private var currentArgs:Object;
    
    function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
        currentArgs = { stringArg:stringArg, objArg:objArg, boolArg:boolArg };
        var iveSeenThisBefore:Boolean = cachedArgs.some(compareToCurrent);
        if(!iveSeenThisBefore)
            cachedArgs.push(currentArgs);
    }
    
    function compareToCurrent(obj:Object):Boolean {
        return someUtil.propsEqual(obj, currentArgs);
    }
    

    这意味着比较将是 O(n) 时间,其中 n 是不断增加的唯一函数参数集的数量。

    如果您的函数的所有参数都是原始参数,请参阅非常相似的问题 In AS3, where do you draw the line between Dictionary and ArrayCollection? .标题听起来不太相似,但已接受的答案中的解决方案(是的,我写的)解决了完全相同的技术问题——使用多个原始值作为单个复合键。您的情况的基本要点是:
    private var cachedArgs:Object = {};
    
    function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
        var argKey:String = stringArg + objArg.toString() + (boolArg ? 'T' : 'F');
        if(cachedArgs[argKey] === undefined)
            cachedArgs[argKey] = _yourMethod(stringArg, objArg, boolArg);
        return cachedArgs[argKey];
    }
    
    private function _yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
        // Do stuff 
        return something;
    }
    

    如果您真的需要确定哪个引用比另一个“大”(如 Dictionary 在内部所做的那样),您将不得不涉足一些丑陋的东西,因为 Adob​​e 尚未提供任何 API 来检索“值”/引用的“地址”。到目前为止我发现的最好的事情是这个有趣的黑客:How can I get an instance's "memory location" in ActionScript? .不做一堆性能测试,我不知道使用这个 hack 来比较引用是否会扼杀二叉搜索树 indexnig 获得的优势。当然,这将取决于 key 的数量。

    关于actionscript-3 - 缓存具有多个参数的方法结果的最佳方法 - 对象作为字典中的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14156102/

    相关文章:

    php - 使用可变项创建一个两次通过的 PHP 缓存系统

    python - 如何从 Python 中的点列表创建一个以椭圆体为中心的二进制 3 维矩阵?

    Android循环字节码比较

    xml - atom feed xmlns 属性搞乱了 AS3 的 XML 解析?

    actionscript-3 - 赛车游戏中的AI对手汽车逻辑

    apache-flex - ActionScript-3 : Array vs. ArrayList

    java - 计算十六进制颜色相反的公式 ("Difference")

    python - 如何使用 Flask/SQLAlchemy 将返回结果的数量限制为仅 1000 个最新条目?

    spring-boot - Spring Boot native 缓存 : How to expire/remove cache data by individual keys/elements

    python - 为什么我的 python 进程占用了这么多内存?