2016-05-04 5 views
0

Je veux suivre par programme les piles de C pour Node.js (adresses JS de côté).Dtrace de C ne donne pas le même résultat de profilage par rapport à la ligne de commande

La commande suivante me donne des piles avec les symboles c++ résolus.

sudo dtrace -C -n 'profile-101 /pid == 13221/ { ustack() }' 

Le code C suivant renvoie uniquement des adresses pour le code C/C++ du noeud. Quel serait l'équivalent?

#include <dtrace.h> 
#include <signal.h> 
#include <stdio.h> 

struct ps_prochandle *g_pr; 
static dtrace_hdl_t* g_dtp; 

static int chewrec (const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) { 
    // A NULL rec indicates that we've processed the last record. 
    if (rec == NULL) { 
     return (DTRACE_CONSUME_NEXT); 
    } 
    return (DTRACE_CONSUME_THIS); 
} 

static const char* g_prog = 
    "#pragma D option switchrate=1000hz\n" 
    "profile-1ms /pid == 13221/ {\n" 
    "ustack();\n" 
    "}"; 

static int g_intr; 
static int g_exited; 

static void intr (int signo) { 
    g_intr = 1; 
} 


int main (int argc, char** argv) { 
    int err; 

    if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) { 
     fprintf(stderr, "failed to initialize dtrace: %s\n", dtrace_errmsg(NULL, err)); 
     return -1; 
    } 
    printf("Dtrace initialized\n"); 

    (void) dtrace_setopt(g_dtp, "bufsize", "4m"); 
    (void) dtrace_setopt(g_dtp, "aggsize", "4m"); 

    printf("dtrace options set\n"); 

    dtrace_prog_t* prog; 
    if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, DTRACE_C_CPP, 0, NULL)) == NULL) { 
     fprintf(stderr, "failed to compile dtrace program\n"); 
     return -1; 
    } else { 
     printf("dtrace program compiled\n"); 
    } 

    dtrace_proginfo_t info; 
    if (dtrace_program_exec(g_dtp, prog, &info) == -1) { 
     fprintf(stderr, "failed to enable dtrace probes\n"); 
     return -1; 
    } else { 
     printf("dtrace probes enabled\n"); 
    } 

    struct sigaction act; 
    (void) sigemptyset(&act.sa_mask); 
    act.sa_flags = 0; 
    act.sa_handler = intr; 
    (void) sigaction(SIGINT, &act, NULL); 
    (void) sigaction(SIGTERM, &act, NULL); 

    if (dtrace_go(g_dtp) != 0) { 
     fprintf(stderr, "could not start instrumentation\n"); 
     return -1; 
    } else { 
     printf("instrumentation started ..\n"); 
    } 

    int done = 0; 
    do { 
     if (!g_intr && !done) { 
     dtrace_sleep(g_dtp); 
     } 

     if (done || g_intr || g_exited) { 
     done = 1; 
     if (dtrace_stop(g_dtp) == -1) { 
      fprintf(stderr, "could not stop tracing\n"); 
      return -1; 
     } 
     } 

     switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) { 
     case DTRACE_WORKSTATUS_DONE: 
      done = 1; 
      break; 
     case DTRACE_WORKSTATUS_OKAY: 
      break; 
     default: 
      fprintf(stderr, "processing aborted"); 
      return -1; 
     } 
    } while (!done); 

    printf("closing dtrace\n"); 
    dtrace_close(g_dtp); 

    return 0; 
} 
+0

Il y a une chose appelée [ustack helpers] (https://www.joyent.com/blog/understanding-dtrace-ustack-helpers) qui devrait vous aider à accomplir une tâche, mais vous devez appeler 'jstack()' au lieu de 'ustack()' depuis votre code – myaut

+0

@myaut C'est un peu plus compliqué que ça, mais merci quand même. il y a peu de temps à la liste de diffusion dtrace, avec la réponse ci-dessous, qui a aussi votre composant – eljefedelrodeodeljefe

Répondre

1

Dans la liste DTrace-Mailing, Robert Mustacchi:

TL; DR résoudre vous-même des symboles dans l'espace utilisateur.

« Alors, tout le traitement de la résolution des symboles est toujours fait dans l'espace utilisateur. En autres termes, DTrace dans le noyau ne rassemble jamais adresses comme que vous voyez dans les cas où vous utilisez ustack et pas un gestionnaire ustack via l'action jstack() (jstack() ne renvoie également que des symboles pour les trames non natives .) Notez que si vous voulez voir les symboles spécifiques au JavaScript en plus des symboles natifs, vous aurez besoin pour utiliser jstack() dans vos exemples et pas ustack()

La façon dont ceux-ci vous pouvez effectuer ces Les mappages vont changer en fonction de sur quel système vous vous trouvez. Si vous regardez ce que DTrace fait sur illumos pour en imprimant les résultats de ustack() (http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libdtrace/common/dt_consume.c#1320), alors vous verrez qu'il utilise libproc et la fonction Plookup_by_addr() pour effectuer la traduction. Bien qu'il soit à noter que ni sont des interfaces stables, même si elles changent rarement. "