Considering RSS and Shared of statm is more accurate than using the ratio for RSS.
And, there are many apis for getting memory usage in procfs.
Of course, resourced should know all kinds of memory information
depending on the situations.
For instance, when LMK predicts secured memory usage after killing victims,
it should check real ram usage which considers zram compression ratio.
On the other hand, if someone wants to know memory usage,
it can check approximate memory usage from /proc/{pid}/statm
and swap usage from /proc/{pid}/status.
Conflicts:
src/memory/lowmem-limit.c
Change-Id: I7e664ff40f05fa9c1d8122be64180e5e7a8fab77
Signed-off-by: ByungSoo Kim <bs1770.kim@samsung.com>
#define PAGE_SIZE_KB 4
-#define MEM_RSS_RATIO 0.3
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+
#define MEM_SWAP_RATIO 0.5
static struct sys_node_table sys_node_tables[] = {
return RESOURCED_ERROR_NONE;
}
-int proc_get_mem_usage(pid_t pid, unsigned int *vmswap, unsigned int *vmrss)
+int proc_get_mem_status(pid_t pid, unsigned int *vmswap, unsigned int *vmrss)
{
char filename[PROC_BUF_MAX];
_cleanup_fclose_ FILE *fp = NULL;
unsigned int swap = 0, rss = 0;
- snprintf(filename, PROC_BUF_MAX, "/proc/%d/status", pid);
+ sprintf(filename, "/proc/%d/status", pid);
fp = fopen(filename, "r");
if (!fp)
return RESOURCED_ERROR_FAIL;
return RESOURCED_ERROR_NONE;
}
-int proc_get_rss(pid_t pid, unsigned int *rss)
-{
- unsigned int vmrss, vmswap;
- int ret;
-
- *rss = 0;
-
- ret = proc_get_mem_usage(pid, &vmswap, &vmrss);
- if (ret != RESOURCED_ERROR_NONE)
- return ret;
-
- /*
- * USS is more real live usage compare to RSS.
- * But, RSS is faster to get, PSS is very slow.
- * So, RSS value with heuristic weight factor and SWAP size which is considered swap compression ration
- * can be more accurate value as well as getting it fastly.
- */
- *rss = vmrss * MEM_RSS_RATIO + vmswap * MEM_SWAP_RATIO;
-
- return RESOURCED_ERROR_NONE;
-}
-
int proc_get_zram_usage(pid_t pid, unsigned int *usage)
{
int ret;
}
/* Read usage of Swap (VmSwap) of interested process */
- ret = proc_get_mem_usage(pid, &proc_swap_usage, NULL);
+ ret = proc_get_mem_status(pid, &proc_swap_usage, NULL);
if (ret != RESOURCED_ERROR_NONE)
return ret;
return RESOURCED_ERROR_NONE;
}
-int proc_get_procstat_mem_usage(pid_t pid, unsigned int *usage)
+int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage)
{
int ret;
- unsigned int pss, swap;
+ unsigned long resident = 0, shared = 0;
+ char filename[PROC_BUF_MAX];
+ _cleanup_fclose_ FILE *fp = NULL;
- ret = proc_get_pss(pid, &pss);
- if (ret != RESOURCED_ERROR_NONE)
- return ret;
+ snprintf(filename, PROC_BUF_MAX, "/proc/%d/statm", pid);
+ fp = fopen(filename, "r");
+ if (!fp)
+ return RESOURCED_ERROR_FAIL;
- ret = proc_get_mem_usage(pid, &swap, NULL);
- if (ret != RESOURCED_ERROR_NONE)
- return ret;
+ /*
+ * For quick read, open code by putting numbers directly
+ * expected format is
+ * seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n",
+ * size, resident, shared, text, data);
+ */
+ ret = fscanf(fp, "%*s %lu %lu %*s %*s %*s %*s\n", &resident, &shared);
+ if (ret < 0)
+ return RESOURCED_ERROR_FAIL;
/*
- * For user information it's better to present PSS value
- * as it account libraries as they are shared between processes.
- *
- * If process is being swapped (moved to zram) then it's PSS goes
- * to very low value, then it's needed to account VmSwap usage
- * so there wouldn't be any strange information about process memory usage.
+ * The value resident - shared is mostly similar to Uss.
*/
- *usage = pss + swap;
+ *usage = BYTE_TO_KBYTE((resident - shared) << PAGE_SHIFT);
+ return RESOURCED_ERROR_NONE;
+}
+
+/**
+ * @desc get total memory usage from VmSwap and VmRSS.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_mem_usage(pid_t pid, unsigned int *usage)
+{
+ int ret;
+ unsigned int vmswap = 0, total = 0;
+
+ ret = proc_get_approx_mem_usage(pid, &total);
+ if (ret < 0) {
+ _E("Failed to get usage : %d", pid);
+ return ret;
+ }
+
+ if (swap_get_state() == SWAP_ON) {
+ ret = proc_get_mem_status(pid, &vmswap, NULL);
+ if (ret != RESOURCED_ERROR_NONE)
+ goto out;
+
+ total += vmswap;
+ }
+out:
+ *usage = total;
+ return RESOURCED_ERROR_NONE;
+}
+
+/**
+ * @desc get how much ram is used in each application
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_ram_usage(pid_t pid, unsigned int *usage)
+{
+ int ret;
+ unsigned int vmswap = 0, total = 0;
+
+ ret = proc_get_approx_mem_usage(pid, &total);
+ if (ret < 0) {
+ _E("Failed to get usage : %d", pid);
+ return ret;
+ }
+
+ if (swap_get_state() == SWAP_ON) {
+ ret = proc_get_mem_status(pid, &vmswap, NULL);
+ if (ret != RESOURCED_ERROR_NONE)
+ goto out;
+
+ /*
+ * If it is necessary to know real ram size about each application,
+ * it should consider compression ratio.
+ */
+ vmswap *= MEM_SWAP_RATIO;
+ total += vmswap;
+ }
+out:
+ *usage = total;
return RESOURCED_ERROR_NONE;
}
if (ret)
continue;
- ret = proc_get_mem_usage(pid, &swap, &rss);
+ ret = proc_get_mem_status(pid, &swap, &rss);
if (ret)
continue;
*/
int proc_get_label(pid_t pid, char *label);
-/**
- * @desc get VmSwap and VmRSS from /proc/{pid}/status file.
- * @return negative value if error or pid doesn't exist
- */
-int proc_get_mem_usage(pid_t pid, unsigned int *vmswap, unsigned int *vmrss);
-
/**
* @desc get PSS memory usage from /proc/{pid}/smaps file.
* @return negative value if error or pid doesn't exist
int proc_get_uss(pid_t pid, unsigned int *uss);
/**
- * @desc get RSS memory usage from /proc/{pid}/status file.
+ * @desc get VmRSS and VmSwap from /proc/{pid}/status file.
* @return negative value if error or pid doesn't exist
*/
-int proc_get_rss(pid_t pid, unsigned int *rss);
+int proc_get_mem_status(pid_t pid, unsigned int *rss, unsigned int *swap);
/**
* @desc get aproximated usage of Zram for pid
int proc_get_zram_usage(pid_t pid, unsigned int *usage);
/**
- * @desc get memory usage for proc-stat: PSS+VmSwap
+ * @desc get approximate memory usage from status and statm
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_approx_mem_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get total memory usage from VmSwap and VmRSS.
+ * @return negative value if error or pid doesn't exist
+ */
+int proc_get_mem_usage(pid_t pid, unsigned int *usage);
+
+/**
+ * @desc get how much ram is used in each application
* @return negative value if error or pid doesn't exist
*/
-int proc_get_procstat_mem_usage(pid_t pid, unsigned int *usage);
+int proc_get_ram_usage(pid_t pid, unsigned int *usage);
/**
* @desc get MemAvaliable from /proc/meminfo or calcuate it by MemFree+Cached
static int heart_memory_write(char *appid, char *pkgid, struct proc_status *p_data)
{
_cleanup_free_ char *info = NULL;
- unsigned int rss = 0;
+ unsigned int usage = 0;
int ret;
struct proc_app_info *pai = p_data->pai;
/* For write to data crud during period */
/* write memory usage in proc_list */
- ret = proc_get_rss(p_data->pid, &rss);
+ ret = proc_get_mem_usage(p_data->pid, &usage);
if (ret < 0) {
_E("Failed to get PID(%d) rss: %m", p_data->pid);
return ret;
}
if (pai && pai->childs) {
- unsigned int child_rss;
+ unsigned int child_usage;
GSList *iterchild;
gslist_for_each_item(iterchild, pai->childs) {
pid_t child = GPOINTER_TO_PID(iterchild->data);
- ret = proc_get_rss(child, &child_rss);
+ ret = proc_get_mem_usage(child, &child_usage);
if (ret < 0) {
_E("Failed to get PID(%d) rss: %m", child);
continue;
}
- rss += child_rss;
+ usage += child_usage;
}
}
- _SD("memory write : %s(%d), usage %u", appid, p_data->pid, rss);
- ret = asprintf(&info, "%u", rss);
+ _SD("memory write : %s(%d), usage %u", appid, p_data->pid, usage);
+ ret = asprintf(&info, "%u", usage);
if (ret < 0) {
_E("Failed to allocate memory");
return -ENOMEM;
* is used.
*/
if (tsk->pids == NULL) {
- ret = proc_get_rss(tsk->pid, &size);
+ ret = proc_get_ram_usage(tsk->pid, &size);
/* If there is no proc entry for given pid the process
* should be abandoned during further processing
for (index = 0; index < tsk->pids->len; index++) {
pid = g_array_index(tsk->pids, pid_t, index);
- ret = proc_get_rss(pid, &size);
+ ret = proc_get_ram_usage(pid, &size);
if (ret != RESOURCED_ERROR_NONE)
continue;
total_size += size;
pai->lru_state, pai->proc_exclude, pai->runtime_exclude,
pai->flags, pai->state);
- if (proc_get_procstat_mem_usage(pai->main_pid, &size))
+ if (proc_get_mem_usage(pai->main_pid, &size))
size = 0;
proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime);
LOG_DUMP(fp, "\t main pid : %d, oom score : %d, memory rss : %d KB,"
utime, stime, starttime);
if (pai->childs) {
gslist_for_each_item(iter_child, pai->childs) {
- if (proc_get_procstat_mem_usage(GPOINTER_TO_PID(iter_child->data), &size))
+ if (proc_get_mem_usage(GPOINTER_TO_PID(iter_child->data), &size))
size = 0;
proc_get_cpu_time(GPOINTER_TO_PID(iter_child->data),
&utime, &stime, &starttime);
return;
}
- if (proc_get_procstat_mem_usage(pai->main_pid, &usage) < 0) {
+ if (proc_get_mem_usage(pai->main_pid, &usage) < 0) {
_E("lowmem_get_proc_mem_usage failed for appid = %s (%d)",
appid, pai->main_pid);
D_BUS_REPLY_NULL(invocation);
pai = (struct proc_app_info *)giter->data;
if (!pai || !pai->main_pid)
continue;
- if (proc_get_procstat_mem_usage(pai->main_pid, &usage) < 0)
+ if (proc_get_mem_usage(pai->main_pid, &usage) < 0)
continue;
appid = pai->appid;
continue;
if (type != PROC_TYPE_MAX && pai->type != type)
continue;
- if (proc_get_procstat_mem_usage(pai->main_pid, &usage) < 0)
+ if (proc_get_mem_usage(pai->main_pid, &usage) < 0)
continue;
appid = pai->appid;
int index;
struct swap_task tsk;
struct proc_app_info *pai = NULL;
- unsigned int vmrss = 0;
+ unsigned int usage = 0;
if (!candidates)
return RESOURCED_ERROR_NO_DATA;
pai = tsk.pai;
/* Measuring VmRSS is OK as it's anonymous + swapcache */
- if (proc_get_mem_usage(pai->main_pid, NULL, &vmrss) < 0)
+ if (proc_get_approx_mem_usage(pai->main_pid, &usage) < 0)
continue;
- tsk.size += vmrss;
+ tsk.size += usage;
if (pai->childs) {
GSList *iter_child = NULL;
gslist_for_each_item(iter_child, pai->childs) {
pid_t child = GPOINTER_TO_PID(iter_child->data);
- if (proc_get_mem_usage(child, NULL, &vmrss) < 0)
+ if (proc_get_approx_mem_usage(child, &usage) < 0)
continue;
- tsk.size += vmrss;
+ tsk.size += usage;
}
}
}