内存泄漏:通过简单的设备运动日志记录,内存使用量稳步增加 [英] Memory leak: steady increase in memory usage with simple device motion logging

查看:122
本文介绍了内存泄漏:通过简单的设备运动日志记录,内存使用量稳步增加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个简单的Swift代码,它将设备运动数据记录到磁盘上的CSV文件中.

Consider this simple Swift code that logs device motion data to a CSV file on disk.

let motionManager = CMMotionManager() 
var handle: NSFileHandle? = nil

override func viewDidLoad() {
    super.viewDidLoad()

    let documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
    let file = documents.stringByAppendingPathComponent("/data.csv")

    NSFileManager.defaultManager().createFileAtPath(file, contents: nil, attributes: nil)
    handle = NSFileHandle(forUpdatingAtPath: file)

    motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: {(data, error) in
        let data_points = [data.timestamp, data.attitude.roll, data.attitude.pitch, data.attitude.yaw, data.userAcceleration.x,
            data.userAcceleration.y, data.userAcceleration.z, data.rotationRate.x, data.rotationRate.y, data.rotationRate.z]

        let line = ",".join(data_points.map { $0.description }) + "\n"
        let encoded = line.dataUsingEncoding(NSUTF8StringEncoding)!

        self.handle!.writeData(encoded)
    })
}

我已经坚持了好几天.似乎有内存泄漏,因为内存 消费稳步增长,直到操作系统因超出资源而暂停应用程序为止.

I've been stuck on this for days. There appears to be a memory leak, as memory consumption steadily increases until the OS suspends the app for exceeding resources.

至关重要的是,该应用程序能够长时间运行而不被中断.一些注意事项:

It's critical that this app be able to run for long periods without interruption. Some notes:

  • 我尝试使用NSOutputStream和CSV编写库(CHCSVParser),但问题仍然存在
  • 异步执行日志记录代码(在dispatch_async中包装startDeviceMotionUpdatesToQueue)不能解决问题
  • 在后台执行传感器数据处理NSOperationQueue 确实解决了该问题(仅当maxConcurrentOperationCount> = 2时).但是,这会导致文件写入过程中的并发问题:输出文件之间的行相互缠结,乱七八糟.
  • 该问题似乎仅在记录加速度计数据时不会出现,但在记录多个传感器(例如加速度计+陀螺仪)时似乎不会出现.也许存在触发此问题的文件写入吞吐量阈值?
  • 内存峰值似乎以大约10秒的间隔被隔开(上图中的步骤).也许这表明某些事情? (可能是内存检测基础结构的产物,或者可能是垃圾回收)
  • I've tried using NSOutputStream and a CSV-writing library (CHCSVParser), but the issue is still present
  • Executing the logging code asynchronously (wrapping startDeviceMotionUpdatesToQueue in dispatch_async) does not remove the issue
  • Performing the sensor data processing in a background NSOperationQueue does fix the issue (only when maxConcurrentOperationCount >= 2). However, that causes concurrency issues in file writing: the output file is garbled with lines intertwined between each other.
  • The issue does not seem to appear when logging accelerometer data only, but does seem to appear when logging multiple sensors (e.g. accelerometer + gyroscope). Perhaps there's a threshold of file writing throughput that triggers this issue?
  • The memory spikes seem to be spaced out at roughly 10 second intervals (steps in the above graph). Perhaps that's indicative of something? (could be an artifact of the memory instrumentation infrastructure, or perhaps it's garbage collection)

有指针吗?我尝试使用乐器,但是我没有有效使用它的技能.似乎内存使用量爆炸是由__NSOperationInternal引起的.这是一个示例仪器跟踪.

Any pointers? I've tried to use Instruments, but I don't have the skills the use it effectively. It seems that the exploding memory usage is caused by __NSOperationInternal. Here's a sample Instruments trace.

谢谢.

推荐答案

首先,请参阅我的答案:

First, see this answer of mine:

https://stackoverflow.com/a/28566113/341994

您不应该在调试器中查看内存"图.只相信乐器会告诉您的内容.在Swift中,调试版本和Release版本的内存管理方式非常不同.

You should not be looking at the Memory graphs in the debugger; believe only what Instruments tells you. Debug builds and Release builds are memory-managed very differently in Swift.

第二,如果仍然有问题,请尝试将处理程序的内部包装在autoreleasepool闭包中.我不希望这会有所作为,但是(因为这不是循环),并且我也不希望这是有必要的,因为我怀疑使用Instruments会发现从一开始就没有任何问题. .但是,autoreleasepool调用将确保自动释放的对象没有堆积的机会.

Second, if there is still trouble, try wrapping the interior of your handler in an autoreleasepool closure. I do not expect that that would make a difference, however (as this is not a loop), and I do not expect that it will be necessary, as I suspect that using Instruments will reveal that there was never any problem in the first place. However, the autoreleasepool call will make sure that autoreleased objects are not given a chance to accumulate.

这篇关于内存泄漏:通过简单的设备运动日志记录,内存使用量稳步增加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆