Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to beat NSMutableArray performance with Swift (beta) Array?

In Swift, I'm trying to build a large collection of items. When creating elements in CoreData on-the-go, this is very speedy. However when trying to keep an index to those items, creating an array Swift has a large performance impact. The code below is a benchmark between NSMutableArray and Swift's Array. When ran in the iOS Simulator, the Swift Array is around 8x slower. Why is this, can it be improved, or should it improve over the as Apple releases new builds of Xcode/Swift?

Code:

var start: NSDate
var time: NSTimeInterval
var batch = 1000000
var rate: Double

var oArr = NSMutableArray(capacity: batch)
start = NSDate()
for i in 1..batch {
    oArr.addObject(i)
}
time = -start.timeIntervalSinceNow
rate = Double(batch) / Double(time)
println("NSMutableArray \(batch) appends in \(time) sec: \(rate)/sec")

var sArr = Int[]()
start = NSDate()
for i in 1..batch {
    sArr += i
}
time = -start.timeIntervalSinceNow
rate = Double(batch) / Double(time)
println("Array<Int>     \(batch) appends in \(time) sec: \(rate)/sec")

Output in simulator (beta 2) 794%:

NSMutableArray 1000000 appends in 1.17320102453232 sec: 852368.843096295/sec
Array<Int>     1000000 appends in 9.31138801574707 sec: 107395.374170729/sec

Output in simulator (beta 3):

NSMutableArray 1000000 appends in 0.71416300535202 sec: 1400240.55083487/sec
Array<Int>     1000000 appends in 5.00839000940323 sec: 199664.961818569/sec

Output on iPhone 5 (beta 3 on iOS 7.1):

NSMutableArray 1000000 appends in 8.79256194829941 sec: 113732.494110367/sec
Array<Int>     1000000 appends in 55.6573320031166 sec: 17967.084730975/sec
like image 883
Bouke Avatar asked Feb 13 '23 14:02

Bouke


2 Answers

Update:

with Xcode beta-3, with a console program on a MacBook Pro 2 GHz Intel Core i7, I get these numbers with the original test (also fixed syntax due to minor grammar changes):

Debug (-O0):

NSMutableArray 1000000 appends in 0.782136023044586 sec: 1278549.9843203/sec
Array<Int>     1000000 appends in 5.56463801860809 sec: 179706.208500177/sec

Release (-Os):

NSMutableArray 1000000 appends in 0.14977502822876 sec: 6676680.43081684/sec
Array<Int>     1000000 appends in 0.124498963356018 sec: 8032195.3937913/sec

Release (-Ofast):

NSMutableArray 1000000 appends in 0.151567995548248 sec: 6597698.91646863/sec
Array<Int>     1000000 appends in 0.122538030147552 sec: 8160731.80543105/sec
like image 189
CouchDeveloper Avatar answered Feb 15 '23 03:02

CouchDeveloper


It doesn't seem fair that you're telling the NSMutableArray how much space it needs to allocate right up front but making the Swift array re-allocate itself with every single append. This makes the Swift version stupid fast, although it's kind of unfair in the other direction:

var sArr = Array<Int>(count: batch, repeatedValue: 0)
start = NSDate()
for i in 0..batch {
    sArr[i] = i
}

Edit: It looks like NSMutableArray doesn't actually use the capacity you provide to speed itself up, so maybe never mind?

like image 28
Nate Cook Avatar answered Feb 15 '23 04:02

Nate Cook