瞬态加速读取操作吗?

时间:2017-01-29 09:13:57

标签: optimization clojure

在我的应用程序中,我有一个巨大的不可变状态嵌套映射,我经常使用get-in等操作查询。

每当对此类结构执行大量读取操作时,将其转换为瞬态会获得任何好处吗?或者瞬态只加速更新操作?

3 个答案:

答案 0 :(得分:3)

瞬态旨在通过批量更新来加速写入。他们的目的不是优化读取,如果这是你的目标,我就不会使用它们(使用更有效的数据结构进行查找可能是一个更好的答案)。

瞬态数据结构的

读取可能更慢或更快,因为它们需要同时检查数据结构和进程内批处理。如果该值恰好位于刚刚添加的批处理中,则读取可能更快。如果它们恰好位于更大的数据结构中,它们可能会更慢。

答案 1 :(得分:1)

对于内置的瞬态启用的Clojure数据结构(以及使用相同的一般策略实现的任何数据结构),使用瞬态没有与读取相关的好处。实际上,瞬态需要为查找执行一些额外的工作 - Using IAM Policy Conditions for Fine-Grained Access Control.上的单个.get和结果上的分支。通常这几乎是不可测量的,因此当使用其关键价值主张(更快的更新链)相关的瞬态时,不必担心,但无论如何它确实意味着它们不会更快地进行查找。

这是因为瞬态使用与持久对应物 1 几乎相同的内部结构(实际上在persistent!调用之后,瞬态内部树直接用于新创建的持久数据结构中),因此它们的查找逻辑几乎相同,但是作为瞬态'一般API契约的问题,在对给定瞬态进行persistent!调用之后的任何尝试查找都必须导致IllegalAccessError。每次尝试查找时,这会花费很少的额外工作量。 2

1 存在一些细微差别:例如瞬态向量总是使用32个元素的数组作为尾部(与跟踪当前“结束索引”的字段配对),而持久性向量使用与尾部实际持有的项目一样多的数组;这意味着在大多数情况下可以通过就地变异来完成尾部的增长(在conj!的链中,只有1/32需要分配一个新的尾部阵列),并且它不会导致任何问题。持久版本,当您调用persistent!时,尾部会再次被修剪。但这并不会影响目前的讨论。

2 事实上,写入也支付了相同的微小成本,但通常能够更新数据结构而不是轻松分配新节点的好处超过它。

答案 2 :(得分:0)

有关瞬态结构的文档说,您将获得O(1)性能来创建结构本身(因此调用transient)。更新操作比正常更快(如assoc),但我希望读数相同。您可以在Clojure reference中找到更详细的解释。