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

La bonne manière

4 réponses
Avatar
Stéphane Müller
Bonjour,

Je me posais une petite question. Vaut-il mieux écrire:

my $var;
foreach ( 1..100 ) {
$var = ...
}

ou

foreach ( 1..100 ) {
my $var = ...
}

Il y a-t-il un problème (performance, utilisation mémoire,
etc..) ormis l'aspect "portée" à déclarer $var à chaque
itération ?

Cordialement
Stéphane

4 réponses

Avatar
Nicolas George
"Stéphane Müller" wrote in message <fa43k2$3n1$:
Je me posais une petite question. Vaut-il mieux écrire:

my $var;
foreach ( 1..100 ) {
$var = ...
}

ou

foreach ( 1..100 ) {
my $var = ...
}


Pour moi, le second, très clairement, sauf si la dernière valeur prise est
utile après la fin de la boucle. Sinon, ça laisse une variable déclarée dont
la valeur n'est pas pertinente, c'est un risque de bug.

Il y a-t-il un problème (performance, utilisation mémoire,
etc..) ormis l'aspect "portée" à déclarer $var à chaque
itération ?


Si la performance est critique, il faut essayer, évidemment.

Avatar
Jean-Baptiste Mazon
"Stéphane Müller" writes:

Bonjour,

Je me posais une petite question. Vaut-il mieux écrire:

my $var;
foreach ( 1..100 ) {
$var = ...
}

ou

foreach ( 1..100 ) {
my $var = ...
}

Il y a-t-il un problème (performance, utilisation mémoire,
etc..) hormis l'aspect "portée" à déclarer $var à chaque
itération ?


"La" bonne manière n'existe pas! ;-) Ceci dit, on peut débattre des
différences entre les deux.

Au premier abord, la première est plus efficace: elle n'alloue la
variable qu'une fois pour toutes, alors que la seconde la crée/libère
à chaque itération. L'empreinte mémoire de l'ensemble est similaire
sur la durée de l'itération. (à supposer, bien sûr, qu'aucune
référence à la variable ne soir conservée et gardée, mais le fait que
le dilemme se pose me conforte dans cette hypothèse)

D'un point de vue de prévision de la maintenance, j'aurais tendance à
réduire la portée des variables autant que possible. Mais si le temps
d'exécution devient un problème, il y a effectivement un peu à gratter
par là. Si peu que c'en est rarement justifié.

Avatar
Denis Joiret
Stéphane Müller wrote:
Bonjour,

Je me posais une petite question. Vaut-il mieux écrire:

my $var;
foreach ( 1..100 ) {
$var = ...
}

ou

foreach ( 1..100 ) {
my $var = ...
}

Il y a-t-il un problème (performance, utilisation mémoire,
etc..) ormis l'aspect "portée" à déclarer $var à chaque
itération ?


Bonjour,

Le second semble un peu plus lent au vu de quelques exécutions :

% repeat 5 time perl -e 'my $var; foreach (1 .. 30000000) { $var = $_; }'
3.430u 0.003s 0:03.44 99.7% 0+0k 0+0io 0pf+0w
3.440u 0.002s 0:03.40 101.1% 0+0k 0+0io 0pf+0w
3.430u 0.001s 0:03.42 100.2% 0+0k 0+0io 0pf+0w
3.433u 0.002s 0:03.43 100.0% 0+0k 0+0io 0pf+0w
3.433u 0.007s 0:03.44 99.7% 0+0k 0+0io 0pf+0w
%
% repeat 5 time perl -e 'foreach (1 .. 30000000) { my $var = $_; }'
4.511u 0.002s 0:04.52 99.7% 0+0k 0+0io 0pf+0w
4.518u 0.004s 0:04.53 99.5% 0+0k 0+0io 0pf+0w
4.517u 0.003s 0:04.50 100.2% 0+0k 0+0io 0pf+0w
4.505u 0.005s 0:04.51 99.7% 0+0k 0+0io 0pf+0w
4.512u 0.004s 0:04.53 99.5% 0+0k 0+0io 0pf+0w
%

En moyenne, le premier s'exécute en 3.42 secondes, et le second en 4.41 secondes.

Ceci dit, si la boucle s'éxécute seulement 100 fois (comme mis dans les codes
plus haut), les deux sont strictement équivalents, il a fallu que je mette un
nombre de boucles très importants pour arriver à mettre un peu en évidence une
différence notable de temps d'exécution. Et dans ce cas, le contenu de la
boucle lui même dictera le temps global d'exécution, si on veut optimiser, il
faudra alors scruter chaque ligne du code dans la boucle.

Sinon, pour éviter le problème de porté de la variable, il suffit d'entourer
la boucle dans une construction { } qui est équivalente à une boucle exécutée
une seule fois.

{
my $var;
foreach (1 .. 100) {
$var = ...
}
}

ainsi, la variable disparait une fois la boucle terminée.

Denis

Avatar
espie
In article ,
Denis Joiret wrote:
Stéphane Müller wrote:
Bonjour,

Je me posais une petite question. Vaut-il mieux écrire:

my $var;
foreach ( 1..100 ) {
$var = ...
}

ou

foreach ( 1..100 ) {
my $var = ...
}

Il y a-t-il un problème (performance, utilisation mémoire,
etc..) ormis l'aspect "portée" à déclarer $var à chaque
itération ?


Bonjour,

Le second semble un peu plus lent au vu de quelques exécutions :

% repeat 5 time perl -e 'my $var; foreach (1 .. 30000000) { $var = $_; }'
3.430u 0.003s 0:03.44 99.7% 0+0k 0+0io 0pf+0w
3.440u 0.002s 0:03.40 101.1% 0+0k 0+0io 0pf+0w
3.430u 0.001s 0:03.42 100.2% 0+0k 0+0io 0pf+0w
3.433u 0.002s 0:03.43 100.0% 0+0k 0+0io 0pf+0w
3.433u 0.007s 0:03.44 99.7% 0+0k 0+0io 0pf+0w
%
% repeat 5 time perl -e 'foreach (1 .. 30000000) { my $var = $_; }'
4.511u 0.002s 0:04.52 99.7% 0+0k 0+0io 0pf+0w
4.518u 0.004s 0:04.53 99.5% 0+0k 0+0io 0pf+0w
4.517u 0.003s 0:04.50 100.2% 0+0k 0+0io 0pf+0w
4.505u 0.005s 0:04.51 99.7% 0+0k 0+0io 0pf+0w
4.512u 0.004s 0:04.53 99.5% 0+0k 0+0io 0pf+0w
%

En moyenne, le premier s'exécute en 3.42 secondes, et le second en 4.41
secondes.


Tu omets de dire quelle version de perl tu utilises...

Personnellement, je ne me fatigue jamais a faire ce genre de chose
avant d'avoir passe un profiler quelconque sur mon code, si celui-ci
s'avere un peu lent.

(entre Devel::DProf, Devel::FastProf, Devel::SmallProf, et Devel::Size
il n'y a que l'embarras du choix...)

De toutes facons, qui nous dit que la prochaine version de perl ne va
pas optimiser ce genre de choses ? ca parait du domaine du fort
raisonnable.