Comme beaucoup d'autres développeurs, j'ai été très excité à propos de la nouvelle Swift de la langue d'Apple. Apple a fait sa vitesse est plus rapide que l'Objective-C et peut être utilisé pour écrire le système d'exploitation. Et à partir de ce que j'ai appris jusqu'à présent, c'est un statique tapé de la langue et de pouvoir avoir de contrôler précisément sur le type de données exactes (comme nombre entier de longueur). Donc il ne ressemble ayant un bon potentiel de performance de gestion de tâches critiques, comme le traitement de l'image, à droite?
C'est ce que j'ai pensé, avant j'ai fait un test rapide. Le résultat m'a vraiment surpris.
Voici une très simplifiée de l'image alpha blending extrait de code en C:
test.c:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint8_t pixels[640*480];
uint8_t alpha[640*480];
uint8_t blended[640*480];
void blend(uint8_t* px, uint8_t* al, uint8_t* result, int size)
{
for(int i=0; i<size; i++) {
result[i] = (uint8_t)(((uint16_t)px[i]) *al[i] /255);
}
}
int main(void)
{
memset(pixels, 128, 640*480);
memset(alpha, 128, 640*480);
memset(blended, 255, 640*480);
// Test 10 frames
for(int i=0; i<10; i++) {
blend(pixels, alpha, blended, 640*480);
}
return 0;
}
J'ai compilé sur mon Macbook Air 2011 avec la commande suivante:
clang -O3 test.c -o test
Le 10 cadre temps de traitement est d'environ 0,01 s. En d'autres termes, il prend le code C 1ms pour traiter une image:
$ time ./test
real 0m0.010s
user 0m0.006s
sys 0m0.003s
Alors j'ai une Swift version du même code:
test.swift:
let pixels = UInt8[](count: 640*480, repeatedValue: 128)
let alpha = UInt8[](count: 640*480, repeatedValue: 128)
let blended = UInt8[](count: 640*480, repeatedValue: 255)
func blend(px: UInt8[], al: UInt8[], result: UInt8[], size: Int)
{
for(var i=0; i<size; i++) {
var b = (UInt16)(px[i]) * (UInt16)(al[i])
result[i] = (UInt8)(b/255)
}
}
for i in 0..10 {
blend(pixels, alpha, blended, 640*480)
}
La construction de la ligne de commande est:
xcrun swift -O3 test.swift -o test
J'utilise ici le même O3
niveau d'optimisation de drapeau à faire la comparaison, espérons juste. Cependant, la vitesse résultante est 100 fois plus lent:
$ time ./test
real 0m1.172s
user 0m1.146s
sys 0m0.006s
En d'autres termes, il faut Swift ~120ms à la transformation d'une image qui prend C juste 1 ms.
Ce qui s'est passé?
Mise à jour: je suis en utilisant clang:
$ gcc -v
Configured with: --prefix=/Applications/Xcode6-Beta.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.34.4) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.2.0
Thread model: posix
Mise à jour: plus de résultats avec les différents cours d'exécution itérations:
Voici le résultat pour différents nombre de "cadres", c'est à dire changer le principal for
numéro de boucle de 10 pour les autres numéros. Remarque maintenant je suis encore plus vite du code C temps (cache chaud?), tandis que la Swift de temps ne change pas trop:
C Time (s) Swift Time (s)
1 frame: 0.005 0.130
10 frames(*): 0.006 1.196
20 frames: 0.008 2.397
100 frames: 0.024 11.668
Mise à jour: `-Ofast` aide
Avec -Ofast
suggéré par @mweathers, la Swift de vitesse qui va jusqu'à la fourchette raisonnable.
Sur mon portable le Swift version avec -Ofast
obtient 0.013 s pour 10 cadres et 0.048 s pour 100 cadres, près de la moitié de la performance.