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 :

Optimisation d'ajout dans un fichier à un emplacement aléatoire


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 16
    Points : 4
    Points
    4
    Par défaut Optimisation d'ajout dans un fichier à un emplacement aléatoire
    Bonjour à tous,
    Tout d'abord je vous explique mon projet:
    Mon but est de lister une arborescence (fait) puis ensuite de choisir un fichier aléatoire dans cette arborescence (fait) puis de modifier ce fichier en rajoutant à l'intérieur un binaire n'importe où (fait).
    Mon but est ensuite de choisir au lancement du programme, un taux de modification de l'arborescence, et ensuite le modifier les fichiers (avec un taux de 1/100 de modification par fichier) jusqu'à ce que mon arborescence est le taux de modification choisi.

    Le problème est que c'est extrêmement long (plus de 9h pour une arborescence de 60Go environ(3Go à rajouter pour un taux de 5%)).

    Je dois insérer le binaire n'importe où dans mon code, voici comment je procède. (j'utilise fstream).
    Pour commencer je choisi mon l'emplacement où je vais rajouter mon binaire aléatoirement (rand)
    Fichier d'origine = X
    Nouveau fichier = Y
    Ensuite je copie tout le début de mon fichier(X) jusqu'à l'emplacement dans un second fichier(Y) (j'explique après pourquoi je fais comme ca) puis je rajoute mon binaire dans Y et ensuite je rajoute à la suite de mon binaire le reste du fichier X dans le nouveau fichier Y. Ensuite je supprime le fichier d'origine (X) et renomme le nouveau fichier (Y) en (X) pour remplacer le fichier d'origine(X).
    Je procède de la sorte étant donné que si je rajoute mon binaire directement dans le fichier d'origine, cela va me supprimer la suite, où du moins me supprimer une partie de mon fichier (je me trompe peut être mais c'est ce que j'ai aperçu en essayant). J'ai essayer faire en sorte de sauvegarder la suite de mon fichier dans une variable pour ensuite la rajouter a la suite de mon binaire dans le même fichier mais j'avais des problème avec les gros fichiers (36Go) qui dépassaient la taille du buffer.

    Pour un fichier de 1Go seul, la modification prend environ 40s
    Pour les petits fichiers c'est très rapide. (mais 1% par petit fichier c'est très peu donc ca met quand même énormément de temps pour remplir les 3Go total de modification)

    Voila, j'aimerais avoir votre avis sur comment je pourrais améliorer cela, ou modifier certaines choses.

    Merci d'avance pour votre aide.
    PS: ceci est mon premier programme en c++ donc je suis près a prendre les critiques constructives.

    Voici le code pour la modif d'un fichier:
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    void  modifFic(istream& monFlux, off_t tailleAjout, const string& cheminFic){
     
            string extension="copietemp";
            char caractere;
            off_t lengthF,n;
     
            unsigned int tailleRandom = 10000000; //Segmentation fault et bus error au dessus de 10m
     
            string newFic = cheminFic + extension;
     
            lengthF = tailleFic(monFlux);
            monFlux.clear(); // on remet les 4 flags de fstream a leur etat d'origine
            monFlux.seekg(0, ios::beg); // on se replace au début
     
            //On choisit l'endroit où placer notre binaire
            if(lengthF != 0)
                    n=rand()%lengthF;
            else
                    n=0;
     
            ofstream newFluxCopie (newFic.c_str(), ios::out | ios::ate | ios::binary);
            if(newFluxCopie){
                    //On copie tout ce qu'il y a jusqu'à n dans notre nouveau fichier
                    int i=0;
                    string ligne;
                    do{
                            getline(monFlux,ligne);
                            newFluxCopie << ligne << endl;
                            i+=ligne.size();
                    }while(i<n && !monFlux.eof());
                    monFlux.clear();
                    monFlux.seekg(n,ios::beg);
                    newFluxCopie.seekp(n,ios::beg);
                    //On ajoute le binaire
                    do{
                            if(tailleRandom > tailleAjout)
                                    tailleRandom = tailleAjout;
                            char block[tailleRandom];
                            ifstream urandom("/dev/urandom", ios::in|ios::binary);
                            if(urandom)
                                    urandom.read(block,tailleRandom);
                            else
                                    cerr << "Erreur: Impossible d'ouvrir /dev/urandom" << endl;
     
                            for(off_t i=0;i<tailleRandom;i++){
                                    newFluxCopie.write((char*)&block[i],sizeof(char));
                            }
                            tailleAjout -= tailleRandom;
                    }while(tailleAjout != 0);
     
                    //on rajoute la fin de la ligne pour pouvoir inserer ligne par par ligne ensuite
                    do{
                            monFlux.get(caractere);
                            newFluxCopie << caractere;
                    }while(caractere != '\n' && !monFlux.eof());
                    //On remet la fin de notre premier fichier à partir de n dans notre nouveau
                    while(getline(monFlux,ligne)){
                            newFluxCopie << ligne << endl;
                    }
                    newFluxCopie.close();
            }else{
                    cerr << "Erreur: Impossible d'ouvrir" << newFic << endl;
            }
     
            fstream ficLog("resultModif.log", ios::out | ios::app);
            if(ficLog){
     
                    int rtrmv = remove(cheminFic.c_str());
                    if(rtrmv != 0){
                            cerr << "Erreur lors de la suppression de " << cheminFic << endl;
                            ficLog << "Erreur lors de la suppression de " << cheminFic << endl;
                    }else{
                            int rtrnm = rename(newFic.c_str(),cheminFic.c_str());
                            if(rtrnm != 0){
                                    cerr << "Erreur lors du renommage de " << newFic << endl;
                                    ficLog << "Erreur lors du renommage de " << newFic << endl;
                            }
                    }
                    ficLog.close();
     
            }else
                    cerr << "ERREUR: Impossible d'ouvrir Resultmodif.log" << endl;
     
    }

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Bonjour,

    Juste par curiosité ... c'est ton premier projet ? C'est quoi le but recherché, exactement ?

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    normalement, tu peux écrire trivialement au bout du fichier. et c'est rapide

    La question est bien: pourquoi au milieu?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Bonjour,
    Oui premier projet de c++ (c'est si horrible que ca?), le but étant de simuler les mouvements d'une entreprise pour faire des statistiques sur les sauvegardes effectuées (permet de voir combien de block on été modifié et sauvegardé etc..)
    Oui je me doute que l'ajout est plus rapide à la fin du fichier, mais la consigne est d'insérer le binaire de façon aléatoire dans le fichier.

    Si c'est pas clair, je peux réexpliquer plus en profondeur
    Merci.

  5. #5
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Ce genre d'applications étant assez rare, il n'y a rien dans la bibliothèque standard permettant d'insérer des données au milieu d'un fichier.
    Je pense que tu devrais regarder du côté de fstream, seekg et seekp, qui devraient te permettre de modifier directement le fichier au lieu d'en créer une copie.

  6. #6
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Effectivement je n'ai rien trouvé dans la bibliothèque standard. J'avais fait en sorte avant de modifier directement le fichier au lieu de faire une copie, mais le fait est que je devais sauvegarder de n (n étant l'endroit ou j'ajoute mon binaire) jusqu'à la fin du fichier et le réinsérer dans mon fichier après avoir rajouté mon binaire, donc cela fonctionnait bien pour des petits fichiers mais pour les gros fichiers (par exemple 36Go), j'avais des problèmes de mémoire de stack (je pense) pour sauvegarder la fin du fichier (je pense que c'était aussi plus long que avec cette méthode pour les fichiers de quelques Go).

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Cela dit, si tu utilise linux, je pense qu'avec simplement head, tail et cat, tu dois pouvoir faire ca.

    supposons que tu aie le fichier "truc.bin" qui contient le binaire à insérer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    head -c 13K original.fic | cat - truc.bin > nouveau.fic
    tail -c +13K original.fic >> nouveau.fic
    man head
    man tail

    Avec ca, c'est très vite fait, normalement.
    Il suffira de très peu de chose pour en faire un script simple à utiliser.


    Parfois, le bon outil est ailleurs.
    Si tu es sur windows, évidemment, mon avis est moins utile.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Il ouvre /dev/urandom donc oui je pense que c'est du GNU/Linux ...

    Pour les problèmes de mémoire, tu peux y aller "en douceur", allouer un bloc de mémoire de taille fixe et déplacer tout le contenu en faisant une boucle.

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Une astuce simple à tester : met ton fichier de transition (Y) dans /dev/shm (c'est un tmpfs monté en ram). C'est pas encore idéal mais dans un premier temps ça peut améliorer sensiblement tes perfs. Il faut avoir assez de RAM pour les gros fichiers évidemment... Si tu as des fichiers qui font plusieurs dizaines de gigas, ça va être plus compliqué.
    Find me on github

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je présente l'idée de Hound autrement, parce que j'aime bien l'expression d'un de mes profs (il y a longtemps...)

    C'est l'insertion par vague.

    Considère ton fichier comme une suite de blocs de la même taille T.

    Tu veux introduire un bloc dans le fichier, à partir d'une position P0 donnée.
    voila l'algo:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Pars de la position P=P0
    mets ce que tu veux insérer dans un buffer de taille T: écriture
    soit un second buffer de taille T: sauvegarde
     
    tant que P dans le fichier
        copie le bloc en P dans sauvegarde
        copie écritureen P
        copie sauvegarde dans écriture
        augmente P pour être sur le prochain bloc de taille T
    En pratique, pour éviter des copies inutiles, tu échangera simplement les pointeurs sauvegarde et écriture.
    Assure-toi que le dernier bloc est bien conservé

    Cela dit, comme le contenu de tes fichiers est du bruit blanc, autant écrire à la fin.
    Le résultat sera le même: du bruit blanc, de la même taille.
    Certes pas de la même valeur, mais comme elle n'a aucun impact, quelle différence cela fait-il?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  11. #11
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Bonjour,
    Tous d'abord merci pour ces réponses

    Les commandes head et tail me paraisse effectivement très rapide, mais comme je dois faire un programme en c++, je ne vais pas les utiliser, mais merci de m'avoir montré qu'on pouvait faire comme cela (cela me servira surement à l'avenir)

    Ensuite, concernant le code, effectivement, j'ai utilisé le même principe que cp (j'ai regardé avec strace ce qu'il faisait) et donc il fait aussi ce que vous dites, c'est-à-dire la copie par vague. C'est donc c'est ce que j'ai utilisé, et cela est apparemment plus rapide. Je vais tester de lancer pendant la soirée la modification de toute l'arborescence (avec un taux de 5%) pour voir si le temps a grandement diminué.
    Je vous tiendrais au courant de cela demain.
    Merci encore.

    PS: pour la remarque sur l'insertion à la fin, oui j'ai même avis que toi, mais c'est la consigne, je pense qu'ils veulent faire des statistiques sur les blocks sauvegardés et quels endroits ont été sauvegardés etc.. donc ils ne veulent pas que des insertions à la fin.

  12. #12
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Content de voir que ça avance.

    Tiens nous au courant.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  13. #13
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Bonjour,
    J'ai mis un peu de temps a répondre.
    Donc pour le temps avec une arborescence de 70Go (à peu près) cela met encore énormément de temps (cela a mis environ 9h) mais moins qu'avant je pense. Le problème (pour moi) est que tous les fichiers sont modifiés a taux de 1% chacun(c'est la consigne), donc les petits fichiers n'apportent que quelque octet et sur 3Go de modification même si ca va vite, il faut en modifier énormément. Pour l'instant j'ai d'autre projet, donc on a mis celui la "de coté", et on me dira ce que je peux améliorer par la suite.

    Voilà, en tout cas merci de votre aide !

Discussions similaires

  1. Optimiser la recherche dans des fichiers
    Par Napalm51 dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 22/01/2008, 14h28
  2. ajout dans un fichier
    Par khasanouray dans le forum Langage
    Réponses: 4
    Dernier message: 08/07/2007, 01h02
  3. [DOM] Ajouter dans un fichier XML
    Par noussa_nouha dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 20/07/2006, 12h53
  4. Ajout dans un fichier à un endroit spécifique
    Par VinnieMc dans le forum Langage
    Réponses: 3
    Dernier message: 07/03/2006, 11h46
  5. ajouter dans un fichier xml
    Par hamma2 dans le forum APIs
    Réponses: 4
    Dernier message: 29/09/2003, 12h57

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