Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Taille optimale des blocs pour la lecture d'un fichier

6 réponses
Avatar
Vincent Lascaux
Bonjour,

Je suis l'auteur de File_Archive (http://pear.php.net/package/File_Archive),
qui est une bibliotheque de gestion d'archive, gz entre autre. Pour créer un
fichier gz à partir d'un autre fichier (qu'il faut consideré comme pouvant
être arbitrairement gros), la suite des instructions executées ressemble à
celle là :

$f = fopen('fichier', 'r');
$gz = gzopen('fichier.gz', 'w');

while( !empty($data = fread($f, 8192)) )
gzwrite($gz, $data);

gzclose($gz);
fclose($f);


Ca "copie" des données depuis $f dans $gz bloc par bloc. J'avais fixé la
taille des blocs à 8ko en lisant le code de readfile dans le source de PHP.
Je me demande si ce choix est judicieux ici et si 8ko est une valeur que
l'on peut considerer comme optimale

Merci

--
Vincent

6 réponses

Avatar
Philippe Chaissac

Ca "copie" des données depuis $f dans $gz bloc par bloc. J'avais fixé la
taille des blocs à 8ko en lisant le code de readfile dans le source de PHP.
Je me demande si ce choix est judicieux ici et si 8ko est une valeur que
l'on peut considerer comme optimale


Je ne me suis pas penché sur le code de readfile, mais à priori je me
dis que de nombreux facteurs doivent influencer la valeur optimale,
comme le filesystem et l'OS sur lesquels tourne php. Le mieux serait
sans doute de faire des tests sur des systèmes différents. Et
éventuellement laisser à l'utilisateur du package la possibilité de
modifier ce paramètre.

Avatar
Vincent Lascaux
Ca "copie" des données depuis $f dans $gz bloc par bloc. J'avais fixé la
taille des blocs à 8ko en lisant le code de readfile dans le source de
PHP. Je me demande si ce choix est judicieux ici et si 8ko est une valeur
que l'on peut considerer comme optimale


Je ne me suis pas penché sur le code de readfile, mais à priori je me dis
que de nombreux facteurs doivent influencer la valeur optimale, comme le
filesystem et l'OS sur lesquels tourne php. Le mieux serait sans doute de
faire des tests sur des systèmes différents. Et éventuellement laisser à
l'utilisateur du package la possibilité de modifier ce paramètre.


Oui, cette possibilité a été rajoutée et sera disponible dans la prochaine
release. Reste que je voudrais avoir une valeur par défaut qui soit la
"meilleur" possible (parceque je doute que beaucoup de gens iront modifier
la valeur par défaut, surtout si le résultat final est le même...). Le
probleme c'est que je sais pas trop comment utiliser les tests : si on est
sur une machine chargée (où beaucoup d'autres applications tournent), il
doit être préferable de ne pas utiliser trop de mémoire. Si on est tout seul
sur la machine, il doit être préférable d'y aller à coup de Mo pour faire le
moins d'appels possible à fread et gzwrite (evidemment, si c'est on demande
un buffer trop gros qui necessite que la mémoire soit swappée sur le disque,
c'est désastreux)...

--
Vincent


Avatar
Philippe Chaissac

Oui, cette possibilité a été rajoutée et sera disponible dans la prochaine
release. Reste que je voudrais avoir une valeur par défaut qui soit la
"meilleur" possible (parceque je doute que beaucoup de gens iront modifier
la valeur par défaut, surtout si le résultat final est le même...). Le
probleme c'est que je sais pas trop comment utiliser les tests : si on est
sur une machine chargée (où beaucoup d'autres applications tournent), il
doit être préferable de ne pas utiliser trop de mémoire. Si on est tout seul
sur la machine, il doit être préférable d'y aller à coup de Mo pour faire le
moins d'appels possible à fread et gzwrite (evidemment, si c'est on demande
un buffer trop gros qui necessite que la mémoire soit swappée sur le disque,
c'est désastreux)...



Effectivement, mais tu écris presque noir sur blanc, là, qu'il n'y a pas
de valeur par défaut vraiment acceptable :-).

Donc, mieux valant faire trop d'appels à fread que de swapper sur le
disque, autant prendre une valeur assez basse. 8ko ça semble bien.

Avatar
Bob qui Trolle
Vincent Lascaux wrote:

Oui, cette possibilité a été rajoutée et sera disponible dans la prochaine
release. Reste que je voudrais avoir une valeur par défaut qui soit la
"meilleur" possible (parceque je doute que beaucoup de gens iront modifier
la valeur par défaut, surtout si le résultat final est le même...).


Le paramètre passé à fopen est toujours un vrai fichier local sur un
vrai disque ou un simple descripteur de fichier arbitaire ? (auquel cas,
8*1024 est gros, mais aussi, tester le handle avant de lire dedans)

Avatar
Vincent Lascaux
Le paramètre passé à fopen est toujours un vrai fichier local sur un vrai
disque ou un simple descripteur de fichier arbitaire ? (auquel cas, 8*1024
est gros, mais aussi, tester le handle avant de lire dedans)


Non, c'est pas necessairement un vrai fichier local. Ca peut être ici d'un
fopen('http://........') par exemple.
Pour quelles raisons 8*1024 est une taille acceptable pour un vrai fichier
local et pas pour un descripteur de fichier arbitraire ?
Qu'entends tu par 'tester le handle avant de lire dedans' ? Je teste bien
que fopen retourne un résultat valide (sinon je lance une erreur PEAR, comme
c'est le standard dans presque tous les packages PEAR).

--
Vincent

Avatar
Bob qui Trolle
Vincent Lascaux wrote:
Le paramètre passé à fopen est toujours un vrai fichier local sur un vrai
disque ou un simple descripteur de fichier arbitaire ? (auquel cas, 8*1024
est gros, mais aussi, tester le handle avant de lire dedans)



Non, c'est pas necessairement un vrai fichier local. Ca peut être ici d'un
fopen('http://........') par exemple.
Pour quelles raisons 8*1024 est une taille acceptable pour un vrai fichier
local et pas pour un descripteur de fichier arbitraire ?


Lorsqu'on lit un flux réseau, normalement, la taille des paquets reçus
est très très inférieure à 8k. Même si elle est en théorie relativement
imprévisible, on peut parier à 90% pour 1k.

Après avoir relu le manuel de PHP 4.3.2+, je viens de me rendre compte
que, finalement, mon objection n'était pas si importante (pour PHP
4.3.2+), puisque : " Lorsque vous lisez depuis un flux réseau, ou un
pipe, tel que ceux utilisés pour les accès aux fichiers distants ou
depuis popen() et fsockopen(), la lecture s'arrête après la réception
d'un paquet. " ( http://fr2.php.net/fread/ ),

Mais apparemment : http://laughingmeme.org/archives/000917.html s'est
fait mordre :-))). Je ne sais pas comment se comporte gzwrite() dans ce cas.


Qu'entends tu par 'tester le handle avant de lire dedans' ? Je teste bien
que fopen retourne un résultat valide (sinon je lance une erreur PEAR, comme
c'est le standard dans presque tous les packages PEAR).


Alors, c'est bon.