gpt4 book ai didi

ios - 使用 Libxml2 解析 XML 时占用大量 RAM

转载 作者:行者123 更新时间:2023-11-30 12:45:14 25 4
gpt4 key购买 nike

我正在使用 URLSessionDataTask 从 API 下载 XML 文件。
XML 如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<ResultList id="12345678-0" platforms="A;B;C;D;E">
<Book id="1111111111" author="Author A" title="Title A" price="9.95" ... />
<Book id="1111111112" author="Author B" title="Title B" price="2.00" ... />
<Book id="1111111113" author="Author C" title="Title C" price="5.00" ... />
<ResultInfo bookcount="3" />
</ResultList>

有时 XML 可能有数千本书。
我正在使用 Libxml2 中的 SAX 解析器解析 XML。解析时,我创建一个对象 Book 并设置 XML 中的值,如下所示:

private func startElementSAX(_ ctx: UnsafeMutableRawPointer?, name: UnsafePointer<xmlChar>?, prefix: UnsafePointer<xmlChar>?, URI: UnsafePointer<xmlChar>?, nb_namespaces: CInt, namespaces: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?, nb_attributes: CInt, nb_defaulted: CInt, attributes: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?) {

let elementName = String(cString: name!)

switch elementName {
case "Book":
let book = buildBook(nb_attributes: nb_attributes, attributes: attributes)
parser.delegate?.onBook(book: book)
default:
break
}
}

func buildBook(nb_attributes: CInt, attributes: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?) -> Book {
let fields = 5 /* (localname/prefix/URI/value/end) */
let book = Book()
for i in 0..<Int(nb_attributes) {
if let localname = attributes?[i * fields + 0],
//let prefix = attributes?[i * fields + 1],
//let URI = attributes?[i * fields + 2],
let value_start = attributes?[i * fields + 3]//,
/*let value_end = attributes?[i * fields + 4]*/ {

let localnameString = String(cString: localname)
let string_start = String(cString: value_start)
//let string_end = String(cString: value_end)

if let end = string_start.characters.index(of: "\"") {
let value = string_start.substring(to: end)
book.setValue(value, forKey: localnameString)
} else {
book.setValue(string_start, forKey: localnameString)
}
}
}
return book
}

在 UITableViewController 中,onBook(book: Book) 委托(delegate)方法将 book 对象附加到数组并更新 UITableView。到目前为止一切顺利。

现在的问题是,它占用了太多的设备内存,所以我的设备变得很慢。 XML 中有大约 500 本书,需要 >500 MB 的 RAM。我不知道为什么。当我在 Instruments 中查找 RAM 时,我在 _HeapBufferStorage<_StringBufferIVars, UInt16> 类别中看到所有分配的内存

Instruments

多个条目大于 100 KB

HeapBufferStorage entries事件历史记录中列出了 buildBook() 方法

Event History

当我使用 Foundation 的 XMLParser 和构造函数 XMLParser(contentsOf: URL) 时,它​​首先下载整个 XML,然后解析它,我的 RAM 使用情况正常。不管有多少书。但我想尽快在 UITableView 中显示书籍。我只想要类似适用于 iOS 的 Android XMLPullParser 之类的东西。

最佳答案

我正在使用 libxml2(由于 this 问题)并具有如下代码:

xmlParseChunk(ctxt, data, Int32(read), 0)

更改对此的调用可显着减少内存消耗量:

autoreleasepool {
xmlParseChunk(ctxt, data, Int32(read), 0)
}

如果您使用像上面这样的推送解析器调用,这可能会解决您的问题。如果没有,那么将您的委托(delegate)调用包装在 autoreleasepool 调用中可能会有所帮助。

原因是因为正在创建大量中间对象并将其添加到自动释放池中但没有被释放。请参阅this发帖了解更多详情。

另一种方法是通过以其他方式更改代码来减少添加到自动释放池中的对象数量。例如,我发现我通过在可以避免的地方修剪空白来创建额外的字符串。

此外,这与您的问题无关,但属性的开始和结束告诉您字符串的长度,您应该使用它。

例如:

let valStart = UnsafeMutableRawPointer(mutating: attributes!
.advanced(by: 3 + Int(i * 5)).pointee)
let valEnd = UnsafeMutableRawPointer(mutating: attributes!
.advanced(by: 4 + Int(i * 5)).pointee)
let valData = Data(bytesNoCopy: valStart!, count: valEnd! - valStart!,
deallocator: .none)
let attrValue = String(data: valData, encoding: String.Encoding.utf8)

关于ios - 使用 Libxml2 解析 XML 时占用大量 RAM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41721369/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com