Swift et types de base

MalaMala Membre, Modérateur
juin 2014 modifié dans Objective-C, Swift, C, C++ #1

Je me pose la question de savoir s'il est possible de créer de vrais types de base tel qu'on le fait en Obj-C (int, char, etc) sans la couche objet de Swift?


 


Parce que là  dans l'immédiat, en jouant avec le type UInt etc de Swift, c'est vraiment la cata niveau perfs. Essayez un simple bout de code comme ça, vous allez voir...



var res = UInt.min
        
var deb = NSDate.date();
        
for i in 0..10000000
{
res++
}
        
var fin = NSDate.date();
        
var delay = fin.timeIntervalSinceDate(deb)
        
println(delay)

Presque 10s pour quelque chose qui relève du centième de seconde en Obj-C et cela même en mode debug.


 


Elles sont où les perfs annoncées par Apple?


«1

Réponses

  • AliGatorAliGator Membre, Modérateur
    Tu testes ça où? Si c'est dans playground ça m'étonne pas c'est à  cause du JIT.
  • laudemalaudema Membre
    juin 2014 modifié #3

    Chez moi ça prend 7 secondes et dans playground ça ne produit qu'un gros tas de loge que je n'arrive pas à  déchiffrer 


     



     


    fatal error: Can't unwrap Optional.None

    Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

    The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.

    * thread #1: tid = 0x23d74, 0x000000010ea9302d libswift_stdlib_core.dylib`Swift._StringCore._growBuffer (@inout Swift._StringCore)(Swift.Int, minElementWidth : Swift.Int) -> Swift.COpaquePointer + 813, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

      * frame #0: 0x000000010ea9302d libswift_stdlib_core.dylib`Swift._StringCore._growBuffer (@inout Swift._StringCore)(Swift.Int, minElementWidth : Swift.Int) -> Swift.COpaquePointer + 813

        frame #1: 0x000000010ea8e43f libswift_stdlib_core.dylib`Swift._StringCore.append (@inout Swift._StringCore)(Swift._StringCore) -> () + 607

        frame #2: 0x000000010ea8efa5 libswift_stdlib_core.dylib`Swift.+ @infix (Swift.String, Swift.String) -> Swift.String + 117

        frame #3: 0x000000010ec52a97 PlaygroundLogger`Swift.String._workaround17041741 (Swift.String)() -> Swift.String + 87

        frame #4: 0x000000010ec518e2 PlaygroundLogger`Swift.String.byteLength (Swift.String)() -> Swift.Int + 82

        frame #5: 0x000000010ec4317f PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(Swift.String) -> PlaygroundLogger.BytesStream + 127

        frame #6: 0x000000010ec4adbf PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured_impl (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64, Swift.Array<Swift.Range<Swift.UInt64>>...) -> () + 2143

        frame #7: 0x000000010ec45e0c PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64, PlaygroundLogger.LoggerCappingPolicy) -> () + 1996

        frame #8: 0x000000010ec46e7d PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64) -> () + 989

        frame #9: 0x000000010ec4c856 PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64) -> () + 2486

        frame #10: 0x000000010ec47899 PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_children (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64, Swift.Range<Swift.UInt64>) -> () + 2233

        frame #11: 0x000000010ec4b96a PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured_impl (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64, Swift.Array<Swift.Range<Swift.UInt64>>...) -> () + 5130

        frame #12: 0x000000010ec45e0c PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64, PlaygroundLogger.LoggerCappingPolicy) -> () + 1996

        frame #13: 0x000000010ec46e7d PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_structured (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64) -> () + 989

        frame #14: 0x000000010ec4c856 PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode (PlaygroundLogger.PlaygroundObjectWriter)(Swift.Mirror, Swift.UInt64) -> () + 2486

        frame #15: 0x000000010ec4cf18 PlaygroundLogger`PlaygroundLogger.PlaygroundObjectWriter.encode_object (PlaygroundLogger.PlaygroundObjectWriter)<A>(A, Swift.String) -> () + 1480

        frame #16: 0x000000010ec4d96f PlaygroundLogger`playground_log + 319

        frame #17: 0x00000001105040fe

     



     


    Par contre si je mets


    var res = Int.min

    Là  il est encore en train de calculer, à  cette allure ça va prendre plusieurs minutes !

  • AliGatorAliGator Membre, Modérateur
    L'erreur "can't unwrap optional None" me paraà®t claire (je vous ce qu'elle veut dire en elle-même) mais je vois pas pourquoi tu l'aurais vu ton code, vu que tu n'as aucun optional dans ledit code.


    À moins d'avoir tapé le code un peu vite, d'avoir laissé trainé un '?' de trop que tu as depuis supprimé, sur que le compilo JIT de playground n'a pas fini et en est encore à  l'ancien code et pas le nouveau (je trouve playground lent du moins sur 10.9 et souvent il met un petit temps avant de prendre en compte mon nouveau code et faire sauter les erreurs qu'il avait trouvé quand j'avais tapé des c*nneries juste avant)
  • AliGatorAliGator Membre, Modérateur
    PS : au passage pour créer une date en Swift d'après les conventions de conversion auto d'API ObjC vers Swift décrites dans le guide sur le site d'Apple, c'est directement NSDate() et pas NSDate.date().


    Non de plus NSDate est loin d'être le meilleur moyen et la meilleure méthode à  exécuter pour faire un benchmark mais bon.
  • nolivnoliv Membre

    Testé sur ma machine dans un projet d'app ligne de commande (pour ne pas avoir la lenteur du playground, et je remarque un détail amusant :



    let date_debut = NSDate()
    var count = 0

    for i in 0..10000000 {
    count++
    }

    println("\(-date_debut.timeIntervalSinceNow)")

    Exécution : 5,5 secondes



    let date_debut = NSDate()
    var count = 0

    do {
    count++
    } while count < 10000000

    println("\(-date_debut.timeIntervalSinceNow)")

    Exécution : 0,22 secondes !!!


     


    En objective-C, c'est dix fois plus rapide avec un temps d'exécution de 0,022 secondes.


     


    Je suis sous 10.9


     


    Histoires d'optimisations... faut-il penser que le langage sera plus lent dans certains cas répandus ou qu'avec son lot d'optimisations à  venir il sera comme annoncé par Apple vraiment plus rapide pour nos apps ?


  • AliGatorAliGator Membre, Modérateur
    Et si tu écris "for _ in 0..10000000" en remplaçant le i par _ pour mentionner à  Swift que tu t'en fous de la variable i ?
  • nolivnoliv Membre

    ça reste lent... ça vient peut-être de la syntaxe 1..1000 qui génère un array ?


  • AliGatorAliGator Membre, Modérateur
    c'est très possible en effet.
  • MalaMala Membre, Modérateur
    juin 2014 modifié #10


    Tu testes ça où? Si c'est dans playground ça m'étonne pas c'est à  cause du JIT.




    Non, je suis en compilé avec la Beta sous 10.9.


     


    J'ai utilisé NSDate car je n'ai pas encore d'autres repères avec Swift mais ça change pas le problème. Là  c'est clairement pas la latence de NSDate qui est dans le lac.


  • MalaMala Membre, Modérateur


    Testé sur ma machine dans un projet d'app ligne de commande (pour ne pas avoir la lenteur du playground, et je remarque un détail amusant :



    let date_debut = NSDate()
    var count = 0

    for i in 0..10000000 {
    count++
    }

    println("\(-date_debut.timeIntervalSinceNow)")

    Exécution : 5,5 secondes



    let date_debut = NSDate()
    var count = 0

    do {
    count++
    } while count < 10000000

    println("\(-date_debut.timeIntervalSinceNow)")

    Exécution : 0,22 secondes !!!


     


    En objective-C, c'est dix fois plus rapide avec un temps d'exécution de 0,022 secondes.


     


    Je suis sous 10.9


     


    Histoires d'optimisations... faut-il penser que le langage sera plus lent dans certains cas répandus ou qu'avec son lot d'optimisations à  venir il sera comme annoncé par Apple vraiment plus rapide pour nos apps ?




    Effectivement, il y a du mieux avec une boucle while mais c'est pas encore ça.

  • @Mala et ça donne quoi finalement par rapport à  Objective C ? ( en release)


  • MalaMala Membre, Modérateur
    juin 2014 modifié #13

    Oh putain passez votre Scheme en release.


     


    J'ai l'impression que tant qu'on est en Debug on est pas en compilé.


     


    Voilà  qui me rassure.


     


    Edit: désolé, je reposte après toi Samir. Je pensais avoir fait une fausse manip.


  • MalaMala Membre, Modérateur
    juin 2014 modifié #14


    @Mala et ça donne quoi finalement par rapport à  Objective C ? ( en release)




    Alors chez moi en Obj-C:

    - Boucle for avec variable int: 0.000003s

    - Boucle for avec NSNumber (je sais on le fait jamais mais bon c'est histoire de comparer des manip d'objets): 0.168708s

     

    Et maintenant avec Swift:

    - For .. in: 0.01093s

    - Do while: 0.00717s

  • MalaMala Membre, Modérateur
    juin 2014 modifié #15

    Pour répondre à  ma question de départ:


    https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html


     


    Mais le passage de res en...


    var res:CUnsignedInt = 0

    Ne change pas la donne. Les perfs sont identiques à  priori.


  • Même si Apple a tendance à  enjoliver un peu tout ce qu'ils disent, il ne me semble pas qu'ils mentent ouvertement et en conscience... donc ce serait bien de creuser un peu en cherchant les situations dans lesquelles swift est plus performant que l'objective-c !


  • C'est une bêta, n'oubliez pas !
  • MalaMala Membre, Modérateur
    juin 2014 modifié #19

    J'ai pas souvent vu des release candidates qui me fasse faire "Wooah, la vache! Sacrée différence!!!". Donc oui, c'est une Beta mais le fondement du langage est encré (4 ans de devs) donc je doute qu'on ait droit à  une réelle évolution de ce côté là .


     


    J'ai bien peur qu'Apple nous vende du rêve comme d'hab. Mais bon Wait & See...


  • MalaMala Membre, Modérateur
    juin 2014 modifié #20


    Il ne me semble pas qu'ils mentent ouvertement et en conscience...




    Il n'ont qu'à  mettre à  dispo le code illustrant les chiffres qu'ils annoncent à  la keynote... ;)


     


  • @Mala y a un détail auquel tu n'a pas fais attention :) : le titre du screen shot que tu viens de poster -->" Complex object sort".


     


    Si t'a le temps tu peux tester pas avec une boucle mais avec le tri des objets complexes. 


  • MalaMala Membre, Modérateur

    "Complex object sort" c'est tellement vague que ça peut être à  peu près n'importe quoi.


  • AliGatorAliGator Membre, Modérateur
    Ouais mais au moins la base de travail sera déjà  plus proche de celle qu'ils ont utilisés.

    Une petite classe bidon avec 3 ou 4 propriétés, un tri utilisant un block en ObjC pour définir la comparaison objet par objet, qui se base sur 2 ou 3 de ces propriétés pour déterminer qui est avant et qui est après, et la closure équivalent en Swift, compiler le tout dans une app en Release, et on aura peut-être une petite idée.
  • En me créant une classe comportant trois propriétés (des entiers), dans lesquels je mets des nombres aléatoires à  l'initialisation et que je classe par la moyenne calculée des trois nombres... c'est encore et toujours environ dix fois plus lent en Swift qu'en Objective-C (4 secondes pour trier cent-mille de ces objets). Optimisations de compilation maximales.


     


    Bref, pour moi, j'attends un peu de voir... pour l'instant ce n'est pas le côté performances qui a quoi que ce soit de spectaculaire.


     


    En tout cas ces petits tests me font apprécier la syntaxe du langage, pourtant j'aime aussi l'Objective-C...


  • Ce matin, deux tweets retiennent mon attention, l'un dit :


     



    @nadavrot :


    #swift performance tip: Add the "@final" attribute before your classes to prevent virtual dispatch of methods.



     


    -> mon test de tri des mes objets gagne ~5% de perfs, mais j'avoue ne pas comprendre les conséquences d'empêcher le "virtual dispatch" des méthodes :D 


     



    @nadavrot :


    #swift performance tip: structs are values and they (almost) never require heap allocation or reference counting. Use structs when possible.

     


    -> la par contre, si je passe mon objet en struct, les performances sont multipliées, j'atteins des performances comparables à  celles de l'objective-C avec 0,48 secondes en swift contre 0,32 secondes en objective-C

  • CéroceCéroce Membre, Modérateur

    Il n'ont qu'à  mettre à  dispo le code illustrant les chiffres qu'ils annoncent à  la keynote... ;)

    Excusez-moi, mais il me semble que les tests que vous effectuez sont aberrants. Parce que typiquement, une application ne passe pas son temps à  compter de 0 à  999999.
    Je ne pense pas que les chiffres fournis à  Apple sont faux, simplement, ils sont représentatifs d'une application typique, avec beaucoup d'objets, beaucoup d'appels de méthodes, et beaucoup de code asynchrone.
  • MalaMala Membre, Modérateur


    Excusez-moi, mais il me semble que les tests que vous effectuez sont aberrants. Parce que typiquement, une application ne passe pas son temps à  compter de 0 à  999999.

    Je ne pense pas que les chiffres fournis à  Apple sont faux, simplement, ils sont représentatifs d'une application typique, avec beaucoup d'objets, beaucoup d'appels de méthodes, et beaucoup de code asynchrone.




    On a dérivé mais ce n'était pas ma question de départ. Je voulais pouvoir taper sur des typages de base pour justement jouer avec des pixels d'une NSBitmapImageRep. Donc pour me faire les dents en attendant sur la syntaxe, je me suis amusé avec une  boucle à  2 balles. Mais force est de constater qu'il y a bien un loup jusqu'à  preuve du contraire.


     


    Je demande qu'à  voir le code d'Apple. J'ai déjà  été sacrément refroidi à  de nombreuses reprises sur des technos comme Core Image et j'en passe où Apple nous annonçait mondes et merveilles au niveau perfs. Maintenant, comme beaucoup, je suis devenu comme Saint Thomas...

  • muqaddarmuqaddar Administrateur


    mondes et merveilles au niveau perfs




     


    Ce n'est pas plutôt "Monts et merveilles" ? ;)

  • LeChatNoirLeChatNoir Membre, Modérateur

    oé, c'est comme Maverick qui était ultra optimisé et qui plombe toutes les vieilles machines...


  • CéroceCéroce Membre, Modérateur
    juin 2014 modifié #30

    Mais force est de constater qu'il y a bien un loup jusqu'à  preuve du contraire.

    Je suis d'accord pour dire que pour l'instant dire que " Swift est plus rapide qu'Obj-C " n'est qu'un discours marketing " tant qu'on n'a pas de détails sur le mode de benchmarking. ça dépendra des applications... et nous continuerons à  programmer en C pour certains algo critiques.
  • ERRATUM !


     


    Houla les gars, bonne nouvelle... j'ai fait une petite erreur: dans Xcode, en utilisant swift, il y a maintenant deux endroits où on peut configurer le niveau d'optimisation du compilateur.


     


    Je faisais mes test en configurant correctement "Optimization Level" dans la rubrique "Apple LLVM 6.0 - Code Generation" mais il y a aussi une nouvelle rubrique "Swift Compliler - Code generation" dans laquelle on peut passer de "Fastest [-O]" à  "Fastest, Unchecked [-Ofast]"... je ne l'avais pas vue dans mes tests précédents.


     


    En choisissant ici le niveau le plus rapide, j'obtiens des résultats bien meilleurs.


    Mon tri qui prenait je le rappelle 0.3 s en Objective-C et 0.48 s en Swift en utilisant une struct à  la place d'une class prend maintenant 0.066 s en Swift ! (Mais toujours en utilisant des struct... si je repasse à  une classe, mon tri prend 0.85 s)


     


    ça devient difficile de comparer, parce qu'on pourrait se passer des objets coté Objective-C aussi pour améliorer les résultats mais en terme de facilité d'écriture du code et de souplesse des éléments à  manipuler, les structures en Swift semblent vraiment meilleures. Elles sont d'ailleurs bien plus sollicitées qu'en Objective-C... ils en parlent beaucoup dans les démos et la doc.


     


    Bref, les premiers résultats décevants de Mala ont donné envie de vérifier ce qu'a prétendu Apple pendant la keynote mais force est de constater que c'était un peu trop dans la précipitation.

Connectez-vous ou Inscrivez-vous pour répondre.