From 7341494707810f709855ea85ce03a8ec3ac8dbaf Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 21 Oct 2008 07:00:00 -0700 Subject: Initial Contribution --- showslab/Android.mk | 15 ++ showslab/MODULE_LICENSE_APACHE2 | 0 showslab/NOTICE | 190 ++++++++++++++++++++++ showslab/showslab.c | 351 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 showslab/Android.mk create mode 100644 showslab/MODULE_LICENSE_APACHE2 create mode 100644 showslab/NOTICE create mode 100644 showslab/showslab.c (limited to 'showslab') diff --git a/showslab/Android.mk b/showslab/Android.mk new file mode 100644 index 00000000..c914a8b6 --- /dev/null +++ b/showslab/Android.mk @@ -0,0 +1,15 @@ +# Copyright 2007 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= showslab.c +LOCAL_SHARED_LIBRARIES := +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) + +LOCAL_MODULE_TAGS := debug + +LOCAL_MODULE:= showslab + +include $(BUILD_EXECUTABLE) + diff --git a/showslab/MODULE_LICENSE_APACHE2 b/showslab/MODULE_LICENSE_APACHE2 new file mode 100644 index 00000000..e69de29b diff --git a/showslab/NOTICE b/showslab/NOTICE new file mode 100644 index 00000000..c5b1efa7 --- /dev/null +++ b/showslab/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/showslab/showslab.c b/showslab/showslab.c new file mode 100644 index 00000000..9c9e60eb --- /dev/null +++ b/showslab/showslab.c @@ -0,0 +1,351 @@ +#include +#include +#include +#include +#include +#include +#include + +#define STRINGIFY_ARG(a) #a +#define STRINGIFY(a) STRINGIFY_ARG(a) + +#define DEF_SORT_FUNC sort_nr_objs +#define SLABINFO_LINE_LEN 512 /* size of longest line */ +#define SLABINFO_NAME_LEN 32 /* cache name size (will truncate) */ +#define SLABINFO_FILE "/proc/slabinfo" +#define DEF_NR_ROWS 15 /* default nr of caches to show */ + +/* object representing a slab cache (each line of slabinfo) */ +struct slab_info { + char name[SLABINFO_NAME_LEN]; /* name of this cache */ + struct slab_info *next; + unsigned long nr_pages; /* size of cache in pages */ + unsigned long nr_objs; /* number of objects in this cache */ + unsigned long nr_active_objs; /* number of active objects */ + unsigned long obj_size; /* size of each object */ + unsigned long objs_per_slab; /* number of objects per slab */ + unsigned long nr_slabs; /* number of slabs in this cache */ + unsigned long use; /* percent full: total / active */ +}; + +/* object representing system-wide statistics */ +struct slab_stat { + unsigned long total_size; /* size of all objects */ + unsigned long active_size; /* size of all active objects */ + unsigned long nr_objs; /* total number of objects */ + unsigned long nr_active_objs; /* total number of active objects */ + unsigned long nr_slabs; /* total number of slabs */ + unsigned long nr_active_slabs; /* total number of active slabs*/ + unsigned long nr_caches; /* number of caches */ + unsigned long nr_active_caches; /* number of active caches */ + unsigned long avg_obj_size; /* average object size */ + unsigned long min_obj_size; /* size of smallest object */ + unsigned long max_obj_size; /* size of largest object */ +}; + +typedef int (*sort_t)(const struct slab_info *, const struct slab_info *); +static sort_t sort_func; + +/* + * get_slabinfo - open, read, and parse a slabinfo 2.x file, which has the + * following format: + * + * slabinfo - version: 2.1 + * + * : tunables + * : slabdata + * + * Returns the head of the new list of slab_info structures, or NULL on error. + */ +static struct slab_info * get_slabinfo(struct slab_stat *stats) +{ + struct slab_info *head = NULL, *p = NULL, *prev = NULL; + FILE *slabfile; + char line[SLABINFO_LINE_LEN]; + unsigned int major, minor; + + slabfile = fopen(SLABINFO_FILE, "r"); + if (!slabfile) { + perror("fopen"); + return NULL; + } + + if (!fgets(line, SLABINFO_LINE_LEN, slabfile)) { + fprintf(stderr, "cannot read from " SLABINFO_FILE "\n"); + return NULL; + } + + if (sscanf(line, "slabinfo - version: %u.%u", &major, &minor) != 2) { + fprintf(stderr, "unable to parse slabinfo version!\n"); + return NULL; + } + + if (major != 2 || minor > 1) { + fprintf(stderr, "we only support slabinfo 2.0 and 2.1!\n"); + return NULL; + } + + stats->min_obj_size = INT_MAX; + + while (fgets(line, SLABINFO_LINE_LEN, slabfile)) { + unsigned long nr_active_slabs, pages_per_slab; + int ret; + + if (line[0] == '#') + continue; + + p = malloc(sizeof (struct slab_info)); + if (!p) { + perror("malloc"); + head = NULL; + break; + } + if (stats->nr_caches++ == 0) + head = prev = p; + + ret = sscanf(line, "%" STRINGIFY(SLABINFO_NAME_LEN) "s" + " %lu %lu %lu %lu %lu : tunables %*d %*d %*d : \ + slabdata %lu %lu %*d", p->name, + &p->nr_active_objs, &p->nr_objs, + &p->obj_size, &p->objs_per_slab, + &pages_per_slab, + &nr_active_slabs, + &p->nr_slabs); + + if (ret != 8) { + fprintf(stderr, "unrecognizable data in slabinfo!\n"); + head = NULL; + break; + } + + if (p->obj_size < stats->min_obj_size) + stats->min_obj_size = p->obj_size; + if (p->obj_size > stats->max_obj_size) + stats->max_obj_size = p->obj_size; + + p->nr_pages = p->nr_slabs * pages_per_slab; + + if (p->nr_objs) { + p->use = 100 * p->nr_active_objs / p->nr_objs; + stats->nr_active_caches++; + } else + p->use = 0; + + stats->nr_objs += p->nr_objs; + stats->nr_active_objs += p->nr_active_objs; + stats->total_size += p->nr_objs * p->obj_size; + stats->active_size += p->nr_active_objs * p->obj_size; + stats->nr_slabs += p->nr_slabs; + stats->nr_active_slabs += nr_active_slabs; + + prev->next = p; + prev = p; + } + + if (fclose(slabfile)) + perror("fclose"); + + if (p) + p->next = NULL; + if (stats->nr_objs) + stats->avg_obj_size = stats->total_size / stats->nr_objs; + + return head; +} + +/* + * free_slablist - deallocate the memory associated with each node in the + * provided slab_info linked list + */ +static void free_slablist(struct slab_info *list) +{ + while (list) { + struct slab_info *temp = list->next; + free(list); + list = temp; + } +} + +static struct slab_info *merge_objs(struct slab_info *a, struct slab_info *b) +{ + struct slab_info list; + struct slab_info *p = &list; + + while (a && b) { + if (sort_func(a, b)) { + p->next = a; + p = a; + a = a->next; + } else { + p->next = b; + p = b; + b = b->next; + } + } + + p->next = (a == NULL) ? b : a; + return list.next; +} + +/* + * slabsort - merge sort the slab_info linked list based on sort_func + */ +static struct slab_info *slabsort(struct slab_info *list) +{ + struct slab_info *a, *b; + + if (!list || !list->next) + return list; + + a = list; + b = list->next; + + while (b && b->next) { + list = list->next; + b = b->next->next; + } + + b = list->next; + list->next = NULL; + + return merge_objs(slabsort(a), slabsort(b)); +} + +/* + * Sort Routines. Each of these should be associated with a command-line + * search option. The functions should fit the prototype: + * + * int sort_foo(const struct slab_info *a, const struct slab_info *b) + * + * They return zero if the first parameter is smaller than the second. + * Otherwise, they return nonzero. + */ + +static int sort_name(const struct slab_info *a, const struct slab_info *b) +{ + return (strcmp(a->name, b->name) < 0 ) ? 1: 0; +} + +#define BUILD_SORT_FUNC(VAL) \ + static int sort_ ## VAL \ + (const struct slab_info *a, const struct slab_info *b) { \ + return (a-> VAL > b-> VAL); } + +BUILD_SORT_FUNC(nr_objs) +BUILD_SORT_FUNC(nr_active_objs) +BUILD_SORT_FUNC(obj_size) +BUILD_SORT_FUNC(objs_per_slab) +BUILD_SORT_FUNC(nr_slabs) +BUILD_SORT_FUNC(use) +BUILD_SORT_FUNC(nr_pages) + +/* + * set_sort_func - return the slab_sort_func that matches the given key. + * On unrecognizable key, the call returns NULL. + */ +static void * set_sort_func(char key) +{ + switch (tolower(key)) { + case 'a': + return sort_nr_active_objs; + case 'c': + return sort_nr_pages; + case 'l': + return sort_nr_slabs; + case 'n': + return sort_name; + case 'o': + return sort_nr_objs; + case 'p': + return sort_objs_per_slab; + case 's': + return sort_obj_size; + case 'u': + return sort_use; + default: + return NULL; + } +} + +int main(int argc, char *argv[]) +{ + struct slab_info *list, *p; + struct slab_stat stats = { .nr_objs = 0 }; + unsigned int page_size = getpagesize() / 1024, nr_rows = DEF_NR_ROWS, i; + + sort_func = DEF_SORT_FUNC; + + if (argc > 1) { + /* FIXME: Ugh. */ + if (argc == 3 && !strcmp(argv[1], "-n")) { + errno = 0; + nr_rows = (unsigned int) strtoul(argv[2], NULL, 0); + if (errno) { + perror("strtoul"); + exit(EXIT_FAILURE); + } + } + else if (argc == 3 && !strcmp(argv[1], "-s")) + sort_func = set_sort_func(argv[2][0]) ? : DEF_SORT_FUNC; + else { + fprintf(stderr, "usage: %s [options]\n\n", argv[0]); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -s S specify sort criteria S\n"); + fprintf(stderr, " -h display this help\n\n"); + fprintf(stderr, "Valid sort criteria:\n"); + fprintf(stderr, " a: number of Active objects\n"); + fprintf(stderr, " c: Cache size\n"); + fprintf(stderr, " l: number of sLabs\n"); + fprintf(stderr, " n: Name\n"); + fprintf(stderr, " o: number of Objects\n"); + fprintf(stderr, " p: objects Per slab\n"); + fprintf(stderr, " s: object Size\n"); + fprintf(stderr, " u: cache Utilization\n"); + exit(EXIT_FAILURE); + } + } + + list = get_slabinfo (&stats); + if (!list) + exit(EXIT_FAILURE); + + printf(" Active / Total Objects (%% used) : %lu / %lu (%.1f%%)\n" + " Active / Total Slabs (%% used) : %lu / %lu (%.1f%%)\n" + " Active / Total Caches (%% used) : %lu / %lu (%.1f%%)\n" + " Active / Total Size (%% used) : %.2fK / %.2fK (%.1f%%)\n" + " Min / Avg / Max Object Size : %.2fK / %.2fK / %.2fK\n\n", + stats.nr_active_objs, + stats.nr_objs, + 100.0 * stats.nr_active_objs / stats.nr_objs, + stats.nr_active_slabs, + stats.nr_slabs, + 100.0 * stats.nr_active_slabs / stats.nr_slabs, + stats.nr_active_caches, + stats.nr_caches, + 100.0 * stats.nr_active_caches / stats.nr_caches, + stats.active_size / 1024.0, + stats.total_size / 1024.0, + 100.0 * stats.active_size / stats.total_size, + stats.min_obj_size / 1024.0, + stats.avg_obj_size / 1024.0, + stats.max_obj_size / 1024.0); + + printf("%6s %6s %4s %8s %6s %8s %10s %-23s\n", + "OBJS", "ACTIVE", "USE", "OBJ SIZE", "SLABS", + "OBJ/SLAB", "CACHE SIZE", "NAME"); + + p = list = slabsort(list); + for (i = 0; i < nr_rows && p; i++) { + printf("%6lu %6lu %3lu%% %7.2fK %6lu %8lu %9luK %-23s\n", + p->nr_objs, p->nr_active_objs, p->use, + p->obj_size / 1024.0, p->nr_slabs, + p->objs_per_slab, + p->nr_pages * page_size, + p->name); + p = p->next; + } + + free_slablist(list); + + return 0; +} -- cgit v1.2.3