ios iPhone模拟器是否导致内存使用情况分析膨胀? [英] Is the ios iPhone simulator causing memory usage analysis to swell?

查看:96
本文介绍了ios iPhone模拟器是否导致内存使用情况分析膨胀?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的应用程序中处理大型文本文件.我知道在读取数据时要小心消耗的内存量.读取一条数据后,该应用程序无需保留数据.

I am trying to process a large text file in my app. I know that I want to be careful with the amount of memory being consumed while I read the data. Once a piece of data is read the app does not need to keep the data around.

感谢马丁R"和帖子阅读文件/URL逐行显示,以帮助我快速开始工作.

Thanks to "Martin R" and the post Read a file/URL line-by-line for helping me jump start my effort.

我正在尝试监视我的应用程序在读取大数据文件时的内存消耗,以确保可以按预期运行.这是我遇到问题的地方.

I am trying to monitor the memory consumption of my app as it reads in the large data file so that I can be sure it is behaving as expected. Here’s where I am running into a problem.

当我从Xcode中使用Command-I运行Instruments并监视分配时,我看到在读取文件期间,该应用程序窥视了约15MB,然后回落.这是可重复的+/- 0.5MB.

When I run Instruments using Command-I from within Xcode and I monitor allocations I see that during the read of the file the app peeks at ~15MB and then drops back down. This is fairly repeatable +/- 0.5MB.

当我从Xcode中使用Command-R运行应用程序,然后让它完成文件的读取操作,然后在Instruments中按record时,内存消耗现在猛增到约360MB.

When I run the app using Command-R from within Xcode and then let it finish reading through the file, and then press record within Instruments, the memory consumption now swells to ~360MB.

为了明确起见,我完成内存分配的两种测量方法是:
简介:
1. Xcode Command-I.
2.仪器记录分配.遵守〜15MB
模拟和配置文件:
1. Xcode Command-R.
2.让应用程序运行到"IDLE".
3.仪器记录.观察〜360MB.

So to clarify, the two ways I have done measurement of memory allocations are:
Profile:
1. Xcode Command-I.
2. Instruments Record Allocations. Observe ~15MB
Simulate and Profile:
1. Xcode Command-R.
2. Let app run to "IDLE".
3. Instruments Record. Observe ~360MB.

我一直试图在这里弄清楚一些事情.
Q1.为什么会有所不同? (这可能会回答我所有的问题)

I have been trying to figure out a few things here.
Q1. Why the difference? (This may answer all my questions)

Q2.我是否有真正的问题,还是这仅仅是一个问题,因为调试代码是如何注释到模拟器上的?

Q2. Do I have a real problem or is this only a problem because of how debug code is annotated on to the simulator?

Q3.与第二季度类似,如果我在真实设备上运行调试版本,是否会有相同的问题?

Q3. Similar to Q2, if I run a debug build on a real device, will it have the same issue?

Q4.对于我的应用程序,解析文件时〜15MB是可以接受的,但是〜360MB则不是.有没有其他方法可以继续在我的设备上进行调试,而不会造成360MB的损失?

Q4. For my app, ~15MB is acceptable when parsing the file, but ~360MB will not be. Is there another way I can continue to debug on my device without taking this 360MB hit?

版本8.1(8B62)
塞拉利昂
2.7Ghz i5
MacBook Pro大约2015年

Version 8.1 (8B62)
Sierra
2.7Ghz i5
MacBook Pro Circa 2015

附加了样本代码.为了方便读者,文件的第一部分仅仅是来自所引用帖子的代码的副本.可以直接使用此代码,然后在Xcode中运行它.底部是ViewController的ViewDidLoad()方法,在此方法运行".内存膨胀"在文件打开"之后.

Sample Code attached. The first part of the file is merely a copy of the code from the referenced post for reader convenience. One can take this code as is and run it in Xcode. At the bottom is the ViewController ViewDidLoad() method where things "run". The memory "swell" is after "File opened".

//
//

import UIKit

/* Originally from 
 * stackoverflow:
 * https://stackoverflow.com/questions/24581517/read-a-file-url-line-by-line-in-swift 
 * posted by Martin R.
 * Much thanks!
*/
class StreamReader  {

  let encoding : String.Encoding
  let chunkSize : Int
  var fileHandle : FileHandle!
  let delimData : Data
  var buffer : Data
  var atEof : Bool

  init?(path: String, delimiter: String = "\n", encoding: String.Encoding = .utf8,
        chunkSize: Int = 4096) {

    guard let fileHandle = FileHandle(forReadingAtPath: path),
      let delimData = delimiter.data(using: encoding) else {
        return nil
    }
    self.encoding = encoding
    self.chunkSize = chunkSize
    self.fileHandle = fileHandle
    self.delimData = delimData
    self.buffer = Data(capacity: chunkSize)
    self.atEof = false
  }

  deinit {
    self.close()
  }

  /// Return next line, or nil on EOF.
  func nextLine() -> String? {
    precondition(fileHandle != nil, "Attempt to read from closed file")

    // Read data chunks from file until a line delimiter is found:
    while !atEof {
      if let range = buffer.range(of: delimData) {
        // Convert complete line (excluding the delimiter) to a string:
        let line = String(data: buffer.subdata(in: 0..<range.lowerBound), encoding: encoding)
        // Remove line (and the delimiter) from the buffer:
        buffer.removeSubrange(0..<range.upperBound)
        return line
      }
      let tmpData = fileHandle.readData(ofLength: chunkSize)
      if tmpData.count > 0 {
        buffer.append(tmpData)
      } else {
        // EOF or read error.
        atEof = true
        if buffer.count > 0 {
          // Buffer contains last line in file (not terminated by delimiter).
          let line = String(data: buffer as Data, encoding: encoding)
          buffer.count = 0
          return line
        }
      }
    }
    return nil
  }

  /// Start reading from the beginning of file.
  func rewind() -> Void {
    fileHandle.seek(toFileOffset: 0)
    buffer.count = 0
    atEof = false
  }

  /// Close the underlying file. No reading must be done after calling this method.
  func close() -> Void {
    fileHandle?.closeFile()
    fileHandle = nil
  }
}

extension StreamReader : Sequence {
  func makeIterator() -> AnyIterator<String> {
    return AnyIterator {
      return self.nextLine()
    }
  }
}



class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let path2WordList = Bundle.main.path(forResource: "large_text_file", ofType: "txt")
    var wordCnt: Int = 0

    if nil != path2WordList {
      if let aStreamReader = StreamReader(path: path2WordList!) {
        defer {  aStreamReader.close() }
        print("File openned")

        /* Read and discard */
        while aStreamReader.nextLine() != nil {
          wordCnt += 1
        }

      } // if let ...
    } // if nil ...

    print ("Final wordCnt := \(wordCnt)")
  } // viewDidLoad


  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }


}

推荐答案

在使用长时间运行的while循环时,我遇到了类似的问题.问题在于,分配到当前自动释放池中的任何内容在循环退出之前都不会被释放.

I've encountered problems like this when using long running while loops. The problem is that anything that is allocated into the current autorelease pool won't get deallocated until the loop exits.

为防止这种情况,您可以将while循环的内容包装在autoreleasepool(invoking:)中.这将导致循环的每次迭代都有自己的自动释放池,每次都会消耗掉该释放池.

To guard against this, you can wrap the contents of your while loop in autoreleasepool(invoking:). This will cause each iteration of your loop to have its own autorelease pool that is drained each time.

它看起来像这样:

/// Return next line, or nil on EOF.
func nextLine() -> String? {
  precondition(fileHandle != nil, "Attempt to read from closed file")

  var result: String? = nil

  // Read data chunks from file until a line delimiter is found:
  while !atEof, result == nil {
    result = autoreleasepool {
      if let range = buffer.range(of: delimData) {
        // Convert complete line (excluding the delimiter) to a string:
        let line = String(data: buffer.subdata(in: 0..<range.lowerBound), encoding: encoding)
        // Remove line (and the delimiter) from the buffer:
        buffer.removeSubrange(0..<range.upperBound)
        return line
      }
      let tmpData = fileHandle.readData(ofLength: chunkSize)
      if tmpData.count > 0 {
        buffer.append(tmpData)
      } else {
        // EOF or read error.
        atEof = true
        if buffer.count > 0 {
          // Buffer contains last line in file (not terminated by delimiter).
          let line = String(data: buffer as Data, encoding: encoding)
          buffer.count = 0
          return line
        }
      }
      return nil
    }
  }
  return result
}

关于您的内存增长是否是调试环境的副作用,很难说.但是无论如何,防止这种增长可能是明智的.

As to whether your memory growth is a side effect of the debug environment, it's hard to say. But it would probably be wise to guard against this kind of growth regardless.

这篇关于ios iPhone模拟器是否导致内存使用情况分析膨胀?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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