G'Day Eric,

On Wed, 18 Jan 2006, Eric Lowe wrote:

> Coming into this thread late since I'm returning for vacation...
>
> On Thu, Jan 12, 2006 at 02:55:52AM +1100, Brendan Gregg wrote:
> |
> | I want segvn hit rate. There must be a function in the segvn code
> | somewhere that checks whether a page is already in the page cache or not,
>
> So in a nutshell, what you want to know is, for mmap() faults what is the
> hit rate in the page cache?

At the moment, yes.

> | which would be ideal for DTrace to trace. I would expect this to be
> | related to when a page fault occurs from a segvn mapping.
> |
> | I've looked at a number of functions, including the following,
> |
> |     segvn_fault
> |     page_exists
> |     page_lookup
> |     page_reclaim
> |     ufs_getpage
> |     ufs_getpage_ra
> |     seg_plookup
>
> It's probably easier to track the number of misses and compare to the
> number of faults since there are so many places you can find a page.
> To do that you can just look for calls to page_create_va() from the
> context of {segvn_fault,segvn_faulta}.

Yes, page_create_va() is interesting, but I'm not getting enough faults
that end up calling it (which you explain below).

> Some other notes..
>
> Regarding the number of faults. The read-ahead is completely done within
> the filesystem layer in the current architecture so the behavior is highly
> FS specific.

Yep, and I'm back to ufs_getpage_ra() again - been here a few times over
the past year...

> Look for the callers to hat_memload() and hat_memload_array()
> in the system -- the read-ahead appears to be loading multiple mappings when
> the pages are read in. Further accesses therefore don't generate faults
> to these pages.

Hooray! I suspected the cache-read-ahead was loading the mappings
before they faulted; and now I'm using hat_memload() to see all of the
segvn mapping events. :-)

I'm currently using the following calculations,

   segvn_miss == io strategy while in {segvn_fault,segvn_faulta}
   segvn_hit == hat_memload in {segvn_fault,segvn_faulta} - segvn_miss

and so far, so good (need to add hat_memload_array and check for others).
I've attached a draft script that tests the above; if anyone can find me a
scenario where it doesn't work, please email...

> If OTOH you have a 100% hit rate in the cache I would
> expect to see ~1000 faults for a 8M segment on SPARC or 4M on x86 since
> you would get one fault and one attach per page. These would be counted
> as minor faults.

I'm never seeing all the faults due to the cache-read-ahead (ok, I should
really say FS-read-ahead-from-cache). Only by using hat_memload() I can
see all 1000 mappings..

The way a freshly written file (as opposed to a freshly mounted file)
changed the number of faults really threw me. Still haven't put my finger
on why, but I suspect it's a cache placement policy (maybe MPSS - I need
to go test this on SPARC where I have trapstat. :)

> Hope this helps.

This certainly helps!

thanks,

Brendan

[Sydney, Australia]

#!/usr/sbin/dtrace -s
/* todo: hat_memload_array */

#pragma D option quiet
#pragma D option defaultargs

inline int SCREEN = 21;

dtrace:::BEGIN
{
        lines = SCREEN + 1;
        secs = $1 ? $1 : 1;
        counts = $2 ? $2 : -1;
        first = 1;
        @hits = sum(0);
        @miss = sum(0);
}

profile:::tick-1sec
{
        secs--;
}

profile:::tick-1sec
/first || (secs == 0 && lines > SCREEN)/
{
        printf("%10s %10s\n", "HITS", "MISSES");
        first = 0;
        lines = 0;
}

fbt::segvn_fault:entry,
fbt::segvn_faulta:entry
{
        self->segvn = 1;
}

fbt::hat_memload:entry
/self->segvn && args[2]->p_vnode->v_path != NULL/
{
        /*
         * hat_memload is interesting (thanks Eric L.) as we use it
         * to track the total number of page creates in segvn, so 
         * long as our context is segvn_fault. This value minus io
         * events is used as the hit rate.
         */
        @path[execname, stringof(args[2]->p_vnode->v_path)] = count();
        @hits = sum(1);
}

io:::start
/self->segvn/
{
        /* a segvn miss is an io event within a segvn_fault context */
        @iobytes[execname, args[2]->fi_pathname,
            args[0]->b_flags & B_READ ? "R" : "W"] = sum(args[0]->b_bcount);
        @miss = sum(args[0]->b_bcount / `_pagesize);
        @hits = sum(- (args[0]->b_bcount / `_pagesize));
}

fbt::segvn_fault:return,
fbt::segvn_faulta:return
/self->segvn/
{
        self->segvn = 0;
}

profile:::tick-1sec
/secs == 0/
{
        printa("[EMAIL PROTECTED] ", @hits);
        printa("[EMAIL PROTECTED]", @miss);
        trunc(@hits);
        trunc(@miss);
        @hits = sum(0);
        @miss = sum(0);
        secs = $1 ? $1 : 1;
        lines++;
        counts--;
}

dtrace:::END
{
        printf("hat_memload\n-----------\n");
        printf("%-16s %-50s %8s\n", "CMD", "PATH", "COUNT");
        printa("%-16s %-50s [EMAIL PROTECTED]", @path);

        printf("\nio:::start\n----------\n");
        printf("%-16s %32s %3s %10s\n", "CMD", "FILE", "DIR", "BYTES");
        printa("%-16s %32s %3s [EMAIL PROTECTED]", @iobytes);
}
_______________________________________________
perf-discuss mailing list
perf-discuss@opensolaris.org

Reply via email to