How to improve Swift performance with stream buffers?

Let's say I want to process a large document using Swift. The entire file won't fit in memory, so we'll have to use streaming. In Swift, we have access to NSInputStream

, however, once the input is passed into the Swift string and consumed, performance degrades quickly. Let's say I want to read a buffer (1024 bytes) and create Swift Strings from them and then loop over the string to go to individual characters. I'll show the performance degradation step by step as additional instructions are added.

var stream = NSInputStream(URL: input)!
stream.open()
var buffer = [UInt8](count: 1024, repeatedValue: 0)

      

Only reading streams occurs at ~ 200 MB / s:

while stream.hasBytesAvailable {
    let readSize = stream.read(&buffer, maxLength: buffer.count)
}

      

Create NSString from buffers at ~ 130 MB / s:

while stream.hasBytesAvailable {
    let readSize = stream.read(&buffer, maxLength: buffer.count)
    let nsString = NSString(bytes: &buffer, length: readSize, encoding: NSUTF8StringEncoding)
}

      

Executing from NSString to String at ~ 90MB / s:

while stream.hasBytesAvailable {
    let readSize = stream.read(&buffer, maxLength: buffer.count)
    let nsString = NSString(bytes: &buffer, length: readSize, encoding: NSUTF8StringEncoding)
    let swiftString = nsString as String
}

      

Iterating over a line at ~ 1 MB / s:

while stream.hasBytesAvailable {
    let readSize = stream.read(&buffer, maxLength: buffer.count)
    let nsString = NSString(bytes: &buffer, length: readSize, encoding: NSUTF8StringEncoding)
    let swiftString = nsString as String
    for character in swiftString { }
}

      

Why is this code slow? I now realize that there is a lot of (implicit) casting going on in the current state of hybrid Objective C and Swift. However, the biggest performance hit seems to be iterating over the Swift string itself.

Note that the code was run with the Fastest [-O] compilation flag.

+3


source to share





All Articles