Mon shell bash prend jusqu'à 3-4 secondes pour démarrer, tandis que si je le démarre avec, --norc
il s'exécute immédiatement.
J'ai commencé à "profiler" /etc/bash.bashrc
et ~/.bashrc
en insérant manuellement des return
déclarations et en cherchant des améliorations de vitesse, mais ce n'est pas un processus quantitatif et ce n'est pas efficace.
Comment puis-je profiler mes scripts bash et voir quelles commandes prennent le plus de temps à démarrer?
time bash -c 'exit'
ettime bash -i -c 'exit'
et jouer avec--norc
et--noprofile
.Réponses:
Si vous avez GNU
date
(ou une autre version qui peut générer des nanosecondes), faites-le au début de/etc/bash.bashrc
(ou à l'endroit où vous souhaitez commencer une trace dans n'importe quel script Bash):ajouter
à la fin de
~/.bashrc
(ou à la fin de la section de tout script Bash que vous souhaitez que le traçage arrête). Le\011
est un caractère de tabulation octal.Vous devriez obtenir un journal de
/tmp/bashstart.PID.log
suivi qui affiche l'horodatage en secondes.nanosecondes de chaque commande exécutée. La différence d'une fois à l'autre est la durée de l'étape intermédiaire.Au fur et à mesure que vous affinez les choses, vous pouvez vous déplacer de
set -x
plus en plusset +x
tôt (ou entre parenthèses plusieurs sections d'intérêt de manière sélective).Bien qu'il ne soit pas aussi fin que
date
les nanosecondes de GNU , Bash 5 inclut une variable qui donne le temps en microsecondes. Son utilisation vous évite de créer un exécutable externe pour chaque ligne et fonctionne sur des Mac ou ailleurs qui n'ont pas GNUdate
- tant que vous avez Bash 5, bien sûr. Modifiez le paramètre dePS4
:Comme indiqué par @pawamoy, vous pouvez utiliser
BASH_XTRACEFD
pour envoyer la sortie de la trace vers un descripteur de fichier séparé si vous avez Bash 4.1 ou version ultérieure. De cette réponse :Cela entraînera la sortie de la trace vers le fichier
command.txt
sortantstdout
etstdout
sera sortie normalement (ou sera redirigée séparément).la source
exec
devrait renvoyer fd2 à la normale, vous devriez donc récupérer l'invite.\D{...}
inPS4
permet d'étendre des chaînes de format de temps complètement arbitraires sans la surcharge de performances du lancement endate
tant que sous-processus.date
comprend%N
et Bash 4.2 ne le fait pas (parcestrftime(3)
que non) sur le système GNU - donc arbitraire avec des limites. Votre point de vue sur les performances par rapport à la résolution est bon et un utilisateur doit faire un choix judicieux, en gardant à l'esprit que l'atteinte des performances est temporaire uniquement pendant le débogage (et uniquement lorsqu'elleset -x
est en vigueur).Profilage frapper (4 réponses)
Edit:
script
méthode d' ajout de mars 2016En lisant ceci et parce que le profilage est une étape importante, j'ai fait des tests et des recherches sur toute cette question SO et j'ai déjà publié des réponses.
Il y a 4+ réponses:
La dernière utilisation
script
,scriptreplay
et le fichier de synchronisation .Enfin, un petit comparatif des performances à la fin.
Utilisation
set -x
etdate
mais avec des fourches limitéesReprenez l'idée de @ DennisWilliamson, mais avec la syntaxe suivante, il n'y aura qu'un seul fork initial pour 3 commandes:
Cela ne fonctionnera
date
qu'une seule fois. Il existe une démonstration / test rapide pour montrer comment cela fonctionne:Exemple de script:
En exécutant ce script, vous créez 2 fichiers:
/tmp/sample-XXXX.log
et/tmp/sample-XXXX.tim
(où XXXX est l'identifiant de processus du script en cours d'exécution).Vous pouvez les présenter en utilisant
paste
:Ou vous pouvez même calculer le temps de différence:
ou sur deux colonnes:
Peut rendre:
Utilisation de
trap debug
et/proc/timer_list
sur les noyaux GNU / Linux récents , sans fourches .Sous les noyaux récents de GNU / Linux , vous pouvez trouver un
/proc
fichier nommétimer_list
:Où l'heure actuelle est la somme de
5461935212966259 + 1383718821564493249
, mais en nanosecondes.Donc, pour calculer le temps écoulé , il n'est pas nécessaire de connaître le décalage.
Pour ce genre d'emplois, j'ai écrit elap.bash (V2) , qui provient de la syntaxe suivante:
ou
(Voir les commentaires pour la syntaxe complète)
Vous pouvez donc simplement ajouter cette ligne en haut de votre script:
Petit échantillon:
Faire le rendu sur mon hôte:
Utilisation
trap2
au lieu detrap
comme argument de la commande source:Affiche la dernière commande et le total de deux colonnes :
En utilisant
strace
Oui,
strace
pourrait faire le travail:Mais il pourrait y avoir beaucoup de choses!
Utilisation d'une commande plus restreinte:
Videra le journal plus léger:
Selon ce que vous recherchez, vous pouvez être plus restrictif:
Leur lecture sera un peu plus difficile:
Le script bash original n'est pas si facile à suivre dans ce cas ...
L' utilisation
script
,scriptreplay
et le fichier de synchronisationDans le cadre de BSD Utils ,
script
(andscriptreplay
) est un outil très ancien qui peut être utilisé pour profiler bash, avec un très faible encombrement.Produira:
et générez deux fichiers:
Le fichier
script.log
contient toutes les traces etscript.tim
est le fichier de synchronisation :Vous pouvez voir l'exécution du temps total avec les première et dernière lignes du fichier journal et / ou en résumant les temps dans le fichier de synchronisation:
Dans le fichier de synchronisation, la deuxième valeur est le nombre d'octets suivants dans le fichier journal correspondant. Cela vous permet de rejouer le fichier journal en option avec un facteur d'accélération :
ou
ou
Afficher les heures et les commandes côte à côte est également un peu plus complexe:
Tests et conclusion
Pour faire des tests, j'ai téléchargé un deuxième exemple sur bash complex hello world , ce script prend environ 0,72 sec pour se terminer sur mon hôte.
J'ai ajouté en haut du script l'un des:
par
elap.bash
fonctionpar
set -x
etPS4
par
set -x
et initialisation de la commande d'exécution longuepar
script
(etset +x
)Fois
Et comparez les temps d'exécution (sur mon hôte):
Les sorties
par
elap.bash
fonctionpar
set -x
etPS4
par
set -x
et initialiser le fork à la commande d'exécution longue (et mon deuxièmepaste
exemple de script)par
strace
par
script
Conclusion
Bien! Si mon pur bash est plus rapide que le forking à ce jour sur chaque commande , mon pur bash implique quelques opérations sur chaque commande.
La manière de consacrer un processus indépendant pour la journalisation et le stockage est clairement plus efficace.
strace
est une manière intéressante, plus détaillée, mais difficile à lire.script
, avecscriptreplay
et facteur d'accélération est très sympa aussi, pas la même précision car cela est basé sur l'échange de console au lieu de l'exécution de processus, mais très léger et efficace (pas le même objectif, pas le même usage).Enfin, je pense que le plus efficace, en lisibilité et en performances, c'est
set + 1 fork
, le premier de cette réponse, mais in fine, selon le cas particulier, j'utilise parfoisstrace
et / ouscript
aussi.la source
exec {BASH_XTRACEFD}>
place deexec 3>&2 2>
qui ne remplira le fichier journal qu'avec la sortie de journalisation de trace et pas une autre sortie stderr.script.sh
, je peux simplement fairebash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.sh
et obtenir des données de profilage sans les modifierscript.sh
. Quand une précision inférieure à la seconde n'est pas nécessaire, j'aimebash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.sh
quel horodatage chaque ligne de trace avec une seconde précision et sans bifurcation à la date (faible surcharge).Il aide souvent à retracer les appels système
À partir du manuel:
-c Compter le temps, les appels et les erreurs pour chaque appel système et rapporter un résumé à la sortie du programme.
-f Tracer les processus enfants ...
Ce n'est pas exactement ce que vous voulez et ce qu'un profileur orienté ligne vous montrerait, mais cela aide généralement à trouver des points chauds.
la source
Vous pouvez consulter la
trap
commande avec la condition DEBUG . Il existe un moyen de définir une ou plusieurs commandes à exécuter avec vos commandes. Voir les notes de la réponse.la source
help trap
: "Si un SIGNAL_SPEC est DEBUG, ARG est exécuté avant chaque commande simple." Dans Bash 3.2, il dit "après". C'est une faute de frappe. Depuis Bash 2.05b, il est déjà exécuté. Référence : "Ce document détaille les changements entre cette version, bash-2.05b-alpha1, et la version précédente, bash-2.05a-release. ... 3. Nouvelles fonctionnalités de Bash ... w. Le trap DEBUG est maintenant s'exécute avant les commandes simples, les ((...)) commandes, [...] les commandes conditionnelles et les boucles for ((...)). " Le test dans chaque version confirme que c'est avant .Time, xtrace, bash -x
set -x
etset+x
( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) restent la méthode classique pour déboguer un script.Toujours pour élargir notre horizon, il est possible de donner un contrôle à un système pour le débogage et le profilage disponible pour les programmes Linux habituels [ici une des listes] , par exemple il devrait en résulter un utile basé sur valgrind en particulier pour déboguer la mémoire ou sysprof pour profil l'ensemble du système:
Pour sysprof:
Et après pour sélectionner la branche de sous-processus que vous trouvez intéressante.
Pour Valgrind:
Avec un peu plus de gym, il semble possible de rendre visibles à Valgrind certains programmes que nous installons habituellement à partir de binaires (par exemple OpenOffice ).
Il est possible de lire la FAQ de valgrind qui
Valgrind
profilera les processus enfants si cela est explicitement demandé.Il le fera avec cette option activée
Références supplémentaires:
la source
Cet article d' Alan Hargreaves décrit la méthode de profilage du script Bourne shell à l'aide du fournisseur DTrace. Autant que je sache, cela fonctionne avec Solaris et OpenSolaris (voir: / bin / sh DTrace Provider ).
Donc, étant donné le script dtrace suivant (
sh_flowtime.d
à GH basé sur l' original ):vous pouvez suivre le flux des fonctions, y compris les temps delta.
Exemple de sortie:
Ensuite, à l'aide de la
sort -nrk7
commande, vous pouvez trier la sortie pour afficher les appels les plus consommateurs.Je ne connais aucun fournisseur de sondes disponibles pour d'autres shells, alors faites des recherches (recherche sur GitHub?) Ou si vous souhaitez investir du temps, vous pouvez les écrire en vous basant sur l' exemple sh existant : (voir: Comment activer sh Fournisseur DTrace? ).
la source