[PATCH] Export per-thread resource usage via sysctl
John Baldwin
jhb at freebsd.org
Mon Jul 18 16:00:43 UTC 2011
On Saturday, July 16, 2011 8:04:58 am Alexander Best wrote:
> On Sat Jul 16 11, Pan Tsu wrote:
> > Alexander Best <arundel at freebsd.org> writes:
> >
> > > On Fri Jul 15 11, John Baldwin wrote:
> > >> This change exports each individual thread's resource usage via sysctl when
> > >> individual threads are requested via KERN_PROC_INC_THREAD. This generally
> > >> works correctly with 'top -m io' after the previous change to revert top(1)
> > >> back to using KERN_PROC_PROC when threads are not enabled. There is one issue
> > >> in that top doesn't necessarily DTRT when disabling/enabling threads via 'H'
> > >> at runtime while in io mode. I may do some further work to clean that up.
> > >> However, for just top run it will now show per-thread stats instead of
> > >> duplicating the per-process stats for each thread.
> > >
> > > i'm not sure, if i understand what the patch is supposed to do. however after
> > > applying it, and recompiling/reinstalling the kernel, 'top -mio' displays the
> > > same stats for each thread of a process. if i understood you correctly, each
> > > thread should have individual stats.
> > >
> > > i'm running r224068 on amd64 and just reinstalled 'top'. anything i am missing?
> >
> > FWIW, I see different numbers for a few threads of firefox-bin with top-3.8b1.
> >
> > http://img233.imageshack.us/img233/1570/81482202.png
> >
> > Which is an improvement compared to how all threads showed same numbers
> > before applying the patch.
>
> hmmm...not here. i did the following: 'top -mio -b -H -d2 999999' and had a
> look at the second output, where if found these lines:
Hmm, I never saw that. However, I do need this patch to top to get consistently sane numbers
(otherwise top picks one thread as the old thread for all threads causing diffs):
Index: machine.c
===================================================================
--- machine.c (revision 224062)
+++ machine.c (working copy)
@@ -235,6 +235,7 @@ static int *pcpu_cpu_states;
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
+static int compare_tid(const void *a, const void *b);
static const char *format_nice(const struct kinfo_proc *pp);
static void getsysctl(const char *name, void *ptr, size_t len);
static int swapmode(int *retavail, int *retfree);
@@ -557,7 +558,7 @@ get_old_proc(struct kinfo_proc *pp)
* cache it.
*/
oldpp = bsearch(&pp, previous_pref, previous_proc_count,
- sizeof(*previous_pref), compare_pid);
+ sizeof(*previous_pref), ps.thread ? compare_tid : compare_pid);
if (oldpp == NULL) {
pp->ki_udata = NOPROC;
return (NULL);
@@ -652,7 +653,7 @@ get_process_info(struct system_info *si, struct pr
previous_pref[i] = &previous_procs[i];
bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs));
qsort(previous_pref, nproc, sizeof(*previous_pref),
- compare_pid);
+ ps.thread ? compare_tid : compare_pid);
}
previous_proc_count = nproc;
@@ -1059,6 +1060,18 @@ compare_pid(const void *p1, const void *p2)
return ((*pp1)->ki_pid - (*pp2)->ki_pid);
}
+static int
+compare_tid(const void *p1, const void *p2)
+{
+ const struct kinfo_proc * const *pp1 = p1;
+ const struct kinfo_proc * const *pp2 = p2;
+
+ if ((*pp2)->ki_tid < 0 || (*pp1)->ki_tid < 0)
+ abort();
+
+ return ((*pp1)->ki_tid - (*pp2)->ki_tid);
+}
+
/*
* proc_compare - comparison function for "qsort"
* Compares the resource consumption of two processes using five
However, using this test app:
#include <sys/types.h>
#include <err.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFER_LEN 16384
#define FILE_LEN (BUFFER_LEN * 128)
char buffer[BUFFER_LEN];
int fd;
static void *
work(void *arg)
{
int mode = (intptr_t)arg;
ssize_t result;
off_t offset;
static const char* names[] = { "idle", "hog", "read", "write" };
pthread_set_name_np(pthread_self(), names[mode]);
offset = 0;
for (;;) {
switch (mode) {
case 0:
sleep(60);
break;
case 1:
pthread_yield();
break;
case 2:
case 3:
if (mode == 2)
result = pread(fd, buffer, sizeof(buffer),
offset);
else
result = pwrite(fd, buffer, sizeof(buffer),
offset);
if (result < 0)
warn("%s", mode == 2 ? "pread" : "pwrite");
offset += sizeof(buffer);
if (offset >= FILE_LEN)
offset = 0;
usleep(1000 * 100);
break;
}
}
return (NULL);
}
int
main(int ac, char **av)
{
pthread_t thread;
char template[] = "/tmp/t.XXXXXXXX";
int error, flags;
fd = mkstemp(template);
if (fd < 0)
err(1, "mkstemp");
if (unlink(template) < 0)
err(1, "unlink(%s)", template);
if (ftruncate(fd, FILE_LEN) < 0)
err(1, "ftruncate");
flags = fcntl(fd, F_GETFL);
if (flags < 0)
err(1, "fcntl(F_GETFL)");
if (fcntl(fd, F_SETFL, flags | O_DIRECT) < 0)
err(1, "fcntl(F_SETFL, O_DIRECT)");
printf("PID: %ld\n", (long)getpid());
error = pthread_create(&thread, NULL, work, (void *)0);
if (error)
errc(1, error, "pthread_create");
/*
error = pthread_create(&thread, NULL, work, (void *)1);
if (error)
errc(1, error, "pthread_create");
*/
error = pthread_create(&thread, NULL, work, (void *)2);
if (error)
errc(1, error, "pthread_create");
(void)work((void *)3);
return (0);
}
I get top output like so with this patch and the above patch applied to the
latest top:
PID USERNAME VCSW IVCSW READ WRITE FAULT TOTAL PERCENT COMMAND
25003 jhb 20 0 0 6 0 6 75.00% {write}
25003 jhb 21 0 1 0 0 1 12.50% {read}
25003 jhb 0 0 0 0 0 0 0.00% {idle}
Without the top patch I get bogus output like so:
25003 jhb 20 0 0 0 0 0 -0.00% {write}
25003 jhb 41 5 34 -75 0 -41 33.33% {read}
25003 jhb -2326 -1 -7 -75 0 -82 66.67% {idle}
--
John Baldwin
More information about the freebsd-current
mailing list