J'utilise ce script dtrace de here pour essayer de trouver quand les changements de contexte se produisent pour les threads d'un programme java. J'essaie de faire correspondre les données recueillies à partir du script avec les données de trace recueillies à partir du programme en cours d'exécution (des choses comme l'entrée/la sortie de la méthode). Je reçois l'identifiant pthread du thread en cours d'exécution en utilisant une méthode JNI courte qui retourne simplement la valeur de pthread_self(). Le problème que je rencontre est que l'identifiant de thread que j'obtiens en appelant pthread_self() est complètement différent de n'importe quel identifiant de thread que j'obtiens dans le script dtrace. Je me demande si c'est parce que j'appelle pthread_self() incorrectement car il renvoie un pointeur, mais il a été difficile de trouver des informations sur ce que pthread_t est réellement sur mac osx.Pthread id de pthread_self() ne correspond pas aux données du script dtrace
Répondre
De /usr/include/pthread.h
:
typedef __darwin_pthread_t pthread_t;
puis de /usr/include/sys/_types.h
:
struct _opaque_pthread_t {
long __sig;
struct __darwin_pthread_handler_rec* __cleanup_stack;
char __opaque[__PTHREAD_SIZE__];
};
typedef struct _opaque_pthread_t* __darwin_pthread_t;
Le code source est votre ami :)
donc je vais répondre à ma propre question, le curthread et les variables tid dans dtrace sont les valeurs de pointeur pour les structures de thread kernal, pour obtenir ces valeurs pour comparer dtrace avec les données de thread de l'espace utilisateur que je devais créer un ker nel extension pour obtenir ces valeurs internes pour les threads dans l'espace utilisateur.
En général, c'est une mauvaise idée car elle est non portable, pourrait facilement se casser si le noyau a été changé et représente probablement un risque pour la sécurité. Malheureusement, je n'ai pas trouvé un autre moyen de réaliser ce que je veux.
+ 1 pour trouver une solution ... serait encore mieux si vous pouviez le poster :) –
Que diriez-vous de quelque chose d'un peu plus élégant en utilisant le fournisseur pid
, qui traite du code de l'utilisateur?
# dtrace -n 'pid$target::pthread_self:return {printf("%p", arg1)}' -c 'java'
dtrace: description 'pid$target::pthread_self:return ' matched 1 probe
dtrace: pid 87631 has exited
CPU ID FUNCTION:NAME
0 90705 pthread_self:return 1053a7000
0 90705 pthread_self:return 1054ad000
2 90705 pthread_self:return 7fff7b479180
2 90705 pthread_self:return 7fff7b479180
2 90705 pthread_self:return 7fff7b479180
2 90705 pthread_self:return 7fff7b479180
2 90705 pthread_self:return 7fff7b479180
4 90705 pthread_self:return 10542a000
4 90705 pthread_self:return 10542a000
Huzzah!
arg1
se réfère à la valeur de retour dans la sonde, qui dans ce cas est un pointeur. Si vous avez besoin des informations, utilisez copyin(arg1, size_of_struct)
et attribuez le résultat à ce que vous pensez (voir le post @ Nikolai et n'oubliez pas que vous pouvez utiliser #include
dans les scripts DTrace tant que vous vous souvenez de l'option -C
sur la ligne de commande). Le nom du fournisseur pid$target
s'étend à pid1234
, où 1234
est l'ID de processus de la commande exécutée avec l'option -c
- dans ce cas, java
.
Pour plus d'informations, consultez Brendan Gregg's blog (qui est une grande source générale d'informations dtrace).
Notez que vous pouvez entrelacer cette sonde avec les sondes intégrées au noyau que vous utilisiez avant de suivre les changements de contexte - utilisez simplement le stockage local des threads ('self-> variable = ...') pour stocker les résultats de 'pthread_self()' et le référencer plus tard quand le changement de contexte est en cours. – Dan
Sur linux, la façon la plus fiable que j'ai trouvé pour identifier les changements de contexte de processus, est par la commande:
pidstat -hluwrt | grep "processname"
La colonne « tid » (# 3) est le même que « gettid() ', permettant ainsi au développeur de corréler directement quel thread utilise CPU et la commutation de contexte. Je suggère que lorsqu'un thread est engendré pour le programme à cracher la valeur gettid(): printf ("% lul", gettid()).
Les deux dernières colonnes, avant la ligne de commande du processus, sont les compteurs de changement de contexte 'cswtch/s' (volontaire) et 'nvcswtch/s' (non volontaire), par seconde.
Lorsque le 'cswtch/s' est haut (1000's), votre processus est de faire défiler le 'wake' et le 'sleep' de manière excessive. Vous voudrez peut-être envisager une sorte de tampon pour fournir les threads, ce qui permet de dormir plus longtemps. ex: Lorsque le tampon n'est PAS saturé, le fil reste plus longtemps endormi. Lorsque le tampon devient plein, le thread est éveillé jusqu'à ce que le tampon devienne vide. Lorsque le 'nvswtch/s' est haut (1000), c'est un symptôme que votre système est lourdement chargé et le thread individuel est en concurrence pour le temps CPU. Vous pouvez examiner la charge du serveur, la quantité de processus actifs & sur le serveur: 'top' ou 'htop' sont vos amis.
je trouve le script suivant débogage/optimisation de filetage de processus utile (sorties toutes les 20 secondes):
stdbuf -oL pidstat -hluwrt 20 | stdbuf -oL grep -e "processname" -e "^#"
Documentation pour gettid: (doc here)
Documentation pour pidstat: (doc here)
Documentation pour stdbuf: (doc here)
Évidemment votre réponse indique pourquoi vous ne pourriez pas faire correspondre 'tid' et' pthread_self() ', mais je crois que ma solution ci-dessous gère le problème que vous essayiez de comprendre. Pourriez-vous jeter un coup d'oeil? Merci! – Dan