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 :

Performance manipulation byte[]


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut Performance manipulation byte[]
    Bonjour à tous,

    j'aurais voulu savoir comment améliorer les performances du code suivant :

    Code C# : 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
            public Byte[] Combine(params Byte[][] Arrays)
            {
                Byte[] Result = new Byte[Arrays.Sum(a => a.Length)];
                Int32 Offset = 0;
                foreach (Byte[] Array in Arrays)
                {
                    System.Buffer.BlockCopy(Array, 0, Result, Offset, Array.Length);
                    Offset += Array.Length;
                }
                return (Result);
            }
     
            public void Append(Byte[] Buffer)
            {
     
                if (this.Buffer == null)
                    this.Buffer = Buffer;
                else
                    this.Buffer = this.Combine(this.Buffer, Buffer);
            }
            public Packet TryParseBuffer(ref Int32 Length)
            {
                if (this.Buffer == null)
                    return (null);
                if (this.Buffer.Length < 4)
                    return (null);
                Int32 Size = BitConverter.ToInt32(this.Buffer, 0);
                Length = Size;
                if (this.Buffer.Length < Size + 4)
                    return (null);
                Byte[] Content = (new MemoryStream(this.Buffer, 4, Size)).ToArray();
                Packet Packet = Packet.Deserialize(Content);
                if (this.Buffer.Length == Size + 4)
                    this.Buffer = null;
                else
                    this.Buffer = (new MemoryStream(this.Buffer, Size + 4, this.Buffer.Length - 4 - Size)).ToArray();
                return (Packet);
            }

    C'est une application réseau, le flux en réseau local est tellement important que le buffer grandit de plus en plus ... jusqu'à qu'il y ai une OutOfMemoryException.

    Merci d'avance

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par NeoKript Voir le message
    C'est une application réseau, le flux en réseau local est tellement important que le buffer grandit de plus en plus ... jusqu'à qu'il y ai une OutOfMemoryException.
    Dans ce cas il n'y a pas grand chose à faire pour optimiser ce code, il faut revoir complètement le principe... Visiblement le volume de données est trop important pour pouvoir le manipuler entièrement en mémoire. Est-ce que tu ne pourrais pas le traiter morceau par morceau, et écrire sur le flux réseau au fur et à mesure que tu traites les données ? (ou traiter les données au fur et à mesure que tu les reçois, si c'est dans ce sens là que ça se passe)

  3. #3
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Je n'ai pas de lien vers un tutorial, mais tu sembles avoir besoin d'une architecture multi-threadée avec un thread fournisseur et un thread consommateur.

    => Le fournisseur est le thread qui s'occupe de récupérer le flux réseau
    => Le consommateur est celui qui récupére les données et les transforme

    Si au niveau du consommateur tu as aussi un goulot d'étranglement, tu paux rajouter un thread entre les deux de transformation.

    Par exemple :
    - Fournisseur = interface réseau
    - Transformeur = compression des données sous forme d'un flux vidéo
    - Consommateur = écruture du flux vidéo sur le disque

    Ainsi, tu travailles avec plusieurs buffers de petites tailles :
    Le fournisseur rempli son buffer, et se met en attente lorsque le buffer dépasse un certain seuil, et ne redémarre que lorsqu'il est en dessous d'un certain seuil.
    Le transformeur lit dans le buffer du fournisseur, et se met en attente lorsque le buffer est vide. Il rempli un buffer de sortie, et se met en attente lorsqu'il dépasse un certain seuil, et redémarre lorsqu'il descent en dessous d'un certain seuil.
    Le consommateur récupère les données dans le buffer de sortie du transformateur, et se met en attente lorsque le buffer est vide.

    Tu obtiendras ainsi les meilleures performances possible pour faire un traitement donc les limitations de vitesse peuvent venir de l'encombrement réseau, de la charge CPU ou de l'encombrement des IO disque, le tout de façon dynamique.

    Ce n'est pas très compliqué à mettre en place, et c'est un très bon exercice pour découvrir le multi-thread.

    J'avais mis ça en place il y a quelques temps pour encrypter des données à la volée depuis un disque avec un algo proprio (basé sur hufmann à l'envers, afin de générer en sortie un code le plus aléatoire possible). Ça marchait fichtrement bien.
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Points : 460
    Points
    460
    Par défaut
    Bonjour,

    Outch, mais diable qui a bien pu écrire un truc pareil.
    D'abord les tableaux multidimensionnel c'est lent en .net, ensuite mais pourquoi faire une méthode à argument variable si c'est le même type à chaque fois. Un simple énumérable aurait suffit.

    Par contre, concernant ton problème d'exception, es-tu sur que le problème soit du a la place occupé par ton buffer, ou n'est ce pas plutôt parce que tu réclame un tableau encore plus grand?

    - Dans le premier cas, la cause peut être dû au traitement du buffer, qui serait devenu trop lent par rapport à ton nouveau volume/débit de données.

    - Dans le deuxième cas, la cause peut être la combinaisons des buffer. Alors là on peut faire plusieur chose. Soit récrire la combinaison. Soit se passer de combinaison, en utilisant un container de tableau qui sera capable de faire correctement le parcours.

    Edit:
    Au passage je l'avais pas vu a la premiere lecture, mais t'as une belle memory leak. Car les "MemoryStream" ne sont pas fermés

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut
    Bonjour à tous et merci pour vos réponses,

    J'ai refais l'architecture du serveur comme l'avais décris StringBuilder et j'ai transmis les paquets au fur et à mesure (c'était ça le principale problème). J'utilisais les socket asynchrone BeginSend et les problèmes de mémoires venais d'ici la pile d'envoi devenais trop importante d'où le OutOfMemoryException. Maintenant, j’envoie les paquets de manière synchrone (pas de perte de performance) et la consommation mémoire ne dépasse pas les 10ko.

    Merci encore pour vos conseils.

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

Discussions similaires

  1. Manipulation de byte, je ne comprend pas
    Par Djobird dans le forum Général Java
    Réponses: 2
    Dernier message: 23/04/2009, 20h01
  2. manipuler un pdf en byte en utildant itext
    Par yazen dans le forum Documents
    Réponses: 0
    Dernier message: 27/10/2008, 11h20
  3. manipulation de bits d'un byte
    Par orelero dans le forum Langage
    Réponses: 6
    Dernier message: 22/08/2008, 10h41
  4. manipulation de Byte, bit et int
    Par Edta dans le forum Langage
    Réponses: 14
    Dernier message: 04/06/2008, 03h50
  5. Ca doit etre la surchauffe: manipuler des byte
    Par TheCaribouX dans le forum C#
    Réponses: 12
    Dernier message: 09/04/2008, 11h37

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