Memory leak in Swift's FileHandler.read

Hi,

I try to to read a file from Swift using class FileHandle and function

Code Block Swift
@available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *)
public func read(upToCount count: Int) throws -> Data?


This works fine in principle. However, I'm faced with a memory leak. The data allocated in the returned Data buffer is not freed. Is this possibly a bug in the underlying Swift wrapper?

Here is my test function, which reads a file block by block (and otherwise does nothing with the data).

Code Block Swift
func readFullFile(filePath: String) throws {
let blockSize = 32 * 1024
guard let file = FileHandle(forReadingAtPath: filePath) else {
fatalError("Failed to open file")
}
while (true) {
guard let data = try file.read(upToCount: blockSize) else {
break
}
}
}


If I call the function in a loop, and watch the program's memory consumption, it's obvious that the memory goes up in each loop by the size of the read file.

Can anybody confirm this behavior or knows how to fix it or if there's possibly already a bug issue opened at Apple?

My environment:
  • macOS 11.3.1 Big Sur

  • XCode 12.5

Best,
Michael

You always read the same data, definitely. Your loop is just to check if memory use grows ?

What happens when you exit the func ? Is memory released ?
As a already wrote: I e.g. use this function in a loop. Memory is not released.

I e.g. use this function in a loop. Memory is not released.

Many of the intermediate data consumed in Apple's APIs are autoreleased.
Have you tried using autoreleasepool?

I had the same issue, the method read(upToCount:) was growing the memory usage, as suggested the autoreleasepool solved the issue, you could rewrite it like this:

func readFullFile(filePath: String) throws {
    let blockSize = 32 * 1024

    guard let file = FileHandle(forReadingAtPath: filePath) else {
        fatalError("Failed to open file")
    }

    while (true) {
        var data: Data?
        try autoreleasepool {
            data = try file.read(upToCount: blockSize)
        }
        guard let data = data else {
           break
        }
    }
}

I've also tried to read a large file using the approach above and faced the same issues with memory consumption. My implementation is similar to that one.

autoreleasepool did't solve the issues.

It appears the new async/await API consumes the same large amounts of memory

let reader = try FileHandle(forReadingFrom: url)
for try await line in reader.bytes.lines {
    // some code processing `line`
}
Memory leak in Swift's FileHandler.read
 
 
Q