F# 不变的字典开销?

F# 不变的字典开销?,f#,dictionary,immutability,F#,Dictionary,Immutability,在F#中使用不可变字典时,添加/删除条目时会有多少开销 它是否会将整个bucket视为不可变的,并克隆这些bucket,而只重新创建已更改项目的bucket 即使是这样,为了创建新的词典,似乎还需要进行大量的复制(?)很多树结构都可以重用。我不知道算法的复杂度,我猜平均来说只有像摊销logN‘废物’ 为什么不试着写一个程序来测量呢?(我们将看看今晚我是否有动力亲自尝试。) 编辑 好的,这是我破解的东西。我还没有决定这里是否有有用的数据 open System let rng = new Ran

在F#中使用不可变字典时,添加/删除条目时会有多少开销

它是否会将整个bucket视为不可变的,并克隆这些bucket,而只重新创建已更改项目的bucket


即使是这样,为了创建新的词典,似乎还需要进行大量的复制(?)

很多树结构都可以重用。我不知道算法的复杂度,我猜平均来说只有像摊销logN‘废物’

为什么不试着写一个程序来测量呢?(我们将看看今晚我是否有动力亲自尝试。)

编辑

好的,这是我破解的东西。我还没有决定这里是否有有用的数据

open System

let rng = new Random()
let shuffle (array : _[]) =
    let n = array.Length
    for x in 1..n do
        let i = n-x
        let j = rng.Next(i+1)
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp

let TryTwoToThe k =
    let N = pown 2 k

    GC.Collect()

    let a = Array.init N id

    let makeRandomTreeAndDiscard() =
        shuffle a
        let mutable m = Map.empty
        for i in 0..N-1 do
            m <- m.Add(i,i)

    for i in 1..20 do
        makeRandomTreeAndDiscard()
    for i in 1..20 do
        makeRandomTreeAndDiscard()
    for i in 1..20 do
        makeRandomTreeAndDiscard()

#time
// run these as separate interactions
printfn "16"
TryTwoToThe 16

printfn "17"
TryTwoToThe 17

printfn "18"
TryTwoToThe 18

这表明内存的扩展可能是超线性的,但不会太严重。我认为gen0集合大概是重新平衡树的“浪费”的一个很好的代表。但是已经很晚了,所以我不确定我是否已经充分考虑了这一点

我研究了F#
Map
类型的实现,我认为它是作为一个。它将值存储在树的内部节点以及叶子中,对于每个节点,它确保|高度(左)-高度(右)|因此F中的字典是二叉树的某种形式,而不是哈希表?我想这是有道理的。如果是的话,它是自我平衡的吗?是的,是的。您可以在
map.fs
中查看CTP中的实现。中描述的一个使用“哈希数组映射trie”,需要log32N跳。这可以被认为是所有实际问题的O(1)。
--> Timing now on

> 
16
Real: 00:00:08.079, CPU: 00:00:08.062, GC gen0: 677, gen1: 30, gen2: 1
> 
17
Real: 00:00:17.144, CPU: 00:00:17.218, GC gen0: 1482, gen1: 47, gen2: 4
> 
18
Real: 00:00:37.790, CPU: 00:00:38.421, GC gen0: 3400, gen1: 1059, gen2: 17
            A 
         /     \
        B       C
      /   \
     D     E