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 :

Optimiser les appels à la fonction fread()


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2011
    Messages : 17
    Par défaut Optimiser les appels à la fonction fread()
    Bonjour,

    J'ai beaucoup de fichiers binaires (taille max 300 Ko) qui arrivent sur une ressource et je cherche à les traiter le plus vite possible car j'ai de fortes contraintes de temps sur cette application.

    Tout naturellement j'utilise fopen() puis fread() pour la lecture des fichiers binaires. Ma lecture du fichier et son traitement sont séquentiels, je n'ai pas besoin de naviguer dans mon fichier, je ne fais que le dérouler.

    Je me posais la question d'optimiser mes appels à la fonction fread() et de l'utilité de passer par un buffer de lecture (char *).

    Qu'est-ce qui est le plus rapide et pourquoi ?
    1 - Lire d'un bloc tout le fichier, le stocker dans un buffer puis travailler octet par octet sur ce buffer.
    2 - Lire le fichier bloc par bloc dans une boucle avec un buffer de taille moyenne (exemple 256 octet) puis travailler octet par octet sur ce buffer.
    3 - Lire le fichier octet par octet avec fread et donc travailler directement avec le résultat de la lecture par fread

    En gros est-il plus avantageux de travailler sans buffer et donc multiplier les appels à fread() ou bien augmenter la taille du buffer pour minimiser les appels à fread() ?

    Merci d'avance pour vos lumières.

  2. #2
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    tu veux optimiser quoi? la vitesse ou la consomation memoire.
    faire plusieurs appels system c'est plus lent qu'en faire un seul, en meme temps tout mettre dans un buffer consomme plus.
    de plus connait tu la taille exacte du fichier a l'octet pres?

    ce que tu peux faire c'est:
    1/si tes fichiers ont toujours la meme taille et assez petite 300ko de les lire en entier et travailler sur le buffer, ton programme sera donc plus rapide mais consommera plus
    2/si les tables sont variables et inconnu tu serai pourait charger des parties, travailler avec et recharger une autre partie travailler avec ... ou alors charger le tout dans un buffer en faissant plusieurs appel fread.

  3. #3
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Bonjour,

    Pour optimiser la rapidite, minimise les appels a fread, en utilisant une seule lecture si possible.
    Apres, le mieux est peut-etre d'implementer une version, puis de faire appel a un profileur de code (valgrind, purify/quantify, gprof, ...) pour voir ou tu passes le plus de temps.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  4. #4
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2011
    Messages : 17
    Par défaut
    Je souhaite plutôt optimiser la vitesse que la consommation mémoire.
    Mes fichiers ont une taille variable entre 50 ko et 300 ko et je peux déterminer leur taille avec la fonction ftell() ou struct stat.

    Si j'ai bien compris ce que vous me dites, la solution la plus rapide serait celle qui minimise le nombre d'appel à fread() et fonctionne plus avec le buffer.
    (Donc lecture du fichier en un seul bloc, mise en mémoire de tout son contenu dans un buffer puis je travaille uniquement sur le buffer)
    Est-ce que quelqu'un peut m'expliquer pourquoi les lectures avec fread seront plus lentes que les lectures dans le buffer ?

    Pour ce qui est des profileur de code, j'en suis encore qu'au début de la phase de développement, je n'ai jamais travaillé avec ces outils, mais j'y jetterai un coup d’œil plus tard pour mes tests ça à l'air interressant

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Est-ce que quelqu'un peut m'expliquer pourquoi les lectures avec fread seront plus lentes que les lectures dans le buffer ?
    Je présume qu'un accès au disque dur via des fonctions du système est plus lent qu'un accès direct à la mémoire vive.

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2011
    Messages : 17
    Par défaut
    Qu'en est-il si je recode ma propre fonction fread() dans mon programme et que j'utilise celle-ci ou lieu d'utiliser l'appel système ?

  7. #7
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    Citation Envoyé par Korrigan5 Voir le message
    Je souhaite plutôt optimiser la vitesse que la consommation mémoire.
    donc mets ton fichier dans un buffer
    Citation Envoyé par Korrigan5 Voir le message
    Est-ce que quelqu'un peut m'expliquer pourquoi les lectures avec fread seront plus lentes que les lectures dans le buffer ?
    La reponse est on ne peut plus simple.
    fread appartient a la librairie standard qui fait un appel system. donc voici ce qui se passe en gros:
    1/tu demandes au kernel de lire sur le disk
    2/le kernel fait
    3/te donne le resultat.
    4/ tu traites
    5/tu recommences

    avec un buffer tu fais de 1 a 3 une seule fois.
    donc tu gagnes le temps de l'appel systeme et surtout la lecture sur le disk qui est comme tout le monde te le dira lente.
    donc tu fait etapes 1 a 3 une seule vois, une seule lecture sur le disque et le reste du temps tu travailles avec ton buffer ( ram ou cache).

    en gros c'est ca si tu veux plus de detail tu peux voir dans la section (utiisation des fichiers dans le bouquin Beginning linux programming des editions Wrox

  8. #8
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2011
    Messages : 17
    Par défaut
    Merci lilington pour ces précisions.

    Qu'en est-il si je recode ma propre fonction fread() dans mon programme et que j'utilise celle-ci ou lieu d'utiliser l'appel système ?
    a priori je ne travaillerai plus avec l'appel système sur le disque mais bien avec ma fonction qui sera en RAM/Cache ?

    Mais je suppose qu'a un moment donnée dans la réécriture de fread je serai obligé d'utiliser un autre appel système ? comme memcpy. Mais je pourrai aussi réécrire memcpy dans mon programme ... etc
    Où se situe la limite entre ce qui est exécuté en RAM/Cache ou sur le disque ?

  9. #9
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    Tu gagneras rien de bon a le faire.
    au mieux gagnera le temps perdu lors de l'appel au pire tu vas truffer ton programme de failles pourquoi?
    ben simplement parceque la lecture du disk n'est pas comme celle d'un fichier.
    il ya un systeme de fichier installer (NTFS, FAT,EXT2,EXT3... plein plein plein).
    donc quand tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fd=fopen("/home/moi/truc.txt","r");
    tu remarque que tu ne donnes aucune information autre que la position du fichier sur le systeme de fichier.
    a ton avis qui le fait pour toi?
    Reponse le Kernel. il sait donc reconnaitre les types de Systeme de Fichier(FS) et donc retrouver le fichier qui est segmente dans 99%des cas.

    donc ton programme doit savoir lire la plus part des FS, retrouver une donner et la copier.
    en gros tu feras la meme chose que fait deja la fonction fread avec la difference que tu risques de creer plein de bug qui ne sont pas deja la. car fread se contentde de demander au kernel des choses. toi tu veux reprogrammer ses choses.
    Je sais pas si je suis claire generalement j'explique mal.

    en resumer la tache est. lire le debut du disque, retrouver la partition, trouver la position de debut de la partition,detecter le type de format FS, lire la table d'allocation de la partition pour trouver le premier bout de ton fichier, savoir calculer les adresses des autres bout et recuperer le tout avant de balancer dans ton buffer.

    et la je le dis comme ca a la va vite. plus de detail avec les Systeme D'exploitation de Andrew S. Tanenbaum section Files System. tu veras que c'est du boulot

    edit: ll est possible d'aller plus vite que fread mais ton code sera specifique a un cas particulier parmis des milliers en plus d'etre kilometrique. d'ou le manque d'interret

  10. #10
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    pour ta question sur les appels systemes ca depend surtout du systeme d'exploitation.

    un systeme peut te permettre de foutre le bordel dans la memoire donc d'y acceder comme tu veux ce qui te permet de te passer d'appel systeme

    un autre ne te laisse pas faire ce que tu veux et t'alloue un espace qui t'appartient que tu retrouves avec les appelles systeme mais apres comme on est en C tu peux acceder a ta zone sans appels systemes.
    tu alloue avec malloc (appel systeme)
    et tu copy avec mencpy (appel systeme)
    ou tu copy avec une simple boucle for *(ptr+ofset)=machin (aucun appel)

    tu peux verifier ce que je dis en accedent n'importe ou et n'importe comment sans avoir demander la permittion avec malloc. tu auras une erreur de segmentation et ton programme se fera ejecter par le systeme. tu peux en deduire que pour le systeme dans le quel tu es protege un minimum sa memoire.

  11. #11
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2011
    Messages : 17
    Par défaut
    Merci beaucoup de m'avoir éclairer sur tous ces points

    Je vais donc lire mon fichier avec fread dans un buffer de taille suffisamment grande pour limiter le nombre d'appel à fread().

  12. #12
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    Citation Envoyé par Korrigan5 Voir le message
    Merci beaucoup de m'avoir éclairer sur tous ces points

    Je vais donc lire mon fichier avec fread dans un buffer de taille suffisamment grande pour limiter le nombre d'appel à fread().
    c'est 50euro merci.

  13. #13
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    Bonjour à tous

    Des petits compléments et quelques rectifications, tout ça dans un contexte Unix/Linux uniquemennt.

    Un appel à fread ne provoque pas forcément - c'est même un cas particulier - de lecture réelle sur disque. Seul l'appel système read (fread n'en est pas un) lit effectivement des données, quand il est appelé explicitement ou implicitement, par fread par exemple.

    De plus, et depuis longtemps (bien avant l'apparition de Linux, je l'avais constaté sous plusieurs Unix de familles différentes, SunOS (BSD à l'époque) Ultrix (Unix de Digital, BSD aussi) ou encore des sytèmes AT&T (system V)), il y a une bufferisation gérée dans les structures FILE dont bénéficient toutes les fonctions manipulant des FILE *.

    Ce petit exemple l'illustre bien : après ouverture, je lis (fread) 1 et 1 seul caractère du fichier "alphabet" (les 26 lettres et le '\n' final) puis affiche le reste, sans jamais faire d'autre lecture :

    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
    #include <stdio.h>
     
    int main(int argc,char *argv[])
    {
        FILE *fp;
        char caractere;
        char format[64];
        int taille_restante;
     
        fp = fopen(argv[1],"r");
     
        fread(&caractere,1,1,fp);
        printf("le premier caractere du fichier est ->%c<-\n",caractere);
     
        // A PARTIR D'ICI, JE NE LIS PLUS RIEN DANS fp : PLUS DE FREAD, FSCANF, ..., RIEN !!!
        // ET POURTANT ...
     
        taille_restante = fp->_IO_read_end-fp->_IO_read_ptr;
        sprintf(format,"le reste :\n%%%d.%ds",taille_restante,taille_restante);
        printf(format,fp->_IO_read_ptr);
     
        printf("Etonnant, non ?\n");
    }
    A l'usage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    plx@sony:~$ more alphabet 
    abcdefghijklmnopqrstuvwxyz
    plx@sony:~$ gcc -o magique magique.c
    plx@sony:~$ ./magique alphabet
    le premier caractere du fichier est ->a<-
    le reste :
    bcdefghijklmnopqrstuvwxyz
    Etonnant, non ?
    plx@sony:~$
    Tout ça pour dire que si la lecture fread, caractère par caractère, est plus longue qu'une lecture d'un "gros" buffer, ce n'est pas à cause des lectures disques mais à la répétition des appels (ça a, malgré tout, un coût). Sous mon système Ubuntu, avec des buffers de 4Ko, il faut comparer 1 appel à plus de 4000, l'exécution de la fonction fread elle-même, la gestion de ce fameux buffer, etc... mais le buffer n'est re-rempli (lecture disque cette fois), en lecture octet par octet, qu'à la 4097-ieme lecture

    J'ai reproduit, sous MacOSX (base FreeBSD je crois), la même chose, même si la structure FILE n'a pas tout à fait la même tête, avec des noms de champs différents.

    Alors comment optimiser l'utilisation de fread ? Ré-écrire un équivalent ? bof ... Je commencerais par utiliser une "bonne" taille, pas forcément tout le fichier, avant d'envisager cette solution.

    J'ai fait quelques petits tests, en mesurant, grossièrement, les performances et en lisant entre 50,000 octets (pas 50Ko, trop "typé" !) et 300,000 octets d'un (très) gros fichier, par pas de 50,000 et en testant les fread par 1 octet, 1 * 4Ko, 10 * 4Ko, etc...

    Le source C :

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc,char *argv[])
    {
    	FILE  *fp;
    	long  total;
    	int   paquet;
    	char *buffer;
    	int   i;
     
    	fp = fopen(argv[1],"r");
    	total = atol(argv[2]);
    	if ((paquet = atoi(argv[3])*4096) == 0) paquet = 1;
    	buffer = malloc(paquet);
     
    	for (i=0;i<total/paquet;i++)
    		fread(buffer,paquet,1,fp);
    	fread(buffer,total%paquet,1,fp);
     
    	fclose(fp);
    }

    et la boucle de lancement (en Python, mais vous comprendrez sans problème) et les résultats (en secondes) :

    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
    >>> from time import time
    >>> for size in range(50000,300001,50000):
    ...     print "Lecture de %d octets" % size
    ...     for bloc in (0,1,10,20,30,40,50):
    ...             t0 = time()
    ...             _ = os.system('./mesures Bureau/POINTS_LIAISONS.TXT %d %d' % (size,bloc))
    ...             delta = time()-t0
    ...             if bloc:
    ...                     print "par blocs de %2d x 4Ko : %f" % (bloc,delta)
    ...             else:
    ...                     print "octet par octet       : %f" % delta
    ... 
    Lecture de 50000 octets
    octet par octet       : 0.008019
    par blocs de  1 x 4Ko : 0.002877
    par blocs de 10 x 4Ko : 0.002981
    par blocs de 20 x 4Ko : 0.002949
    par blocs de 30 x 4Ko : 0.003050
    par blocs de 40 x 4Ko : 0.002926
    par blocs de 50 x 4Ko : 0.002935
    Lecture de 100000 octets
    octet par octet       : 0.012798
    par blocs de  1 x 4Ko : 0.003069
    par blocs de 10 x 4Ko : 0.002928
    par blocs de 20 x 4Ko : 0.002999
    par blocs de 30 x 4Ko : 0.002964
    par blocs de 40 x 4Ko : 0.003093
    par blocs de 50 x 4Ko : 0.003068
    Lecture de 150000 octets
    octet par octet       : 0.014815
    par blocs de  1 x 4Ko : 0.001944
    par blocs de 10 x 4Ko : 0.001819
    par blocs de 20 x 4Ko : 0.001893
    par blocs de 30 x 4Ko : 0.001966
    par blocs de 40 x 4Ko : 0.002032
    par blocs de 50 x 4Ko : 0.002061
    Lecture de 200000 octets
    octet par octet       : 0.014005
    par blocs de  1 x 4Ko : 0.002007
    par blocs de 10 x 4Ko : 0.001819
    par blocs de 20 x 4Ko : 0.001882
    par blocs de 30 x 4Ko : 0.001955
    par blocs de 40 x 4Ko : 0.002128
    par blocs de 50 x 4Ko : 0.002079
    Lecture de 250000 octets
    octet par octet       : 0.021874
    par blocs de  1 x 4Ko : 0.002014
    par blocs de 10 x 4Ko : 0.001885
    par blocs de 20 x 4Ko : 0.001961
    par blocs de 30 x 4Ko : 0.002052
    par blocs de 40 x 4Ko : 0.002132
    par blocs de 50 x 4Ko : 0.002173
    Lecture de 300000 octets
    octet par octet       : 0.019919
    par blocs de  1 x 4Ko : 0.002156
    par blocs de 10 x 4Ko : 0.001928
    par blocs de 20 x 4Ko : 0.001932
    par blocs de 30 x 4Ko : 0.002003
    par blocs de 40 x 4Ko : 0.002200
    par blocs de 50 x 4Ko : 0.002186
    >>>
    bref, sauf à vouloir gratter sur tout, une lecture fread en utilisant la taille du buffer de FILE est peut être la solution efficace la plus simple, non ?

  14. #14
    Membre extrêmement actif
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Par défaut
    excellent, merci pour le complement.
    j'ajoute aussi que c'est pas fread ou read qui ne lisent pas le disk mais le SE qui met en cache tout fichier ouvert au dela d'une limite.

    difficile a tester mais la doc de free(free command unix pas free du C) te le dira.
    quand tu tapes free on va que la colonne free est toujours tres petite meme quand on vient d'allumer la machine. c'est justement que sous linux une bonne partie de la memoire est utiliser pour bufferiser mais le systeme laisse la priorite au application donc si un programme demande de la memoire et que ce qui est “free" n'est pas suffisant il va liberer une partie du buffer.

    pour verifier essaies d'ouvrire un fichier plus gros que le "free" mais inferieur a la taille free+buffer.

  15. #15
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    Absolument !

    Je ne voulais pas trop rentrer dans les détails et descendre "trop" bas dans les explications (déjà que ...) mais, effectivement, avant même la bufferisation dans les structures FILE, au niveau utilisateur, le noyau bufferise les entrées-sorties, pour des périphériques mode bloc (donc sur des fichiers "classiques" pour faire simple).

    Donc, pour être précis, read(2) provoque une lecture du/depuis le système de fichiers, et, si besoin et pas toujours, une lecture sur le disque.

    Alors, fread(3), x couches/appels au-dessus ...

    Cette bufferisation, côté noyau cette fois, est aussi assez ancienne et était déjà décrite en détails, au milieu des années 80, dans "The design of the UNIX Operating System" de M.J. Bach qui y consacre un chapitre entier ('The buffer cache') :

    (...) The kernel could read and write directly to and from the disk for all file system accesses, but system response time and throughput would be poor because of the slow disk transfer rate. The kernel therefore attempts to minimize the frequency of disk access by keeping a pool of internal data buffers, called the buffer cache, which contains the data in recently used disk blocks.

    Figure 2.1 showed the position of the buffer cache module in the kernel architecture between the file subsystem and (block) device drivers. When reading data from the disk, the kernel attemps to read from the buffer cache. If the data is already in the cache, the kernel does not have to read from the disk.


    Pour mettre ça en évidence, il y a free, mais aussi, et cette fois-ci plutôt côté bufferisation en mode écriture, sync (synchronisation du file sytem "mémoire" et du disque) :

    sync (1) - la commande - "flush file system buffers",
    sync (8) - la commande système - "synchronize data on disk with memory"
    sync (2) - l'appel système - "commit buffer cache to disk"

    (descriptions récupérées sur Linux/Ubuntu)

    De façon plus pratique et visuelle : lorsque l'on copie un ou plusieurs fichiers, le tout de grande taille, sur un disque dur externe, que l'on récupère la main et que l'on tente aussitôt un démontage du système de fichiers (du disque dur externe), une jolie fenêtre popup apparaît souvent et indique que "c'est en cours, attendez un petit peu et ré-essayez plus tard !" : c'est, je pense, dû à cette synchronisation.


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

Discussions similaires

  1. preferer les appels aux fonctions const
    Par yan dans le forum C++
    Réponses: 12
    Dernier message: 29/08/2008, 10h15
  2. Espacer les appels des fonctions
    Par thibaut06 dans le forum Langage
    Réponses: 1
    Dernier message: 25/12/2007, 16h58
  3. Hooking : intercepter les appels de fonction
    Par The Lord of Nesquik dans le forum Windows
    Réponses: 17
    Dernier message: 28/02/2007, 17h07
  4. Optimiser les appels à la BD ?
    Par toutoune60 dans le forum JSF
    Réponses: 2
    Dernier message: 24/01/2007, 15h48
  5. voir tout les appels de fonction avec le debugger?
    Par decksroy dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 03/10/2006, 11h33

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