【问题标题】:Huge memory consumption with Strings使用字符串消耗大量内存
【发布时间】:2016-12-23 11:43:24
【问题描述】:

我正在一个结构中收集字符串数据。最后,我将该字符串写入文件。结果是 4 个文件,每个 80 MB。但在内部,它占用了将近 16 GB(!)的 RAM,迫使操作系统进行交换。 (我使用的是 Swift 3.0)

struct ActionCMD {  // struct!
    var cmd = String()

...

    mutating func lines(_ text: String, toTheTop: Bool = false) {
        if toTheTop { cmd  = text + cmd }
        else        { cmd += text }
    }
...
}

知道为什么会发生这种情况以及如何避免吗?

【问题讨论】:

  • 看起来你在某处有内存泄漏。您是否启动了 Instruments 并检查了所有内存的使用情况?
  • 不,我不知道这个工具。我正在搜索它(以及如何使用)并尝试检查该问题。
  • 当然可以,但如果不影响您的架构,您可以将ActionCMD 重写为class

标签: swift string memory optimization


【解决方案1】:

这可能与标记为mutating 的方法有关。 Swift 中的 mutating 方法会将其更改应用到新副本,在本例中为 ActionCMD 实例。根据您的其余代码,您可能会保留所有这些实例。

【讨论】:

  • 这很有趣。我正在更改结构中的字符串,所以它正在变异。在没有这种效果的情况下,是否有另一种方法可以做到这一点,但是(!)保持它像 Swift 一样?从 struct 切换到 class 是否会使情况变得更糟?也许不是,因为我不创建更多对象而不是改变自己?
  • Swift 中的结构是一种值类型,它似乎不能很好地支持您的用例。您可以将ActionCMD 设为具有实例变量var cmdComponents: [String] = [] 的类。当您以正确的顺序用所有字符串填充该数组后,您可以使用 cmdComponents.reduce("", combine: +) 从中创建一个字符串。
  • 谢谢。我做了一个类并使用了数组,它似乎将内存消耗减少了一半。还是 8,5 GB!?但我没有看到任何进一步的优化。
【解决方案2】:

首先,如果不知道如何分配和释放这些实例,就很难告诉您应用程序出了什么问题。您看到的问题可能与保留周期或您收集字符串数据的方式有关。 String 是一种值类型,因此每次更改它时,由于写入时复制功能,都会生成一个新副本。也就是说,我能给你的最好建议是让你仔细检查good article 关于使用 ObjC 和 Swift 改进内存管理的几个技巧。希望这会有所帮助。

【讨论】:

    【解决方案3】:

    在 C# 和 Java 中,您将使用字符串生成器,因为如果您不添加内容,则每次添加新字符串时都会创建一个新字符串。 stringbuilder 只分配一次内存。

    这个:http://cocoadocs.org/docsets/StringBuilder/ 好像是从 Java 到 Swift 的一个端口,没测试过,但是你可以试一试。

    这个:https://gist.github.com/kristopherjohnson/1fc55e811d944a430289 非常糟糕(可悲的是,谷歌的第一个结果)。它不是字符串生成器,只是普通方法的包装器。

    【讨论】:

      猜你喜欢
      • 2015-07-04
      • 2022-01-16
      • 2014-01-04
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 1970-01-01
      相关资源
      最近更新 更多