加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0045-add-dram_percent-to-etmem.patch 16.53 KB
一键复制 编辑 原始数据 按行查看 历史
yangxin 提交于 2021-09-30 22:57 . Update etmem.
From 6ef46195753a4f383e931b7267cebedc40e756c5 Mon Sep 17 00:00:00 2001
From: liubo <liubo254@huawei.com>
Date: Wed, 18 Aug 2021 10:22:50 +0800
Subject: [PATCH 45/50] add dram_percent to etmem
---
inc/etmemd_inc/etmemd_common.h | 9 ++++
inc/etmemd_inc/etmemd_exp.h | 5 ++
inc/etmemd_inc/etmemd_migrate.h | 3 +-
inc/etmemd_inc/etmemd_scan.h | 5 +-
inc/etmemd_inc/etmemd_slide.h | 1 +
src/etmemd_src/etmemd_common.c | 94 +++++++++++++++++++++++++++++++++
src/etmemd_src/etmemd_migrate.c | 46 ++++++++++++++++
src/etmemd_src/etmemd_scan.c | 70 ++++++++++++++++++++++++
src/etmemd_src/etmemd_slide.c | 83 +++++++++++++++++++++++++----
9 files changed, 304 insertions(+), 12 deletions(-)
diff --git a/inc/etmemd_inc/etmemd_common.h b/inc/etmemd_inc/etmemd_common.h
index 4127ccf..8d18f8a 100644
--- a/inc/etmemd_inc/etmemd_common.h
+++ b/inc/etmemd_inc/etmemd_common.h
@@ -20,10 +20,16 @@
#include <stdbool.h>
#define PROC_PATH "/proc/"
+#define STATUS_FILE "/status"
+#define SWAPIN "SwapIN"
+#define VMRSS "VmRSS"
+#define VMSWAP "VmSwap"
#define FILE_LINE_MAX_LEN 1024
#define KEY_VALUE_MAX_LEN 64
#define DECIMAL_RADIX 10
#define ETMEMD_MAX_PARAMETER_NUM 6
+#define BYTE_TO_KB(s) ((s) >> 10)
+#define KB_TO_BYTE(s) ((s) << 10)
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
@@ -48,11 +54,14 @@ int etmemd_parse_cmdline(int argc, char *argv[], bool *is_help);
bool check_str_format(char endptr);
int get_int_value(const char *val, int *value);
int get_unsigned_int_value(const char *val, unsigned int *value);
+int get_unsigned_long_value(const char *val, unsigned long *value);
void etmemd_safe_free(void **ptr);
FILE *etmemd_get_proc_file(const char *pid, const char *file, int flags, const char *mode);
int get_keyword_and_value(const char *str, char *key, char *val);
+unsigned long get_pagesize(void);
+int get_mem_from_proc_file(const char *pid, const char *file_name, unsigned long *data, const char *cmpstr);
int dprintf_all(int fd, const char *format, ...);
diff --git a/inc/etmemd_inc/etmemd_exp.h b/inc/etmemd_inc/etmemd_exp.h
index 8c57d9f..48a0018 100644
--- a/inc/etmemd_inc/etmemd_exp.h
+++ b/inc/etmemd_inc/etmemd_exp.h
@@ -39,4 +39,9 @@ struct page_refs {
struct page_refs *next; /* point to next page */
};
+struct page_sort {
+ struct page_refs **page_refs_sort;
+ struct page_refs **page_refs;
+ int loop;
+};
#endif
diff --git a/inc/etmemd_inc/etmemd_migrate.h b/inc/etmemd_inc/etmemd_migrate.h
index db61c69..ef20bde 100644
--- a/inc/etmemd_inc/etmemd_migrate.h
+++ b/inc/etmemd_inc/etmemd_migrate.h
@@ -17,6 +17,7 @@
#define ETMEMD_MIGRATE_H
#include "etmemd.h"
+#include "etmemd_task.h"
#define COLD_PAGE "/swap_pages"
@@ -26,5 +27,5 @@
#define SWAP_ADDR_LEN 20
int etmemd_grade_migrate(const char* pid, const struct memory_grade *memory_grade);
-
+unsigned long check_should_migrate(const struct task_pid *tk_pid);
#endif
diff --git a/inc/etmemd_inc/etmemd_scan.h b/inc/etmemd_inc/etmemd_scan.h
index 09ad51c..9e5bcc4 100644
--- a/inc/etmemd_inc/etmemd_scan.h
+++ b/inc/etmemd_inc/etmemd_scan.h
@@ -77,9 +77,12 @@ struct vmas *get_vmas_with_flags(const char *pid, char **vmflags_array, int vmfl
struct vmas *get_vmas(const char *pid);
void clean_page_refs_unexpected(void *arg);
-
void clean_memory_grade_unexpected(void *arg);
+void clean_page_sort_unexpected(void *arg);
+struct page_sort *alloc_page_sort(const struct task_pid *tk_pid);
+struct page_sort *sort_page_refs(struct page_refs **page_refs, const struct task_pid *tk_pid);
+
struct page_refs *add_page_refs_into_memory_grade(struct page_refs *page_refs, struct page_refs **list);
int init_g_page_size(void);
int page_type_to_size(enum page_type type);
diff --git a/inc/etmemd_inc/etmemd_slide.h b/inc/etmemd_inc/etmemd_slide.h
index af48be7..93de502 100644
--- a/inc/etmemd_inc/etmemd_slide.h
+++ b/inc/etmemd_inc/etmemd_slide.h
@@ -22,6 +22,7 @@
struct slide_params {
struct task_executor *executor;
int t; /* watermark */
+ uint8_t dram_percent;
};
int fill_engine_type_slide(struct engine *eng, GKeyFile *config);
diff --git a/src/etmemd_src/etmemd_common.c b/src/etmemd_src/etmemd_common.c
index 8aad0eb..4595499 100644
--- a/src/etmemd_src/etmemd_common.c
+++ b/src/etmemd_src/etmemd_common.c
@@ -195,6 +195,19 @@ int get_unsigned_int_value(const char *val, unsigned int *value)
return 0;
}
+int get_unsigned_long_value(const char *val, unsigned long *value)
+{
+ char *pos = NULL;
+
+ errno = 0;
+ *value = strtoul(val, &pos, DECIMAL_RADIX);
+ if (check_str_format(pos[0])) {
+ etmemd_log(ETMEMD_LOG_ERR, "invalid value, must be type of unsigned long.\n");
+ return -1;
+ }
+
+ return 0;
+}
void etmemd_safe_free(void **ptr)
{
if (ptr == NULL || *ptr == NULL) {
@@ -205,6 +218,36 @@ void etmemd_safe_free(void **ptr)
*ptr = NULL;
}
+static int get_status_num(char *getline, char *value, size_t value_len)
+{
+ size_t len = strlen(getline);
+ int start_cp_index = 0;
+ int end_cp_index = 0;
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (isdigit(getline[i])) {
+ start_cp_index = i;
+ end_cp_index = start_cp_index;
+ break;
+ }
+ }
+
+ for (; i < len; i++) {
+ if (!isdigit(getline[i])) {
+ end_cp_index = i - 1;
+ break;
+ }
+ }
+
+ if (strncpy_s(value, value_len, getline + start_cp_index, end_cp_index - start_cp_index + 1) != 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "strncpy_s for result failed.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static char *etmemd_get_proc_file_str(const char *pid, const char *file)
{
char *file_name = NULL;
@@ -398,3 +441,54 @@ int dprintf_all(int fd, const char *format, ...)
va_end(args_in);
return 0;
}
+
+int get_mem_from_proc_file(const char *pid, const char *file_name, unsigned long *data, const char *cmpstr)
+{
+ FILE *file = NULL;
+ char value[KEY_VALUE_MAX_LEN] = {};
+ char get_line[FILE_LINE_MAX_LEN] = {};
+ unsigned long val;
+ int ret = -1;
+
+ file = etmemd_get_proc_file(pid, file_name, 0, "r");
+ if (file == NULL) {
+ etmemd_log(ETMEMD_LOG_ERR, "cannot open %s for pid %s\n", file_name, pid);
+ return ret;
+ }
+
+ while (fgets(get_line, FILE_LINE_MAX_LEN - 1, file) != NULL) {
+ if (strstr(get_line, cmpstr) == NULL) {
+ continue;
+ }
+
+ if (get_status_num(get_line, value, KEY_VALUE_MAX_LEN) != 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "get mem from /proc/%s/%s fail\n", pid, file_name);
+ break;
+ }
+
+ if (get_unsigned_long_value(value, &val) != 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "get value with strtoul fail.\n");
+ break;
+ }
+
+ *data = val;
+ ret = 0;
+ break;
+ }
+
+ fclose(file);
+ return ret;
+}
+
+unsigned long get_pagesize(void)
+{
+ long pagesize;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize == -1) {
+ etmemd_log(ETMEMD_LOG_ERR, "get pageszie fail,error: %d\n", errno);
+ return -1;
+ }
+
+ return (unsigned long)pagesize;
+}
diff --git a/src/etmemd_src/etmemd_migrate.c b/src/etmemd_src/etmemd_migrate.c
index 2f29f31..639d570 100644
--- a/src/etmemd_src/etmemd_migrate.c
+++ b/src/etmemd_src/etmemd_migrate.c
@@ -20,6 +20,7 @@
#include "etmemd.h"
#include "etmemd_migrate.h"
#include "etmemd_common.h"
+#include "etmemd_slide.h"
#include "etmemd_log.h"
static char *get_swap_string(struct page_refs **page_refs, int batchsize)
@@ -113,3 +114,48 @@ int etmemd_grade_migrate(const char *pid, const struct memory_grade *memory_grad
return ret;
}
+unsigned long check_should_migrate(const struct task_pid *tk_pid)
+{
+ int ret = -1;
+ unsigned long vm_rss;
+ unsigned long vm_swap;
+ unsigned long vm_cmp;
+ unsigned long need_to_swap_page_num;
+ char pid_str[PID_STR_MAX_LEN] = {0};
+ unsigned long pagesize;
+ struct slide_params *slide_params = NULL;
+
+ if (snprintf_s(pid_str, PID_STR_MAX_LEN, PID_STR_MAX_LEN - 1, "%u", tk_pid->pid) <= 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "snprintf pid fail %u", tk_pid->pid);
+ return 0;
+ }
+
+ ret = get_mem_from_proc_file(pid_str, STATUS_FILE, &vm_rss, VMRSS);
+ if (ret != 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "get vmrss %s fail", pid_str);
+ return 0;
+ }
+
+ ret = get_mem_from_proc_file(pid_str, STATUS_FILE, &vm_swap, VMSWAP);
+ if (ret != 0) {
+ etmemd_log(ETMEMD_LOG_ERR, "get swapout %s fail", pid_str);
+ return 0;
+ }
+
+ slide_params = (struct slide_params *)tk_pid->tk->params;
+ if (slide_params == NULL) {
+ etmemd_log(ETMEMD_LOG_ERR, "slide params is null");
+ return 0;
+ }
+
+ vm_cmp = (vm_rss + vm_swap) / 100 * slide_params->dram_percent;
+ if (vm_cmp > vm_rss) {
+ etmemd_log(ETMEMD_LOG_DEBUG, "migrate too much, stop migrate this time\n");
+ return 0;
+ }
+
+ pagesize = get_pagesize();
+ need_to_swap_page_num = KB_TO_BYTE(vm_rss - vm_cmp) / pagesize;
+
+ return need_to_swap_page_num;
+}
diff --git a/src/etmemd_src/etmemd_scan.c b/src/etmemd_src/etmemd_scan.c
index 0fb4fe6..fec6373 100644
--- a/src/etmemd_src/etmemd_scan.c
+++ b/src/etmemd_src/etmemd_scan.c
@@ -24,6 +24,7 @@
#include "etmemd_project.h"
#include "etmemd_engine.h"
#include "etmemd_common.h"
+#include "etmemd_slide.h"
#include "etmemd_log.h"
#include "securec.h"
@@ -819,6 +820,46 @@ void clean_memory_grade_unexpected(void *arg)
return;
}
+void clean_page_sort_unexpected(void *arg)
+{
+ struct page_sort **msg = (struct page_sort **)arg;
+
+ if (*msg == NULL) {
+ return;
+ }
+
+ for (int i = 0; i < (*msg)->loop + 1; i++) {
+ clean_page_refs_unexpected(&((*msg)->page_refs_sort)[i]);
+ }
+
+ free(*msg);
+ *msg = NULL;
+
+ return;
+}
+
+struct page_sort *alloc_page_sort(const struct task_pid *tpid)
+{
+ struct page_sort *page_sort = NULL;
+
+ page_sort = (struct page_sort *)calloc(1, sizeof(struct page_sort));
+ if (page_sort == NULL) {
+ etmemd_log(ETMEMD_LOG_ERR, "calloc page sort failed.\n");
+ return NULL;
+ }
+
+ page_sort->loop = tpid->tk->eng->proj->loop;
+
+ page_sort->page_refs_sort = (struct page_refs **)calloc((tpid->tk->eng->proj->loop + 1), sizeof(struct page_refs *));
+ if (page_sort->page_refs_sort == NULL) {
+ etmemd_log(ETMEMD_LOG_ERR, "calloc page refs sort failed.\n");
+ free(page_sort);
+ return NULL;
+ }
+
+ return page_sort;
+}
+
struct page_refs *add_page_refs_into_memory_grade(struct page_refs *page_refs, struct page_refs **list)
{
struct page_refs *tmp = NULL;
@@ -851,3 +892,32 @@ void etmemd_scan_exit(void)
{
g_exp_scan_inited = false;
}
+
+/* Move the colder pages by sorting page refs.
+ * Use original page_refs if dram_percent is not set.
+ * But, use the sorting result of page_refs, if dram_percent is set to (0, 100] */
+struct page_sort *sort_page_refs(struct page_refs **page_refs, const struct task_pid *tpid)
+{
+ struct slide_params *slide_params = NULL;
+ struct page_sort *page_sort = NULL;
+ struct page_refs *page_next = NULL;
+
+ page_sort = alloc_page_sort(tpid);
+ if (page_sort == NULL)
+ return NULL;
+
+ slide_params = (struct slide_params *)tpid->tk->params;
+ if (slide_params == NULL || slide_params->dram_percent == 0) {
+ page_sort->page_refs = page_refs;
+ return page_sort;
+ }
+
+ while (*page_refs != NULL) {
+ page_next = (*page_refs)->next;
+ (*page_refs)->next = (page_sort->page_refs_sort[(*page_refs)->count]);
+ (page_sort->page_refs_sort[(*page_refs)->count]) = *page_refs;
+ *page_refs = page_next;
+ }
+
+ return page_sort;
+}
diff --git a/src/etmemd_src/etmemd_slide.c b/src/etmemd_src/etmemd_slide.c
index 96d3dcc..a024178 100644
--- a/src/etmemd_src/etmemd_slide.c
+++ b/src/etmemd_src/etmemd_slide.c
@@ -28,12 +28,15 @@
#include "etmemd_pool_adapter.h"
#include "etmemd_file.h"
-static struct memory_grade *slide_policy_interface(struct page_refs **page_refs, void *params)
+static struct memory_grade *slide_policy_interface(struct page_sort **page_sort, const struct task_pid *tpid)
{
- struct slide_params *slide_params = (struct slide_params *)params;
+ struct slide_params *slide_params = (struct slide_params *)(tpid->tk->params);
+ struct page_refs **page_refs = NULL;
struct memory_grade *memory_grade = NULL;
+ unsigned long need_2_swap_num;
+ volatile uint64_t count = 0;
- if (params == NULL) {
+ if (slide_params == NULL) {
etmemd_log(ETMEMD_LOG_ERR, "cannot get params for slide\n");
return NULL;
}
@@ -44,14 +47,41 @@ static struct memory_grade *slide_policy_interface(struct page_refs **page_refs,
return NULL;
}
- while (*page_refs != NULL) {
- if ((*page_refs)->count >= slide_params->t) {
- *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->hot_pages);
- continue;
+ if (slide_params->dram_percent == 0) {
+ page_refs = (*page_sort)->page_refs;
+
+ while (*page_refs != NULL) {
+ if ((*page_refs)->count >= slide_params->t) {
+ *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->hot_pages);
+ continue;
+ }
+ *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->cold_pages);
+ }
+
+ return memory_grade;
+ }
+
+ need_2_swap_num = check_should_migrate(tpid);
+ if (need_2_swap_num == 0)
+ goto count_out;
+
+ for (int i = 0; i < tpid->tk->eng->proj->loop + 1; i++) {
+ page_refs = &((*page_sort)->page_refs_sort[i]);
+
+ while (*page_refs != NULL) {
+ if ((*page_refs)->count >= slide_params->t) {
+ *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->hot_pages);
+ goto count_out;
+ }
+
+ *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->cold_pages);
+ count++;
+ if (count >= need_2_swap_num)
+ goto count_out;
}
- *page_refs = add_page_refs_into_memory_grade(*page_refs, &memory_grade->cold_pages);
}
+count_out:
return memory_grade;
}
@@ -80,17 +110,32 @@ static void *slide_executor(void *arg)
struct task_pid *tk_pid = (struct task_pid *)arg;
struct page_refs *page_refs = NULL;
struct memory_grade *memory_grade = NULL;
+ struct page_sort *page_sort = NULL;
/* register cleanup function in case of unexpected cancellation detected,
* and register for memory_grade first, because it needs to clean after page_refs is cleaned */
pthread_cleanup_push(clean_memory_grade_unexpected, &memory_grade);
pthread_cleanup_push(clean_page_refs_unexpected, &page_refs);
+ pthread_cleanup_push(clean_page_sort_unexpected, &page_sort);
page_refs = etmemd_do_scan(tk_pid, tk_pid->tk);
- if (page_refs != NULL) {
- memory_grade = slide_policy_interface(&page_refs, tk_pid->tk->params);
+ if (page_refs == NULL) {
+ etmemd_log(ETMEMD_LOG_WARN, "pid %u cannot get page refs\n", tk_pid->pid);
+ goto scan_out;
}
+ page_sort = sort_page_refs(&page_refs, tk_pid);
+ if (page_sort == NULL) {
+ etmemd_log(ETMEMD_LOG_ERR, "failed to alloc memory for page sort.", tk_pid->pid);
+ goto scan_out;
+ }
+
+ memory_grade = slide_policy_interface(&page_sort, tk_pid);
+
+scan_out:
+ /* clean up page_sort linked array */
+ pthread_cleanup_pop(1);
+
/* no need to use page_refs any longer.
* pop the cleanup function with parameter 1, because the items in page_refs list will be moved
* into the at least on list of memory_grade after polidy function called if no problems happened,
@@ -131,8 +176,26 @@ static int fill_task_threshold(void *obj, void *val)
return 0;
}
+static int fill_task_dram_percent(void *obj, void *val)
+{
+ struct slide_params *params = (struct slide_params *)obj;
+ int value = parse_to_int(val);
+
+ if (value <= 0 || value > 100) {
+ etmemd_log(ETMEMD_LOG_WARN,
+ "dram_percent %d is abnormal, the reasonable range is (0, 100],\
+ cancle the dram_percent parameter of current task\n", value);
+ value = 0;
+ }
+
+ params->dram_percent = value;
+
+ return 0;
+}
+
static struct config_item g_slide_task_config_items[] = {
{"T", INT_VAL, fill_task_threshold, false},
+ {"dram_percent", INT_VAL, fill_task_dram_percent, true},
};
static int slide_fill_task(GKeyFile *config, struct task *tk)
--
2.27.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化