Memory leak: steady increase in memory usage with simple device motion logging

不问归期 提交于 2020-01-11 06:52:25

问题


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:

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

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.

Thank you.


回答1:


First, see this answer of mine:

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

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.

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.



来源:https://stackoverflow.com/questions/28545108/memory-leak-steady-increase-in-memory-usage-with-simple-device-motion-logging

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!