35 votes

Swift est-il vraiment lent à gérer les chiffres?

Comme je l'ai été jouer avec un rapide tutoriel, j'ai commencé à écrire une coutume isPrime méthode pour vérifier si un Int est premier ou non.

Après l'avoir écrit, j'ai réalisé qu'il a été fonctionne correctement mais le trouve un peu lent à accomplir isPrime sur certains assez grand nombre (encore beaucoup plus faible alors Int.max).

J'ai donc écrit le même morceau de code dans objc et le code a été exécuté beaucoup plus rapide (d'un facteur de 66 fois le niveau).

Voici le code swift:

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;
    }
}

Et l'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

Et dans 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");

Ce produit:

[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 3953.82004976273ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 66.4250254631042ms

Je sais que j'aurais pu utiliser un extension sur Int ici pour vérifier si un nombre est premier, mais je voulais à la fois le code pour être très similaires.

Quelqu'un peut-il me dire pourquoi ce code swift est beaucoup plus lent? Le 66 fois le niveau de facteur est assez effrayant et ne fait que s'aggraver comme je l'incrément de la gamme.

27voto

Joseph Mark Points 2348

Voici niveaux d'optimisation pour la Swift compilateur de génération de code (vous pouvez les trouver dans les Paramètres de construction):

[-Onone] no optimizations, the default for debug.
[-O]     perform optimizations, the default for release.
[-Ofast] perform optimizations and disable runtime overflow checks and runtime type checks.

À l'aide de votre code, j'ai eu de ces moments, à différents niveaux d'optimisation:

[Individualisé]

Swift: 6110.98903417587ms
Objc:  134.006023406982ms

[-O]

Swift: 89.8249745368958ms
Objc:  85.5680108070374ms

[-Ofast]

Swift: 77.1470069885254ms
Objc:  76.3399600982666ms

Gardez à l'esprit que -Ofast est livré avec risques. par exemple, Il va l'ignorer en silence entier et de la matrice de débordements, la production non-sens des résultats, donc si vous choisissez de l'utiliser, vous devrez vous assurer que les débordements ne sont pas possibles dans votre programme.

5voto

apouche Points 2000

Les crédits à @sjeohp pour son commentaire qui est, fondamentalement, la réponse à la question.

J'ai essayé d'optimiser le code pour la plus agressive en Release pour les deux LLVM et Swift optimisations:

enter image description here

enter image description here

Compilé le projet en Release et a obtenu:

[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 63.211977481842ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 60.0320100784302ms

Encore une fois, merci @sjeohp pour la capture de ce !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X