欢迎!有关此网站的更多信息,请参阅关于页面。
评论者:[email protected]
我认为最明显的解决方案是对缓存的尺寸进行限制。向缓存添加项不是最快的路径,因此可以进一步提高防止缓存无限增长的工作。
这确实引发了一个问题:我们应该使用什么标准。保留前n个条目?保留最近n次使用的(这需要在快速缓存命中路径中进行记录)?还是保留最近添加的n个?
评论者:jsmorph
至少,也许可以通过禁用缓存来切换(请注意明显的性能影响)。
看起来昂贵的LRU逻辑可能是最佳选择,但也许不要在达到某个阈值之前完全启用它。
评论者:alexmiller
从邮件列表中看到的生产报告 https://groups.google.com/forum/#!topic/clojure/_n3HipchjCc
评论者:adrianm
这就是我们遇到PermGen空间异常的原因!这是我们相当关键的错误——我们在代码库中广泛使用多方法,这个异常将在运行时随机出现。
评论者:hiredman
也许最好把这个问题分为两个,因为从非常抽象的角度来看,这两个问题是“相同的”,但具体来说是不同的(协议实际上并没有与多方法共享代码路径),把它们保留在一个问题中似乎是一个大型的、难以阅读的补丁的配方
naive-lru-method-cache-for-multimethods.diff用非常简单的基于PersistentHashMap和PersistentQueue构建的LRU缓存替换了多方法中的methodCache。
文件“naive-lru-for-multimethods-and-protocols.diff”创建了一个新的类 clojure.lang.LRUCache,该类提供了一个使用 PHashMap 和 PQueue 在 IPMap 接口后面构建的 lru 缓存。
将 MultiFn 修改为使用 LRUCache 进行方法缓存。
将 expand-method-impl-cache 修改为使用 LRUCache 进行 MethodImplCache 的 map 用例。
我认为我的补丁 naive-lru-for-multimethods-and-protocols.diff 是错误的,除非 MethodImplCache 真正被用作缓存,否则我们不能在它满了之后乱扔条目。
再次查看 deftype 代码,MethidImplCache 似乎确实被用作缓存,所以这个补丁可能没问题。
如果我对任何事情有信心,那就是我不确定,所以希望有人能站出来。
评论者:bronsa
我没有看过你的补丁,但我可以确认,在协议函数中的 MethodImplCache 只被用作缓存。
评论者:killme2008
我开发了一个新的补丁,将 MultiFn 中的 methodCache 转换为使用 WeakReference 作为调度值,并在必要时清理缓存。
我用票据中的代码测试了它,看起来很好。当 perm gen 几乎用完时,类将被卸载。
我不知道这里该如何评价。multifn_weak_method_cache.diff 是取代 naive-lru-for-multimethods-and-protocols.diff,还是这两个替代方案都在考虑中?
我认为最直接的方法是将它们视为替代品,我不是弱引用的忠实粉丝,但当然,如果不使用弱引用,我们不得不为缓存选择一些边界大小,而缓存有一个强引用,这可能会阻止gc,因此存在折衷。我避开弱引用的一般原因是使用它们会将你正在构建的内容的行怍与gc的行为紧紧联系在一起。这可能是个人喜好的问题。
评论者:jafingerhut
在2014年8月29日对Clojure进行了一些提交后,所有日期为2014年8月8日及以前的补丁不再干净地应用到最新的master分支上。在那一天之前,它们是可以干净地应用的。
我没有检查更新补丁的难易程度。
我已经更新了naive-lru-for-multimethods-and-protocols.diff,使其适用于当前master。
谢谢,Kevin。虽然JIRA允许为具有相同文件名但内容不同的票据添加多个附件,但这可能会让寻找特定补丁的人感到困惑,并且对于我有一个用来评估补丁是否可以从源代码干净构建的程序来说,这也是一个问题。你介意移除旧的补丁,或者以某种方式让所有文件名都是独一无二的吗?