Is autoreleasepool still needed with the new Foundation?

In Swift, you had to use autoreleasepool when loading data, e.g.:

autoreleasepool {
    let image = loadImageFromFile("image.png")
    // ...
}

or also when calling Data(contentsOf: url).

And for code that should also work on Linux and Windows, where this was not needed, the following "shim" was convenient:

#if os(Linux) || os(Android) || os(Windows)
/// A shim for Linux that runs the given block of code.
///
/// The existence of this shim allows you the use of auto-release pools to optimize memory footprint on Darwin platforms while maintaining
/// compatibility with Linux where this API is not implemented.
@discardableResult
public func autoreleasepool<Result>(_ block: () throws -> Result) rethrows -> Result {
    return try block()
}
#endif

I guess that all this not necessary any more with the newer Swift versions?

1 Like

Predicting which things use Objective-C under the hood on Darwin is still fairly difficult. It can vary depending on what OS version your app is running on, which arguments you pass to a function (for example a number of Foundation String extensions have used ObjC only when passed non-ASCII/UTF8 encoding arguments), and other factors.

It’s worth noting, though, that Swift Concurrency on Darwin always wraps jobs in a pool (as does RunLoop, and DispatchQueue has a flag to enable the same), so you may not need explicit ones in your code anyway.

1 Like

With the following test, when reading several files sequentially (and not using at a later point) of size 180 MB each, the memory consumption is approximately 180 MB, so obviously it does not pile up and autoreleasedoes not seem to be necessary at least for Data(contentsOf:).

I am just wondering while in the pauses there actually is this 180 MB memory consumption, as we are out of the scope of the variable then. But using autorelease does not change this.

for n in 1...1 {
    let data = try Data(contentsOf: directory.appending(component: "\(n).xml"))
    print("#\(n): \(data.count)")
}

print("Waiting..."); _ = readLine()

for n in 1...5 {
    let data = try Data(contentsOf: directory.appending(component: "\(n).xml"))
    print("#\(n): \(data.count)")
}

print("Waiting..."); _ = readLine()