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

perl, strace et @INC

1 réponse
Avatar
apolloj
Bonjour,

J'ai un programme qui tourne bien, assez rapidement (manageip_byprojet)

Le détail du programme n'a pas d'importance à mes yeux pour comprendre
la suite.

Par curiosité, qd je regarde avec la commande strace, je vois beaucoup
d'appels systemes non optimises.

0.000074 stat64("/usr/lib/perl5/vendor_perl/5.8.6/Term/ANSIColor.pmc",
0xbfb8e63c) = -1 ENOENT (No such file or directory)
0.000781
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/sse2/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.000831
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/sse2",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000850
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.000698
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000855
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/sse2/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.001050
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/sse2",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000788
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)


Comment éviter les multiples lignes telles que celles-ci ? (> 900)

PS : perl a été installé via un rpm. Peut on modifier le @INC sans
recompiler ?

___________________________________________________________________________________________

A/
Le résultat /usr/bin/strace -c -o /tmp/test manageip_byprojet :


% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
60.59 0.021301 4260 5 waitpid
14.18 0.004986 5 999 959 stat64
8.70 0.003057 5 650 read
6.36 0.002237 447 5 clone
4.71 0.001656 1656 1 execve
1.73 0.000607 8 74 20 open
1.15 0.000405 6 72 close
0.87 0.000306 7 43 mmap2
0.74 0.000261 9 28 brk
0.35 0.000123 0 1758 7 _llseek
0.28 0.000098 0 395 write
0.27 0.000094 2 42 39 ioctl
0.07 0.000023 12 2 munmap
0.00 0.000000 0 1 time
0.00 0.000000 0 1 1 access
0.00 0.000000 0 9 pipe
0.00 0.000000 0 1 readlink
0.00 0.000000 0 1 uname
0.00 0.000000 0 9 mprotect
0.00 0.000000 0 32 rt_sigaction
0.00 0.000000 0 1 rt_sigprocmask
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 ftruncate64
0.00 0.000000 0 28 fstat64
0.00 0.000000 0 1 getuid32
0.00 0.000000 0 1 getgid32
0.00 0.000000 0 1 geteuid32
0.00 0.000000 0 1 getegid32
0.00 0.000000 0 6 fcntl64
0.00 0.000000 0 2 futex
0.00 0.000000 0 1 set_thread_area
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.035154 4174 1026 total

Comment interpréter waitpid ? Peut on éviter les erreurs stat64?


B/
résultat du time (temps d'éxécution du programme) :

real 0m2.023s
user 0m1.972s
sys 0m0.051s

PS :

1/ Mon @INC (que je veux amincir)

[root] # perl -e 'foreach (@INC){print $_."\n"}'
/var/cds
/usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.7/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.8
/usr/lib/perl5/site_perl/5.8.7
/usr/lib/perl5/site_perl/5.8.6
/usr/lib/perl5/site_perl/5.8.5
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.7/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.8
/usr/lib/perl5/vendor_perl/5.8.7
/usr/lib/perl5/vendor_perl/5.8.6
/usr/lib/perl5/vendor_perl/5.8.5
/usr/lib/perl5/vendor_perl
/usr/lib/perl5/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/5.8.8

1 réponse

Avatar
Paul Gaborit
À (at) Sat, 14 Feb 2009 11:44:55 +0100,
apolloj écrivait (wrote):
Par curiosité, qd je regarde avec la commande strace, je vois beaucoup
d'appels systemes non optimises.



Heu... L'appel système lui-même est optimisé ou, en tous cas, s'il ne
l'est pas cela n'a rien à voir avec perl. Ce que vous constatez,
c'est que perl fait appel à de nombreux appels systèmes de manière
inefficace (de votre point de vue et pour votre programme).

0.000074 stat64("/usr/lib/perl5/vendor_perl/5.8.6/Term/ANSIColor.pmc",
0xbfb8e63c) = -1 ENOENT (No such file or directory)
0.000781
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/sse2/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.000831
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/sse2",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000850
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.000698
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/i686",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000855
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/sse2/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)
0.001050
stat64("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/sse2",
0xbff307a8) = -1 ENOENT (No such file or directory)
0.000788
open("/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE/tls/libperl.so",
O_RDONLY) = -1 ENOENT (No such file or directory)

Comment éviter les multiples lignes telles que celles-ci ? (> 900)

PS : perl a été installé via un rpm. Peut on modifier le @INC sans
recompiler ?



On ne peut pas modifier @INC de manière globale sans recompilation. En
revanche, on peut le modifier pour un script donné.

% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
60.59 0.021301 4260 5 waitpid
14.18 0.004986 5 999 959 stat64
8.70 0.003057 5 650 read
6.36 0.002237 447 5 clone
4.71 0.001656 1656 1 execve


[...]
0.00 0.000000 0 9 pipe


[...]
------ ----------- ----------- --------- --------- ----------------
100.00 0.035154 4174 1026 total

Comment interpréter waitpid ? Peut on éviter les erreurs stat64?



Les appels à waitpid ne s'expliquent que parce que votre script fait
appel à des processus externes (d'où les appels à 'pipe' et 'execve').

Pour les "erreurs" de stat64 et de open, le seul moyen d'en réduire le
nombre consiste à modifier @INC.

1/ Mon @INC (que je veux amincir)

[root] # perl -e 'foreach (@INC){print $_."n"}'



Il est plus rapide de taper :

# perl -V

ou à la rigueur :

# perl -le 'print foreach @INC'

/var/cds
/usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.7/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.8
/usr/lib/perl5/site_perl/5.8.7
/usr/lib/perl5/site_perl/5.8.6
/usr/lib/perl5/site_perl/5.8.5
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.7/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.8
/usr/lib/perl5/vendor_perl/5.8.7
/usr/lib/perl5/vendor_perl/5.8.6
/usr/lib/perl5/vendor_perl/5.8.5
/usr/lib/perl5/vendor_perl
/usr/lib/perl5/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/5.8.8



Le '/var/cds' est bizarre. D'où vient-il ?

C'est sûr que c'est un peu long comme liste. Si vous n'utilisez aucun
module datant de versions antérieures de pelr, vous pouvez déjà
supprimer tous les répertoire qui font référence à une version autre
que 5.8.8.

Pour ce faire, ajoutez dès le début de votre script quelques lignes
comme celles ci-dessous (à adapter à votre besoin) :

BEGIN {
@INC = qw{
/usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.8
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.8
/usr/lib/perl5/vendor_perl
/usr/lib/perl5/5.8.8/i386-linux-thread-multi
/usr/lib/perl5/5.8.8
};
}

Ça devrait faire diminuer le nombre de recherches infructueuses.

Une autre solution plus radicale consisterait à embarquer tout le code
Perl de vos modules directement dans votre script, à placer tous les
codes externes (.so et autres) dans le même répertoire que le script
et à ne placer que '.' dans @INC.

PS : ces 'optimisations' n'ont pas vraiment de sens. En effet
l'exécution de votre script consomme un peu plus d'une seconde et
l'ensemble des appels à stat64 ne consomme que 4ms (d'ailleurs ce
dernier temps doit être variable selon l'état du cache disque).

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>