Als ich mit einem schnellen Tutorial herumspielte, fing ich an, eine benutzerdefinierte isPrime
Methode zu schreiben, um zu überprüfen, ob eine gegebene Int
Prime ist oder nicht.Ist Swift wirklich langsam im Umgang mit Zahlen?
Nach dem Schreiben Ich erkennen, dass es richtig funktioniert, aber fand es ein bisschen langsam auf einige ziemlich große Zahl durchzuführen isPrime
(noch viel niedriger als Int.max
).
Also schrieb ich das gleiche Stück Code in objc und der Code wurde viel schneller ausgeführt (ein Faktor von 66x). Hier
ist der SWIFT-Code:
class Swift {
class func isPrime(n:Int) -> Bool {
let sqr : Int = Int(sqrt(Double(n))) + 1
for i in 2...sqr {
if n % i == 0 {
return false
}
}
return true;
}
class func primesInRange(start:Int, end:Int) -> Int[] {
var primes:Int[] = Int[]()
for n in start...end {
if self.isPrime(n) {
primes.append(n)
}
}
return primes;
}
}
Und der objc Code:
@implementation Utils
+ (BOOL)isPrime:(NSUInteger)n {
NSInteger sqr = (NSUInteger)(sqrt(n))+1;
for (NSUInteger i = 2; i < sqr; ++i) {
if (n % i == 0) {
return false;
}
}
return YES;
}
+ (NSArray*)primesInRange:(NSUInteger)start end:(NSUInteger)end {
NSMutableArray* primes = [NSMutableArray array];
for (NSUInteger i = start; i <= end; ++i) {
if ([self isPrime:i])
[primes addObject:@(i)];
}
return primes.copy;
}
@end
Und in main.swift
:
let startDateSwift = NSDate.date()
let swiftPrimes = Swift.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedSwift = NSDate.date().timeIntervalSinceDate(startDateSwift)*1000
let startDateObjc = NSDate.date()
let objcPrimes = Utils.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedObjc = NSDate.date().timeIntervalSinceDate(startDateObjc)*1000
println("\(swiftPrimes) took: \(elapsedSwift)ms");
println("\(objcPrimes) took: \(elapsedObjc)ms");
Dies erzeugt:
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 3953.82004976273ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 66.4250254631042ms
Ich weiß, dass ich extension
auf Int
hier verwendet haben könnte, um zu überprüfen, ob eine Zahl prime ist, aber ich wollte beide Code sehr ähnlich sein.
Kann mir jemand sagen, warum dieser schnelle Code so viel langsamer ist? Der 66x-Faktor ist ziemlich gruselig und wird nur noch schlimmer, wenn ich die Reichweite vergrößere.
Haben Sie sich den generierten Assembler-Code angesehen? Ich denke, das wäre ziemlich lehrreich. – cmaster
Zuerst die Reihenfolge der Tests umkehren und prüfen, ob die Ergebnisse identisch sind. Ich sehe nicht, warum es in diesem Fall wichtig wäre, aber in anderen Kontexten könnten Sie Caching-Effekte usw. bekommen. –
@cmaster xcode 6 (6A215l) scheint noch nicht 'Assembly View' für Swif zu unterstützen. @ "Tom Zych" ja das habe ich auch versucht aber das selbe ergebnis. Objc gerade läuft schnell in beliebiger Reihenfolge. – apouche