summaryrefslogtreecommitdiff
path: root/libpagemap
diff options
context:
space:
mode:
authorThierry Strudel <tstrudel@google.com>2015-12-02 23:53:00 +0000
committerandroid-build-merger <android-build-merger@google.com>2015-12-02 23:53:00 +0000
commitc641ee41319181e02e3a9afc2fc93d3989d1d41e (patch)
tree7ceeaee72940184ec50695e704d75bdec1dfb838 /libpagemap
parent002efefd9d24da9740667530350d04b4ff3ee2b1 (diff)
parent6ca5d6992307ac6d063e4a7a1f0457afb88e033c (diff)
downloadextras-c641ee41319181e02e3a9afc2fc93d3989d1d41e.tar.gz
procrank: add proportional swap accounting am: 08ea6e722b
am: 6ca5d69923 * commit '6ca5d6992307ac6d063e4a7a1f0457afb88e033c': procrank: add proportional swap accounting
Diffstat (limited to 'libpagemap')
-rw-r--r--libpagemap/include/pagemap/pagemap.h30
-rw-r--r--libpagemap/pm_map.c10
-rw-r--r--libpagemap/pm_memusage.c103
-rw-r--r--libpagemap/pm_process.c9
4 files changed, 148 insertions, 4 deletions
diff --git a/libpagemap/include/pagemap/pagemap.h b/libpagemap/include/pagemap/pagemap.h
index 9063b1e1..4de2b4b6 100644
--- a/libpagemap/include/pagemap/pagemap.h
+++ b/libpagemap/include/pagemap/pagemap.h
@@ -21,9 +21,19 @@
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/types.h>
+#include <sys/queue.h>
__BEGIN_DECLS
+typedef struct pm_proportional_swap pm_proportional_swap_t;
+
+typedef struct pm_swap_offset pm_swap_offset_t;
+
+struct pm_swap_offset {
+ unsigned int offset;
+ SIMPLEQ_ENTRY(pm_swap_offset) simpleqe;
+};
+
typedef struct pm_memusage pm_memusage_t;
/* Holds the various metrics for memory usage of a process or a mapping. */
@@ -33,12 +43,32 @@ struct pm_memusage {
size_t pss;
size_t uss;
size_t swap;
+ /* if non NULL then use swap_offset_list to compute proportional swap */
+ pm_proportional_swap_t *p_swap;
+ SIMPLEQ_HEAD(simpleqhead, pm_swap_offset) swap_offset_list;
+};
+
+typedef struct pm_swapusage pm_swapusage_t;
+struct pm_swapusage {
+ size_t proportional;
+ size_t unique;
};
/* Clears a memusage. */
void pm_memusage_zero(pm_memusage_t *mu);
/* Adds one memusage (a) to another (b). */
void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b);
+/* Adds a swap offset */
+void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset);
+/* Enable proportional swap computing. */
+void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap);
+/* Computes and return the proportional swap */
+void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su);
+void pm_memusage_pswap_free(pm_memusage_t *mu);
+/* Initialize a proportional swap computing handle:
+ assumes only 1 swap device, total swap size of this device in bytes to be given as argument */
+pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size);
+void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap);
typedef struct pm_kernel pm_kernel_t;
typedef struct pm_process pm_process_t;
diff --git a/libpagemap/pm_map.c b/libpagemap/pm_map.c
index c6a17981..301a1cc3 100644
--- a/libpagemap/pm_map.c
+++ b/libpagemap/pm_map.c
@@ -42,12 +42,13 @@ int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
if (error) return error;
pm_memusage_zero(&usage);
+ pm_memusage_pswap_init_handle(&usage, usage_out->p_swap);
for (i = 0; i < len; i++) {
usage.vss += map->proc->ker->pagesize;
if (!PM_PAGEMAP_PRESENT(pagemap[i]) &&
- !PM_PAGEMAP_SWAPPED(pagemap[i]))
+ !PM_PAGEMAP_SWAPPED(pagemap[i]))
continue;
if (!PM_PAGEMAP_SWAPPED(pagemap[i])) {
@@ -70,6 +71,7 @@ int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
usage.uss += (count == 1) ? (map->proc->ker->pagesize) : (0);
} else {
usage.swap += map->proc->ker->pagesize;
+ pm_memusage_pswap_add_offset(&usage, PM_PAGEMAP_SWAP_OFFSET(pagemap[i]));
}
}
@@ -77,7 +79,7 @@ int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
error = 0;
-out:
+out:
free(pagemap);
return error;
@@ -101,13 +103,13 @@ int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out) {
if (error) return error;
pm_memusage_zero(&ws);
-
+
for (i = 0; i < len; i++) {
error = pm_kernel_flags(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
&flags);
if (error) goto out;
- if (!(flags & PM_PAGE_REFERENCED))
+ if (!(flags & PM_PAGE_REFERENCED))
continue;
error = pm_kernel_count(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
diff --git a/libpagemap/pm_memusage.c b/libpagemap/pm_memusage.c
index ea2a003c..70cfedec 100644
--- a/libpagemap/pm_memusage.c
+++ b/libpagemap/pm_memusage.c
@@ -14,10 +14,37 @@
* limitations under the License.
*/
+#include <stdlib.h>
+#include <unistd.h>
+
#include <pagemap/pagemap.h>
+#define SIMPLEQ_INSERT_SIMPLEQ_TAIL(head_a, head_b) \
+ do { \
+ if (!SIMPLEQ_EMPTY(head_b)) { \
+ if ((head_a)->sqh_first == NULL) \
+ (head_a)->sqh_first = (head_b)->sqh_first; \
+ *(head_a)->sqh_last = (head_b)->sqh_first; \
+ (head_a)->sqh_last = (head_b)->sqh_last; \
+ } \
+ } while (/*CONSTCOND*/0)
+
+/* We use an array of int to store the references to a given offset in the swap
+ 1 GiB swap means 512KiB size array: offset are the index */
+typedef unsigned short pm_pswap_refcount_t;
+struct pm_proportional_swap {
+ unsigned int array_size;
+ pm_pswap_refcount_t *offset_array;
+};
+
void pm_memusage_zero(pm_memusage_t *mu) {
mu->vss = mu->rss = mu->pss = mu->uss = mu->swap = 0;
+ mu->p_swap = NULL;
+ SIMPLEQ_INIT(&mu->swap_offset_list);
+}
+
+void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap) {
+ mu->p_swap = p_swap;
}
void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) {
@@ -26,4 +53,80 @@ void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) {
a->pss += b->pss;
a->uss += b->uss;
a->swap += b->swap;
+ SIMPLEQ_INSERT_SIMPLEQ_TAIL(&a->swap_offset_list, &b->swap_offset_list);
+}
+
+pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size)
+{
+ pm_proportional_swap_t *p_swap = NULL;
+
+ p_swap = malloc(sizeof(pm_proportional_swap_t));
+ if (p_swap == NULL) {
+ fprintf(stderr, "Error allocating proportional swap.\n");
+ } else {
+ p_swap->array_size = swap_size / getpagesize();
+ p_swap->offset_array = calloc(p_swap->array_size, sizeof(pm_pswap_refcount_t));
+ if (p_swap->offset_array == NULL) {
+ fprintf(stderr, "Error allocating proportional swap offset array.\n");
+ free(p_swap);
+ p_swap = NULL;
+ }
+ }
+
+ return p_swap;
+}
+
+void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap) {
+ if (p_swap) {
+ free(p_swap->offset_array);
+ free(p_swap);
+ }
+}
+
+void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset) {
+ pm_swap_offset_t *soff;
+
+ if (mu->p_swap == NULL)
+ return;
+
+ if (offset > mu->p_swap->array_size) {
+ fprintf(stderr, "SWAP offset %d is out of swap bounds.\n", offset);
+ return;
+ } else {
+ if (mu->p_swap->offset_array[offset] == USHRT_MAX) {
+ fprintf(stderr, "SWAP offset %d ref. count if overflowing ushort type.\n", offset);
+ } else {
+ mu->p_swap->offset_array[offset]++;
+ }
+ }
+
+ soff = malloc(sizeof(pm_swap_offset_t));
+ if (soff) {
+ soff->offset = offset;
+ SIMPLEQ_INSERT_TAIL(&mu->swap_offset_list, soff, simpleqe);
+ }
+}
+
+void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su) {
+
+ int pagesize = getpagesize();
+ pm_swap_offset_t *elem;
+
+ if (su == NULL)
+ return;
+
+ su->proportional = su->unique = 0;
+ SIMPLEQ_FOREACH(elem, &mu->swap_offset_list, simpleqe) {
+ su->proportional += pagesize / mu->p_swap->offset_array[elem->offset];
+ su->unique += mu->p_swap->offset_array[elem->offset] == 1 ? pagesize : 0;
+ }
+}
+
+void pm_memusage_pswap_free(pm_memusage_t *mu) {
+ pm_swap_offset_t *elem = SIMPLEQ_FIRST(&mu->swap_offset_list);
+ while (elem) {
+ SIMPLEQ_REMOVE_HEAD(&mu->swap_offset_list, simpleqe);
+ free(elem);
+ elem = SIMPLEQ_FIRST(&mu->swap_offset_list);
+ }
}
diff --git a/libpagemap/pm_process.c b/libpagemap/pm_process.c
index b8e06c14..3c5c3914 100644
--- a/libpagemap/pm_process.c
+++ b/libpagemap/pm_process.c
@@ -81,6 +81,10 @@ int pm_process_usage_flags(pm_process_t *proc, pm_memusage_t *usage_out,
return -1;
pm_memusage_zero(&usage);
+ pm_memusage_pswap_init_handle(&usage, usage_out->p_swap);
+
+ pm_memusage_zero(&map_usage);
+ pm_memusage_pswap_init_handle(&map_usage, usage_out->p_swap);
for (i = 0; i < proc->num_maps; i++) {
error = pm_map_usage_flags(proc->maps[i], &map_usage, flags_mask,
@@ -185,6 +189,11 @@ int pm_process_workingset(pm_process_t *proc,
if (ws_out) {
pm_memusage_zero(&ws);
+ pm_memusage_pswap_init_handle(&ws, ws_out->p_swap);
+
+ pm_memusage_zero(&map_ws);
+ pm_memusage_pswap_init_handle(&map_ws, ws_out->p_swap);
+
for (i = 0; i < proc->num_maps; i++) {
error = pm_map_workingset(proc->maps[i], &map_ws);
if (error) return error;