📄 trace.c
字号:
case SInts: if (_e->time > prevts && _e->time <= newestts){ sx = time2x(_e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height / 2 - bottommargin)), Endsquare, Endsquare, 0, green, ZP); } break; case SInte: if (_e->time > prevts && _e->time <= newestts) { sx = time2x(_e->time); line(screen, addpt(p, Pt(sx, Height / 2 - bottommargin)), addpt(p, Pt(sx, Height - bottommargin)), Endsquare, Endsquare, 0, blue, ZP); } break; } } break; } } p.y += Height; } ts = prevts + scales[scaleno].littletics - (prevts % scales[scaleno].littletics); x = time2x(ts); while(x < Width){ p = screen->r.min; for(n = 0; n < ntasks; n++){ int height, width; /* p is upper left corner for this task */ if ((ts % scales[scaleno].scale) == 0){ height = 10 * Height; width = 1; }else if ((ts % scales[scaleno].bigtics) == 0){ height = 12 * Height; width = 0; }else{ height = 13 * Height; width = 0; } height >>= 4; line(screen, addpt(p, Pt(x, height)), addpt(p, Pt(x, Height - lineht)), Endsquare, Endsquare, width, cols[n % Ncolor][2], ZP); p.y += Height; } ts += scales[scaleno].littletics; x = time2x(ts); } rtime = screen->r; rtime.min.y = rtime.max.y - tinyfont->height + 2; draw(screen, rtime, bg, nil, ZP); ts = oldestts + scales[scaleno].bigtics - (oldestts % scales[scaleno].bigtics); x = time2x(ts); ss = 0; while(x < Width){ snprint(buf, sizeof(buf), "%t", ss); string(screen, addpt(p, Pt(x - stringwidth(tinyfont, buf)/2, - tinyfont->height - 1)), fg, ZP, tinyfont, buf); ts += scales[scaleno].bigtics; ss += scales[scaleno].bigtics; x = time2x(ts); } snprint(buf, sizeof(buf), "%t", now); string(screen, Pt(screen->r.max.x - stringwidth(mediumfont, buf), screen->r.min.y), fg, ZP, mediumfont, buf); flushimage(display, 1); prevts = newestts;}Task*newtask(ulong pid){ Task *t; char buf[64], *p; int fd,n; tasks = realloc(tasks, (ntasks + 1) * sizeof(Task)); assert(tasks); t = &tasks[ntasks++]; memset(t, 0, sizeof(Task)); t->events = nil; snprint(buf, sizeof buf, "/proc/%ld/status", pid); t->name = nil; fd = open(buf, OREAD); if (fd >= 0){ n = read(fd, buf, sizeof buf); if(n > 0){ p = buf + sizeof buf - 1; *p = 0; p = strchr(buf, ' '); if (p) *p = 0; t->name = strdup(buf); }else print("%s: %r\n", buf); close(fd); }else print("%s: %r\n", buf); t->pid = pid; prevts = 0; if (newwin){ fprint(wctlfd, "resize -dx %d -dy %d\n", Width + 20, (ntasks * Height) + 5); }else Height = ntasks ? Dy(screen->r)/ntasks : Dy(screen->r); return t;}voiddoevent(Task *t, Traceevent *ep){ int i, n; Event *event; vlong runt; t->tevents[ep->etype & 0xffff]++; n = t->nevents++; t->events = realloc(t->events, t->nevents*sizeof(Event)); assert(t->events); event = &t->events[n]; memmove(event, ep, sizeof(Traceevent)); event->etime = 0; switch(event->etype & 0xffff){ case SRelease: if (t->runthis > t->runmax) t->runmax = t->runthis; t->runthis = 0; break; case SSleep: case SYield: case SReady: case SSlice: for(i = n-1; i >= 0; i--) if (t->events[i].etype == SRun || t->events[i].etype == SEdf) break; if(i < 0 || t->events[i].etime != 0) break; runt = event->time - t->events[i].time; if(runt > 0){ t->events[i].etime = event->time; t->runtime += runt; t->total += runt; t->runthis += runt; t->runs++; } break; case SDead:print("task died %ld %t %s\n", event->pid, event->time, schedstatename[event->etype & 0xffff]); free(t->events); free(t->name); ntasks--; memmove(t, t+1, sizeof(Task)*(&tasks[ntasks]-t)); if (newwin) fprint(wctlfd, "resize -dx %d -dy %d\n", Width + 20, (ntasks * Height) + 5); else Height = ntasks ? Dy(screen->r)/ntasks : Dy(screen->r); prevts = 0; }}voiddrawtrace(void){ char *wsys, line[256]; int wfd, logfd; Mousectl *mousectl; Keyboardctl *keyboardctl; int scaleno; Rune r; int i, n; Task *t; Traceevent *ep; eventbuf = malloc(Nevents*sizeof(Traceevent)); assert(eventbuf); if((logfd = open(profdev, OREAD)) < 0) sysfatal("%s: Cannot open %s: %r\n", argv0, profdev); if(newwin){ if((wsys = getenv("wsys")) == nil) sysfatal("%s: Cannot find windowing system: %r\n", argv0); if((wfd = open(wsys, ORDWR)) < 0) sysfatal("%s: Cannot open windowing system: %r\n", argv0); snprint(line, sizeof(line), "new -pid %d -dx %d -dy %d", getpid(), Width + 20, Height + 5); line[sizeof(line) - 1] = '\0'; rfork(RFNAMEG); if(mount(wfd, -1, "/mnt/wsys", MREPL, line) < 0) sysfatal("%s: Cannot mount %s under /mnt/wsys: %r\n", argv0, line); if(bind("/mnt/wsys", "/dev", MBEFORE) < 0) sysfatal("%s: Cannot bind /mnt/wsys in /dev: %r\n", argv0); } if((wctlfd = open("/dev/wctl", OWRITE)) < 0) sysfatal("%s: Cannot open /dev/wctl: %r\n", argv0); if(initdraw(nil, nil, "trace") < 0) sysfatal("%s: initdraw failure: %r\n", argv0); Width = Dx(screen->r); Height = Dy(screen->r); if((mousectl = initmouse(nil, screen)) == nil) sysfatal("%s: cannot initialize mouse: %r\n", argv0); if((keyboardctl = initkeyboard(nil)) == nil) sysfatal("%s: cannot initialize keyboard: %r\n", argv0); colinit(); paused = 0; scaleno = 7; /* 100 milliseconds */ now = nsec(); for(;;) { Alt a[] = { { mousectl->c, nil, CHANRCV }, { mousectl->resizec, nil, CHANRCV }, { keyboardctl->c, &r, CHANRCV }, { nil, nil, CHANNOBLK }, }; switch (alt(a)) { case 0: continue; case 1: if(getwindow(display, Refnone) < 0) sysfatal("drawrt: Cannot re-attach window\n"); if(newwin){ if(Dx(screen->r) != Width || Dy(screen->r) != (ntasks * Height)){ fprint(2, "resize: x: have %d, need %d; y: have %d, need %d\n", Dx(screen->r), Width + 8, Dy(screen->r), (ntasks * Height) + 8); fprint(wctlfd, "resize -dx %d -dy %d\n", Width + 8, (ntasks * Height) + 8); } } else{ Width = Dx(screen->r); Height = ntasks? Dy(screen->r)/ntasks: Dy(screen->r); } break; case 2: switch(r){ case 'r': for(i = 0; i < ntasks; i++){ tasks[i].tstart = now; tasks[i].total = 0; tasks[i].runtime = 0; tasks[i].runmax = 0; tasks[i].runthis = 0; tasks[i].runs = 0; memset(tasks[i].tevents, 0, Nevent*sizeof(ulong)); } break; case 'p': paused ^= 1; prevts = 0; break; case '-': if (scaleno < nelem(scales) - 1) scaleno++; prevts = 0; break; case '+': if (scaleno > 0) scaleno--; prevts = 0; break; case 'q': threadexitsall(nil); case 'v': verbose ^= 1; default: break; } break; case 3: now = nsec(); while((n = read(logfd, eventbuf, Nevents*sizeof(Traceevent))) > 0){ assert((n % sizeof(Traceevent)) == 0); nevents = n / sizeof(Traceevent); for (ep = eventbuf; ep < eventbuf + nevents; ep++){ if ((ep->etype & 0xffff) >= Nevent){ print("%ld %t Illegal event %ld\n", ep->pid, ep->time, ep->etype & 0xffff); continue; } if (verbose) print("%ld %t %s\n", ep->pid, ep->time, schedstatename[ep->etype & 0xffff]); for(i = 0; i < ntasks; i++) if(tasks[i].pid == ep->pid) break; if(i == ntasks){ t = newtask(ep->pid); t->tstart = ep->time; }else t = &tasks[i]; doevent(t, ep); } } if(!paused) redraw(scaleno); } sleep(scales[scaleno].sleep); }}inttimeconv(Fmt *f){ char buf[128], *sign; vlong t; buf[0] = 0; switch(f->r) { case 'U': t = va_arg(f->args, vlong); break; case 't': // vlong in nanoseconds t = va_arg(f->args, vlong); break; default: return fmtstrcpy(f, "(timeconv)"); } if (t < 0) { sign = "-"; t = -t; }else sign = ""; if (t > S(1)){ t += OneRound; sprint(buf, "%s%d.%.3ds", sign, (int)(t / S(1)), (int)(t % S(1))/1000000); }else if (t > MS(1)){ t += MilliRound; sprint(buf, "%s%d.%.3dms", sign, (int)(t / MS(1)), (int)(t % MS(1))/1000); }else if (t > US(1)) sprint(buf, "%s%d.%.3dµs", sign, (int)(t / US(1)), (int)(t % US(1))); else sprint(buf, "%s%dns", sign, (int)t); return fmtstrcpy(f, buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -