Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/fincore a utility to show in-core status of file pages



details:   https://anonhg.NetBSD.org/src/rev/2ecaa40de752
branches:  trunk
changeset: 771933:2ecaa40de752
user:      yamt <yamt%NetBSD.org@localhost>
date:      Fri Dec 09 15:17:34 2011 +0000

description:
a utility to show in-core status of file pages

diffstat:

 usr.bin/fincore/Makefile  |    5 +
 usr.bin/fincore/fincore.1 |  103 ++++++++++++++++++++++
 usr.bin/fincore/fincore.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 319 insertions(+), 0 deletions(-)

diffs (truncated from 331 to 300 lines):

diff -r 431975c546b1 -r 2ecaa40de752 usr.bin/fincore/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/fincore/Makefile  Fri Dec 09 15:17:34 2011 +0000
@@ -0,0 +1,5 @@
+#      $NetBSD: Makefile,v 1.1 2011/12/09 15:17:34 yamt Exp $
+
+PROG=  fincore
+
+.include <bsd.prog.mk>
diff -r 431975c546b1 -r 2ecaa40de752 usr.bin/fincore/fincore.1
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/fincore/fincore.1 Fri Dec 09 15:17:34 2011 +0000
@@ -0,0 +1,103 @@
+.\"    $NetBSD: fincore.1,v 1.1 2011/12/09 15:17:34 yamt Exp $
+.\"
+.\" Copyright (c)2011 YAMAMOTO Takashi,
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" ------------------------------------------------------------
+.Dd December 9, 2011
+.Dt FINCORE 1
+.Os
+.\" ------------------------------------------------------------
+.Sh NAME
+.Nm fincore
+.Nd query in-core status of file pages
+.\" ------------------------------------------------------------
+.Sh SYNOPSIS
+.Nm
+.Op Fl qs
+.Ar file ...
+.\" ------------------------------------------------------------
+.Sh DESCRIPTION
+The
+.Nm
+utility queries and displays in-core status of specified files.
+.Pp
+Note that the result can already be stale when being output due to other
+activities in the system.
+Thus it should be used only for advisary purposes.
+.Pp
+The
+.Nm
+utility accepts the following options.
+.Bl -tag -width hogehoge
+.It Fl q
+The quiet mode.
+Outputs nothing unless the file has in-core pages.
+.It Fl s
+The summary mode.
+Only shows number of pages.
+.El
+.\" ------------------------------------------------------------
+.Sh EXAMPLES
+The following example shows that /bin/cat and /bin/cp are fully cached in-core
+while the other executables are not in-core.
+numbers shown in the default output are page indexes in the file of
+each in-core pages.
+.Bd -literal
+% fincore /bin/c*
+/bin/cat: 0 1 2 3
+/bin/chio:
+/bin/chmod:
+/bin/cp: 0 1 2 3 4 5
+/bin/cpio:
+/bin/csh:
+% fincore -s /bin/c*
+/bin/cat: 4 / 4 in-core pages (100.00%)
+/bin/chio: 0 / 5 in-core pages (0.00%)
+/bin/chmod: 0 / 3 in-core pages (0.00%)
+/bin/cp: 6 / 6 in-core pages (100.00%)
+/bin/cpio: 0 / 36 in-core pages (0.00%)
+/bin/csh: 0 / 41 in-core pages (0.00%)
+.Ed
+.\" ------------------------------------------------------------
+.\".Sh HISTORY
+.\"The
+.\".Nm
+.\"utility first appeared in
+.\".Nx XXX .
+.\" ------------------------------------------------------------
+.\".Sh SEE ALSO
+.\".Xr XXX
+.\" ------------------------------------------------------------
+.Sh AUTHORS
+The
+.Nm
+utility is written by
+.An YAMAMOTO Takashi .
+.\" ------------------------------------------------------------
+.Sh BUGS
+The amount of CPU time the current implementation of
+.Nm
+utility would take is roughly proportional to the file sizes.
+Ideally it should be proportional to the number of in-core pages.
diff -r 431975c546b1 -r 2ecaa40de752 usr.bin/fincore/fincore.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/fincore/fincore.c Fri Dec 09 15:17:34 2011 +0000
@@ -0,0 +1,211 @@
+/*     $NetBSD: fincore.c,v 1.1 2011/12/09 15:17:34 yamt Exp $ */
+
+/*-
+ * Copyright (c) 2011 YAMAMOTO Takashi,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * a utility to query which file pages are cached
+ *
+ * inspired by:
+ *     http://net.doit.wisc.edu/~plonka/fincore/
+ *     http://www.usenix.org/events/lisa07/tech/plonka.html
+ */
+
+#include <sys/cdefs.h>
+#if defined(__NetBSD__)
+#ifndef lint
+__RCSID("$NetBSD: fincore.c,v 1.1 2011/12/09 15:17:34 yamt Exp $");
+#endif /* not lint */
+#endif /* defined(__NetBSD__) */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if !defined(__arraycount)
+#define        __arraycount(a) (sizeof(a)/sizeof(*a))
+#endif /* !defined(__arraycount) */
+
+size_t page_size;
+bool do_summary;
+bool be_quiet;
+
+/*
+ * fincore: query which pages of the file are in-core.
+ *
+ * this function is intended to be compatible with:
+ *     http://lwn.net/Articles/371538/
+ *     http://libprefetch.cs.ucla.edu/
+ *
+ * while this can be implemented in kernel much more efficiently, i'm not
+ * sure if making this a syscall in 2011 is a good idea.  this API does not
+ * seem scalable for sparsely cached huge files.  the expected scalability
+ * has been changed since the time when mincore was invented.
+ *
+ * some references:
+ *     http://wiki.postgresql.org/images/a/a2/Pgfincore_pgday10.pdf
+ */
+
+static int
+fincore(int fd, off_t startoff, off_t endoff, unsigned char *vec)
+{
+       off_t off;
+       size_t chunk_size;
+
+       for (off = startoff; off < endoff;
+           off += chunk_size, vec += chunk_size / page_size) {
+               void *vp;
+
+               chunk_size = MIN((off_t)(1024 * page_size), endoff - off);
+               vp = mmap(NULL, chunk_size, PROT_NONE, MAP_FILE|MAP_SHARED,
+                   fd, off);
+               if (vp == MAP_FAILED) {
+                       return -1;
+               }
+               if (mincore(vp, chunk_size,
+#if !defined(__linux__)
+                   (char *)
+#endif /* !defined(__linux__) */
+                   vec)) {
+                       munmap(vp, chunk_size);
+                       return -1;
+               }
+               if (munmap(vp, chunk_size)) {
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static void
+do_file(const char *name)
+{
+       unsigned char vec[4096];
+       struct stat st;
+       uintmax_t n;    /* number of pages in-core */
+       off_t off;
+       size_t chunk_size;
+       int fd;
+       bool header_done = false;
+
+       fd = open(name, O_RDONLY);
+       if (fd == -1) {
+               err(EXIT_FAILURE, "open %s", name);
+       }
+       if (fstat(fd, &st)) {
+               err(EXIT_FAILURE, "fstat %s", name);
+       }
+       n = 0;
+       for (off = 0; off < st.st_size; off += chunk_size) {
+               unsigned int i;
+
+               chunk_size = MIN(__arraycount(vec) * page_size,
+                   roundup(st.st_size - off, page_size));
+               if (fincore(fd, off, off + chunk_size, vec)) {
+                       printf("\n");
+                       err(EXIT_FAILURE, "fincore %s", name);
+               }
+               for (i = 0; i < chunk_size / page_size; i++) {
+                       if (vec[i] == 0) {
+                               continue;
+                       }
+                       if (!do_summary) {
+                               if (!header_done) {
+                                       printf("%s:", name);
+                                       header_done = true;
+                               }
+                               printf(" %ju",
+                                   (uintmax_t)(off / page_size + i));
+                       }
+                       n++;
+               }
+       }
+       close(fd);
+       if (do_summary && (n != 0 || !be_quiet)) {
+               const uintmax_t total = howmany(st.st_size, page_size);
+               const double pct = (total != 0) ? ((double)n / total * 100) : 0;
+
+               if (!header_done) {
+                       printf("%s:", name);
+                       header_done = true;
+               }
+               printf(" %ju / %ju in-core pages (%0.2f%%)", n, total, pct);
+       }
+       if (header_done) {
+               printf("\n");
+       } else if (!be_quiet) {
+               printf("%s: \n", name);
+       }
+}
+
+int
+/*ARGSUSED*/
+main(int argc, char *argv[])
+{
+       extern int optind;
+       long l;
+       int ch;
+



Home | Main Index | Thread Index | Old Index