IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Dans une fonction pour la rapidité/performance : struct ou déclaration de variable ?


Sujet :

C

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut Dans une fonction pour la rapidité/performance : struct ou déclaration de variable ?
    Bonjour, dans mon jeu toute les 20 millisecondes je dois faire les tests de collisions ; ma question est la suivante : pour plus de performance est-ce qu'il est préférable de créer une struct OffSet par exemple ou je déclare une fois pour toutes mes variables ou bien est-ce qu'il est préférable de recrée toutes les 20 millisecondes mes variables dans mes différente fonctions ?

    Est-ce mieux de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    typedef struct OffSet
    {
    int XMin1;
    int XMax1;
    int YMin1;
    int YMax1;
    int XMin2;
    int XMax2;
    int YMin2;
    int YMax2;
    int vx, vy;
    }OffSet;
     
    ../..
     
     
    void move_ball(Sprites* S,dataImageScr* D,Clash_SplitScr* CS,InitSdl *A,OffSet* O)
    {
      int i=0;
     
      O->XMin2=D->ship.x;
      O->XMax2=D->ship.x+S->ShipW;
      O->YMin2=D->ship.y;
      O->YMax2=D->ship.y+S->ShipH;
     
      for(i=0;i<D->NbBallScr;i++)
        {
          O->XMin1=D->ball[i]->x;
          O->YMin1=D->ball[i]->y;
          O->XMax1=D->ball[i]->x+S->BallW;
          O->YMax1=D->ball[i]->y+S->BallH;
          O->vx=D->ball[i]->vx;
          O->vy=D->ball[i]->vy;
     
          D->ball[i]->x += O->vx;
          D->ball[i]->y += O->vy;
     
          clash_splitScr(O->XMin1,O->XMax1,O->YMin1,O->YMax1,CS,i); 
          clash_ballEdgesScr(S,D,A,i);
     
          clash_ShipBall(O->XMin1, O->XMax1, O->YMax1,
    			    O->XMin2, O->XMax2, O->YMin2, O->YMax2,
    			    O->vx, O->vy,i,S,D);
    	}
        }
    Ou bien la 2eme solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void move_ball(Sprites* S,dataImageScr* D,Clash_SplitScr* CS,InitSdl *A)
    {
      int i=0;
     
      int vx, vy;
      int XMin1,YMin1,XMax1,YMax1;
     
      int XMin2=D->ship.x;
      int XMax2=D->ship.x+S->ShipW;
      int YMin2=D->ship.y;
      int YMax2=D->ship.y+S->ShipH;
     
      for(i=0;i<D->NbBallScr;i++)
        {
          XMin1=D->ball[i]->x;
          YMin1=D->ball[i]->y;
          XMax1=D->ball[i]->x+S->BallW;
          YMax1=D->ball[i]->y+S->BallH;
          vx=D->ball[i]->vx;
          vy=D->ball[i]->vy;
     
          D->ball[i]->x += vx;
          D->ball[i]->y += vy;
     
          clash_splitScr(XMin1,XMax1,YMin1,YMax1,CS,i);
          clash_ballEdgesScr(S,D,A,i);
     
          clash_ShipBall(XMin1,XMax1,YMax1,
    			   XMin2,XMax2,YMin2,YMax2,
    			   vx,vy,i,S,D);
    	}
        }

  2. #2
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Je vois un avantage probable de la deuxième version sur la première : un paramètre en moins à placer sur la pile d'appels et des indirections en moins.

    Je ne vois a priori pas d'avantage de la première version sur la deuxième.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    C'est sûrement une non-optimisation , mais peut-être un truc comme cela

    L'idée c'est de supprimer à la fois la création (cacahuètes pour des entiers), les déférencements (lorsqu'ils sont dans une structure) et le test NULL de ta structure (même si tu peux [quasi] le supprimer [totalement])


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // Inside XXX.c
     
    // Globals
     
    static int XMin1;
    static int XMax1;
    static int YMin1;
    static int YMax1;
    static int XMin2;
    static int XMax2;
    static int YMin2;
    static int YMax2;
    static int vx, vy;
     
     
    // Functions
     
    void move_ball(Sprites* S,dataImageScr* D,Clash_SplitScr* CS,InitSdl* A) {
      int i;
     
      XMin2=D->ship.x;
      XMax2=D->ship.x+S->ShipW;
      YMin2=D->ship.y;
      YMax2=D->ship.y+S->ShipH;
     
      for(i=0;i<D->NbBallScr;i++) {
          XMin1=D->ball[i]->x;
          YMin1=D->ball[i]->y;
          XMax1=D->ball[i]->x+S->BallW;
          YMax1=D->ball[i]->y+S->BallH;
          vx=D->ball[i]->vx;
          vy=D->ball[i]->vy;
     
          D->ball[i]->x += vx;
          D->ball[i]->y += vy;
     
          clash_splitScr(XMin1,XMax1,YMin1,YMax1,CS,i);
          clash_ballEdgesScr(S,D,A,i);
     
          clash_ShipBall(XMin1,XMax1,YMax1,
    			   XMin2,XMax2,YMin2,YMax2,
    			   vx,vy,i,S,D);
      }
    }

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour vos réponses

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    L'idée c'est de supprimer à la fois la création (cacahuètes pour des entiers), les déférencements (lorsqu'ils sont dans une structure) et le test NULL de ta structure (même si tu peux [quasi] le supprimer [totalement])


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // Inside XXX.c
     
    // Globals
     
    static int XMin1;
    static int XMax1;
    static int YMin1;
    static int YMax1;
    static int XMin2;
    static int XMax2;
    static int YMin2;
    static int YMax2;
    static int vx, vy;
     
     
    // Functions
     
    void move_ball(Sprites* S,dataImageScr* D,Clash_SplitScr* CS,InitSdl* A) {
    ...  }
    }
    Bonjour

    Et si tu mettais alors tes statiques directement dans la fonction ??? Elles ne seraient là aussi créées qu'une seule fois et éviteraient de devenir ces globales autant perturbatrices intellectuellement que génératrices de bug à plus ou moins moyen terme...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Donc si je comprends bien le faite de mettre devant un int (par exemple) le mot static le int n'est pas détruit a la fin de la fonction ce qui évitera à chaque appel de la fonction de recréer une variable de type int et de faire perdre du temps au programme pour recréer ce int.

    C'est un peu la même chose que de faire un passage par pointeur.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par hbx360 Voir le message
    Donc si je comprends bien le faite de mettre devant un int (par exemple) le mot static le int n'est pas détruit a la fin de la fonction ce qui évitera à chaque appel de la fonction de recréer une variable de type int et de faire perdre du temps au programme pour recréer ce int.
    Exact. On s'en sert quand on veut que la fonction se "souvienne" de son état précédent quand elle est rappelée (typique: la fonction strtok qu'on appelle autant de fois qu'il y a de tokens à extraire d'une chaine et qui, à chaque appel, se souvient de sa position dans la chaine pour repartir de là).
    Le principal inconvénient de ce mécanisme est qu'il n'est pas "réentrant" (on ne peut pas le déployer en parallèle sur n opérations distinctes car il n'y a qu'une seule variable en mémoire et donc les n appels qui devraient être indépendants écrasent la même zone => collision).
    Donc généralement on s'oriente de plus en plus à supprimer ce type de mécanisme et à le remplacer par des fonctions où il faut leur fournir nous même la zone de mémoire (n appels distincts => n zones distinctes mais c'est l'utiliisateur qui les gère). Exemple strtok_r() ("r" pour "réentrant")...

    Citation Envoyé par hbx360 Voir le message
    C'est un peu la même chose que de faire un passage par pointeur.
    Pas tout à fait. Passer une adresse signifie que la fonction a besoin de cette adresse (qu'elle stockera effectivement dans un pointeur) qui lui est, au départ, inconnue.
    Alors que dans le mécanisme ci-dessus, tu utilises tes variables comme des variables classiques (la fonction n'a pas besoin d'info externe pour savoir quoi leur mettre) sauf que ces variables restent en mémoire...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci beaucoup pour la confirmation et les explications

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    La seule bonne réponse sera donnée par une comparaison des codes assembleur obtenus par le compilateur.

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Ok merci pour ta réponse

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Et si tu mettais alors tes statiques directement dans la fonction ??? Elles ne seraient là aussi créées qu'une seule fois et éviteraient de devenir ces globales autant perturbatrices intellectuellement que génératrices de bug à plus ou moins moyen terme...
    En mettant static le périmètre est réduit ("file scope"): ces variables ne sont pas visibles de l'extérieur avec extern.

    Donc, à l'intérieur de la fonction ou en global, cela dépend plus du (des) programmeur(s) et de l'usage qui en ai fait.

    Mais j'aurais tendance à les mettre en global parce que ce sont des variables qui ne servent qu'à contenir des valeurs temporaires/ intermédiaires et donc réutilisables ailleurs.

    Mais c'est vrai que si les static ou autres n'apportent rien en performance ou alors le contexte ne le permet pas (multi-threadé comme tu l'as évoqué), le mieux c'est de les mettre en local


    Citation Envoyé par hbx360 Voir le message
    'est un peu la même chose que de faire un passage par pointeur.
    Avec le passage par pointeur tu as:
    • un élément de plus sur la pile d'appels: réponse de CodeurPlusPlus
    • le test NULL pour savoir si ton pointeur est valide. À moins que tu sois sûr.
    • un déférencement à chaque utilisation, même si c'est cacahuète

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour la réponse je pense que je vais déclarer des int simplement sans statique puisque sa change rien au niveau performance donc faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void move_ball(Sprites* S,dataImageScr* D,Clash_SplitScr* CS,InitSdl *A)
    {
      int i=0;
     
      int vx, vy;
      int XMin1,YMin1,XMax1,YMax1;
     
      int XMin2=D->ship.x;
      int XMax2=D->ship.x+S->ShipW;
      int YMin2=D->ship.y;
      int YMax2=D->ship.y+S->ShipH;
     
      for(i=0;i<D->NbBallScr;i++)
        {
          XMin1=D->ball[i]->x;
          YMin1=D->ball[i]->y;
          XMax1=D->ball[i]->x+S->BallW;
          YMax1=D->ball[i]->y+S->BallH;
          vx=D->ball[i]->vx;
          vy=D->ball[i]->vy;
     
          D->ball[i]->x += vx;
          D->ball[i]->y += vy;
     
          clash_splitScr(XMin1,XMax1,YMin1,YMax1,CS,i);
          clash_ballEdgesScr(S,D,A,i);
     
          clash_ShipBall(XMin1,XMax1,YMax1,
    			   XMin2,XMax2,YMin2,YMax2,
    			   vx,vy,i,S,D);
    	}
        }

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    En mettant static le périmètre est réduit ("file scope"): ces variables ne sont pas visibles de l'extérieur avec extern.

    Donc, à l'intérieur de la fonction ou en global, cela dépend plus du (des) programmeur(s) et de l'usage qui en ai fait.
    Il y a static à une fonction, cest-à-dire visible uniquement à l'intérieur de la fonction, ou static au fichier. C'est un mauvais abus de langage d'appler "globales" (ce qui veut dire visible de partout) des variables qui sont statiques à un fichier (et donc visible uniqument dans ce fichier).

    Mais j'aurais tendance à les mettre en global parce que ce sont des variables qui ne servent qu'à contenir des valeurs temporaires/ intermédiaires et donc réutilisables ailleurs.

    Mais c'est vrai que si les static ou autres n'apportent rien en performance ou alors le contexte ne le permet pas (multi-threadé comme tu l'as évoqué), le mieux c'est de les mettre en local
    C'est du grand n'importe quoi : on mets en statique au fichier ce qui doit être partagé entre les fonctions !!! C'est quoi cette histoire de réutilisable ? Si tu as besoin d'un int dans 3 fonction, tu le mets static au fichier ? Si c'est temporaire, intermédiaire, c'est par essence même à cacher à l'intérieur d'une fonction et surtout pas à donner accès aux autres. Il se passe quoi en contexte multithread si tu partages tes variables temporaires !? Tu le dis juste derrièr en plus : pourquoi faire n'importe quoi en mono thread et pleurer le jour de l'utilisation en multi thread ? Toutes les variables devraient être définies de manière à avoir la visibilité la plus faible. Static à la fontion, static au fichier, globale ne sont que les stades les plus éloignés de cette règle et ne devraient être utilisés que si besoin. Le besoin de performances n'est pas une bonne raison et doit être justifié par des benchmarks et utilisé en dernier recours.

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour tes précisions

  15. #15
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Premature optimization totale.. code un système propre, qui fonctionne et fais confiance à ton compilateur pour le reste.

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour ta réponse.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. sizeof dans une fonction pour lire une chaine
    Par Haze. dans le forum Débuter
    Réponses: 11
    Dernier message: 06/11/2007, 12h07
  2. Réponses: 1
    Dernier message: 08/09/2007, 17h12
  3. Réponses: 2
    Dernier message: 29/08/2007, 19h43
  4. Réponses: 3
    Dernier message: 03/08/2007, 07h36
  5. Réponses: 3
    Dernier message: 14/04/2006, 19h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo