内存泄漏:通过简单的设备运动logging稳定增加内存使用量

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

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) }) } 

我已经坚持了几天。 似乎有内存泄漏,因为内存消耗不断增加,直到操作系统暂停应用程序超过资源。

内存使用情况

这个应用程序能够长时间运行而不会中断是至关重要的。 一些说明:

  • 我试过使用NSOutputStream和一个CSV写入库(CHCSVParser),但问题仍然存在
  • asynchronous执行日志代码(在dispatch_async包装startDeviceMotionUpdatesToQueue )并不能解决问题
  • 在后台执行传感器数据处理NSOperationQueue 确实解决了这个问题(仅当maxConcurrentOperationCount > = 2时)。 但是,这会导致文件写入中出现并发问题:输出文件被混乱的线条混淆在一起。
  • 当只logging加速度计数据时,似乎并没有出现这个问题,但是在logging多个传感器(例如加速度计+陀螺仪)时似乎出现了这个问题。 也许有一个文件写入吞吐量的阈值触发这个问题?
  • 内存尖峰似乎间隔大约10秒的间隔(上图中的步骤)。 也许这是指示什么? (可能是内存工具基础设施的人为因素,也可能是垃圾收集)

任何指针? 我尝试过使用乐器,但是我没有这方面的技巧。 内存爆炸似乎是由__NSOperationInternal引起的。 以下是一个仪器跟踪示例。

谢谢。

首先,看我的这个答案:

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

您不应该在debugging器中查看内存图; 只相信仪器告诉你的东西。 debugging版本和发布版本在Swift中的内存pipe理方式非常不同。

其次,如果仍然有问题,请尝试将处理程序的内部封装在autoreleasepool闭包中。 但是,我不认为这会有所作为(因为这不是一个循环),我不认为这是必要的,因为我怀疑使用仪器会发现从来没有任何问题。 但是, autoreleasepool调用将确保自动释放的对象没有机会积累。