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 :

Eviter les memcpy


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut Eviter les memcpy
    Bonjour,
    j'ai lu que l'utilisation des memcpy pour des données inferieures à 8 octets etaient pas top.

    je souhaiterais donc changer mes lignes de copie de memoire qui sont sur 2 et 4 octets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy(start_msg + msg_len, &protocol_version, sizeof(uint32_t));
    comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    uint32_t len = sizeof(uint32_t);
    while (--len > 0)
    {
    *(start_msg + len + msg_len) = *(protocol_version + len);
    }
    Cette syntaxe est elle bonne et à votre avis y en a t'il une meilleure ?
    Merci d'avance ?

  2. #2
    Membre très actif

    Inscrit en
    Juillet 2008
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 186
    Par défaut
    Bonjour,

    AMHA, avant de vouloir remplacer une ligne de code très parlante par cinq lignes pour lesquelles il faut réfléchir avant de comprendre ce qu'elles font, il faudrait mesurer. Oui, mesurer si appeler memcpy fait vraiment perdre du temps.

    Les compilateurs de nos jours sont suffisemment bien foutus pour optimiser tout seuls ces fonctions de base comme memcpy.

    La meilleure syntaxe, c'est celle qui se lit facilement et qui ne demande pas à réfléchir pour comprendre ce qui se passe.

    Didier

  3. #3
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Par défaut
    en effet, il vaut mieux faire des tests avant !

    les implémentations de memcpy diffèrent selon les compilos et les architectures. Généralement codées en assembleur, les différentes version peuvent utiliser des instructions SS2 sous Inte. De plus au sein des implémentations des distinctions sont faites en fonction de la taille et des scénarios différents sont alors appliqués. Etc....

    Donc, avant de vouloir faire mieux que le compilo ou le processeur, soit sur que c'est justifié et que ca vaut le coup.

    Faits donc des tests et tu pourra en juger par toi même
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  4. #4
    Membre émérite Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Par défaut
    Et au pire tu peux créer une fonction my_memcpy dans laquelle tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    void *my_memcpy(void *dest, const void *src, size_t n)
    {
      if(n <=sizeof(uint32_t))
      {
        while (--n >= 0)  /* <- tu as oublie le 'egal' */
        {
          *((uint8_t *)dest + n) = *((uint8_t *)src + n);
        }
      else
      {
        memcpy(dest, src, n);
      }
    }
    Mais il y a quand même toutes les chances pour que le codeur de la fonction memcpy pour ta cible ait déjà pensé à cela.

    Attention dans ton exemple tu as oublié le égal dans la boucle et il faut que les deux pointeurs start_message et &protocol_version soient des pointeurs sur un octet.

  5. #5
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut
    Je suis plutot d'accord avec vous au niveau de l'optimisation du compilateur, mais bon, mise a part que j'ai vu qu'il etais preferable d'eviter des copies des memcpy pour <8 octets, mon chef de projet ne veut pas de memcpy dans mon code.

    @valefor : effectivement pour le cast mais on aurais pu mettre aussi (char *)

    J'ai modifié mon code comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int cpy_len = sizeof(uint32_t);
     
    uint32_t protocol_version = htonl(sql_conn->pversion);
    		while (--cpy_len >= 0)
    		{
    			*((uint32_t *)start_msg + cpy_len) = *((uint32_t *)&protocol_version + cpy_len);
    		}
    et ca fonctionne nickel

  6. #6
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut
    J'ai ajouté une fonction dans mon code pour remplacer tous les memcpy, comme me l'a conseillé valefor :

    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
    void
    sql_copy_data ( void * dest, void * src, int n )
    {
    	if (n <= sizeof(uint32_t))
    	{
    		while (--n >= 0)
    		{
    			*((char *)dest + n) = *((char *)src + n);
    		}
    	}
    	else
    	{
    		memcpy(dest, src, n);
    	}
    }

Discussions similaires

  1. Eviter les warnings "unused parameter"
    Par Le Furet dans le forum C
    Réponses: 9
    Dernier message: 03/10/2005, 22h29
  2. Eviter les doublons
    Par cyrill.gremaud dans le forum ASP
    Réponses: 5
    Dernier message: 14/09/2005, 12h37
  3. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  4. [langage] 2 fichier dans 1 en evitant les doublons
    Par remixxl dans le forum Langage
    Réponses: 6
    Dernier message: 26/07/2004, 17h05
  5. [C#] Comment eviter les boucles infinies ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 12
    Dernier message: 09/06/2004, 00h04

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