Fuite de memory: augmentation constante de l'utilisation de la memory avec la journalisation de mouvement simple de l'appareil

Considérez ce code Swift simple qui enregistre datatables de mouvement du périphérique dans un file CSV sur le disque.

let motionManager = CMMotionManager() var handle: NSFileHandle? = nil override func viewDidLoad() { super.viewDidLoad() let documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSSsortingng let file = documents.ssortingngByAppendingPathComponent("/data.csv") NSFileManager.defaultManager().createFileAtPath(file, contents: nil, atsortingbutes: 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(NSUTF8SsortingngEncoding)! self.handle!.writeData(encoded) }) } 

J'ai été bloqué dessus pendant des jours. Il semble y avoir une fuite de memory, car la consommation de memory augmente régulièrement jusqu'à ce que le operating system suspende l'application pour dépasser les ressources.

Utilisation de la mémoire

Il est essentiel que cette application soit capable de fonctionner pendant de longues périodes sans interruption. Quelques notes:

  • J'ai essayé d'utiliser NSOutputStream et une bibliothèque d'écriture CSV (CHCSVParser), mais le problème est toujours présent
  • L'exécution asynchronous du code de journalisation (envelopper startDeviceMotionUpdatesToQueue dans dispatch_async ) ne supprime pas le problème
  • L'exécution du traitement des données de capteur dans un NSOperationQueue corrige le problème (uniquement lorsque maxConcurrentOperationCount > = 2). Cependant, cela provoque des problèmes de concurrency lors de l'écriture du file: le file de sortie est brouillé avec des lignes entrelacées entre elles.
  • Le problème ne semble pas apparaître lors de la journalisation des données de l'accéléromètre seulement, mais semble apparaître lors de l'logging de plusieurs capteurs (par exemple accéléromètre + gyroscope). Peut-être y a-t-il un seuil de débit d'écriture de file qui triggers ce problème?
  • Les pics de memory semblent être espacés d'environ 10 secondes (étapes dans le graphique ci-dessus). Peut-être que c'est indicatif de quelque chose? (pourrait être un artefact de l'infrastructure d'instrumentation de memory, ou peut-être sa collection de garbage)

Des pointeurs? J'ai essayé d'utiliser des instruments, mais je n'ai pas les compétences pour l'utiliser efficacement. Il semble que l'utilisation de la memory qui explose est causée par __NSOperationInternal . Voici un exemple de trace d'instruments .

Je vous remercie.

D'abord, vois cette réponse de la mienne:

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

Vous ne devriez pas regarder les charts de la memory dans le débogueur; Croyez seulement ce que les Instruments vous disent. Les versions de debugging et les versions Release sont gérées de façon très différente dans Swift.

Deuxièmement, s'il y a encore des problèmes, essayez d'envelopper l'intérieur de votre handler dans une fermeture autoreleasepool . Je ne m'attends pas à ce que cela fasse une différence, cependant (comme ce n'est pas une boucle), et je ne m'attends pas à ce que ce soit nécessaire, car je suppose que l'utilisation d'Instruments révélera qu'il n'y a jamais eu de problème. . Cependant, l'appel autoreleasepool s'assurera que les objects autoreleased n'ont aucune chance de s'accumuler.