Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xcode 快速字典内存消耗是天文数字_Xcode_Swift_Dictionary_Memory_Trie - Fatal编程技术网

Xcode 快速字典内存消耗是天文数字

Xcode 快速字典内存消耗是天文数字,xcode,swift,dictionary,memory,trie,Xcode,Swift,Dictionary,Memory,Trie,有人能帮助解释一下为什么下面的代码在运行时消耗了超过100MB的RAM吗 public struct Trie<Element : Hashable> { private var children: [Element:Trie<Element>] private var endHere : Bool public init() { children = [:] endHere = false }

有人能帮助解释一下为什么下面的代码在运行时消耗了超过100MB的RAM吗

public struct Trie<Element : Hashable> {
    private var children: [Element:Trie<Element>]
    private var endHere : Bool

    public init() {
        children = [:]
        endHere  = false
    }
    public init<S : SequenceType where S.Generator.Element == Element>(_ seq: S) {
        self.init(gen: seq.generate())
    }
    private init<G : GeneratorType where G.Element == Element>(var gen: G) {
        if let head = gen.next() {
            (children, endHere) = ([head:Trie(gen:gen)], false)
        } else {
            (children, endHere) = ([:], true)
        }
    }
    private mutating func insert<G : GeneratorType where G.Element == Element>(var gen: G) {
        if let head = gen.next() {
            let _ = children[head]?.insert(gen) ?? { children[head] = Trie(gen: gen) }()
        } else {
            endHere = true
        }
    }
    public mutating func insert<S : SequenceType where S.Generator.Element == Element>(seq: S) {
        insert(seq.generate())
    }
}

var trie = Trie<UInt32>()
for i in 0..<300000 {
    trie.insert([UInt32(i), UInt32(i+1), UInt32(i+2)])
}

为什么这个数据结构在运行时会消耗超过100 MB的内存?

您的结构的大小是9字节,而不是5字节

public struct Trie<Element : Hashable> {
    private var children: [Element:Trie<Element>]
    private var endHere : Bool

    public init() {
        children = [:]
        endHere  = false
    }
    public init<S : SequenceType where S.Generator.Element == Element>(_ seq: S) {
        self.init(gen: seq.generate())
    }
    private init<G : GeneratorType where G.Element == Element>(var gen: G) {
        if let head = gen.next() {
            (children, endHere) = ([head:Trie(gen:gen)], false)
        } else {
            (children, endHere) = ([:], true)
        }
    }
    private mutating func insert<G : GeneratorType where G.Element == Element>(var gen: G) {
        if let head = gen.next() {
            let _ = children[head]?.insert(gen) ?? { children[head] = Trie(gen: gen) }()
        } else {
            endHere = true
        }
    }
    public mutating func insert<S : SequenceType where S.Generator.Element == Element>(seq: S) {
        insert(seq.generate())
    }
}

var trie = Trie<UInt32>()
for i in 0..<300000 {
    trie.insert([UInt32(i), UInt32(i+1), UInt32(i+2)])
}
您可以使用
sizeof
进行检查:

let size = sizeof( Trie< UInt32 > );
let size=sizeof(Trie);
此外,您迭代了300000次,但插入了3个值(当然,这是一个trie)。那就是90万了。
无论如何,这本身并不能解释你观察到的内存消耗

我的Swift不是很流利,我不懂你的代码。
也许它也有一些错误,使得它分配的内存超出了需要

但无论如何,为了理解发生了什么,您需要在工具中运行代码(command-i)

在我的机器上,我可以看到通过
swift\u slowAlloc
分配的90000096字节 那更像是

为什么是96字节,假设代码中没有错误?
这可能是因为为元素分配内存的方式。
当满足一个请求时,内存分配器可以分配比请求更多的内存。这可能是因为它需要一些内部元数据,因为分页,因为对齐


但是,尽管如此,它看起来确实有些夸张,所以请使用工具并仔细检查您的代码在做什么。

sizeof
只报告堆栈上的静态足迹,而
字典
只是对其内部引用类型实现的引用的一种包装,也是对写时拷贝的支持。换句话说,字典的键值对和哈希表是在堆上分配的,堆不在
sizeof
中。这适用于所有其他Swift托收类型

在您的例子中,您正在创建三个
Trie
——间接地创建三个字典——每30万次迭代。如果@macmake提到的96字节分配是字典的最小开销(例如它的哈希桶),我不会感到惊讶

存储容量的增长可能也会带来成本。因此,您可以尝试查看在字典上设置
最小容量是否有帮助。另一方面,如果不需要每次迭代生成一个发散路径,则可以考虑间接枚举作为备选方案,例如

public enum Trie<Element> {
    indirect case Next(Element, Trie<Element>)
    case End
}
公共枚举Trie{
下一个间接案例(元素,Trie)
案例结束
}

这将占用更少的内存。

MacMake,感谢您的回复。您是正确的,结构大小是9字节。意识到这一点后,我更新了我的问题。您还纠正了,这仍然不能解释这里消耗的内存量有多大。我也使用了仪器,注意到96字节的分配总量为82.4 MB。但是为什么呢?需要更多的调查…不客气。这也可能是由于swift_slowalloc造成的错误。你检查过这个雷达了吗?看起来像你的例子:只是简单地阅读一下雷达-我需要进一步调查,并尝试用一个更简单的例子来重现以确认。这个错误似乎是在Xcode 7 beta 5中修复的,所以我们可以排除它可能是罪魁祸首。安德斯,你是对的。我一直在玩minimumCapacity,它似乎对0-2之间的值没有影响。文件还规定“实际容量为2的最小幂,即>=最小容量”。
public enum Trie<Element> {
    indirect case Next(Element, Trie<Element>)
    case End
}