线上计数系统遇到一个奇怪的问题,进程在做备份时,系统内存迅速变小,25G内存被吃掉,最后进程大量占用swap,导致服务响应缓慢,SLA下降严重。
最后发现跟Transparent hugepage相关,具体记录如下。
1 计数系统备份说明
cache系统占用内存在10-100G级别,备份是在每日凌晨低峰时间进行,备份逻辑:主进程 fork,然后子进程执行落地任务,父进程继续响应请求,备份期间,系统变更量很少,单个kv的byte在64btes以内,变更的tps在100以下。
2 os版本与thp
线上Linux内核2.6.38 ——2.7,而 Linux 内核在2.6.38之后,默认开启Transparent hugepage,之前那些没法从复杂的hugepage中获得好处的应用,现在不需要做任何修改也可以得到性能改善,预计性能提升在10%左右。
3 内存去向分析
日志分析发现,整个备份过程持续10分钟,整个过程的修改kv的个数为 100*60*10=60000,有效内存变更 60000*64=约4M;
fork过程中,父进程变更是一个cow的过程,可以先算最极端情况:即每次变更的kv分散在一个page中,来进行计算最大值;
对于普通的page,应该占用的内存:4M * 4K=16G;所以这个过程最多占用16G;
系统默认开启了THP,每个page变成了2M,所以这个过程的最大占用内存 4M*2M=8192G;
由于kv的size很小,很多kv是在相同的page,所以实际占用内存在25G mem & 20G+ swap;
4 关闭THP
关闭THP,重启计数服务,百G数据的备份过程,更新毫无压力。
小结一下,fork 备份,主进程变更流程变为cow,而Linux默认启用THP,于是出现写放大(即便你更新1 byte,实际内存也可能需要新占用2M bytes),于是内存就成为了瓶颈,swap、响应慢,极端情况下被os干掉而crash 等都会出现。
5 如何关闭THP
1)boot时生效 修改grub.cfg
transparent_hugepage=never
2) runtime 是修改
# echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled
# echo never > /sys/kernel/mm/redhat_transparent_hugepage/defrag
6 More about THP
Transparent hugepage是一个hugepage管理的简化版,在Linux 2.6.38之后自动生效,只对anonymous mem生效,可以通过 grep -i AnonHugePages /proc/meminfo 查看实际使用情况。
对于普通的cache应用,默认的THP有性能提升,但如果有fork 且 fork的时间较长,需要观测资源占用情况,必要时关闭THP。
runtime 期间 关闭THP,之前已经分配的hugepage继续生效,只对新分配的page不再采用hugepage,os也不再scan & merge pages。
进程可以通过madvise 进行设置是否启用THP:
#include <sys/mman.h> int madvise(void *addr, size_t length, int advice);
参考:
https://access.redhat.com/solutions/46111
http://lwn.net/Articles/423584/
http://lwn.net/Articles/423592/
相关推荐
Git客户端Fork是一款专为开发者设计的Git版本控制系统可视化界面工具,它旨在简化Git的使用,使得非专业程序员或者对命令行操作不熟悉的用户也能轻松地进行代码管理和协作。Fork不仅提供了美观的图形界面,还包含了...
1. **复制进程**:当`fork()`被调用时,操作系统会为父进程创建一个镜像,包括内存映射、打开的文件描述符、环境变量等。但请注意,它们是共享的,直到有写操作发生,这时才会发生写时复制(Copy-On-Write, COW)。 ...
当一个进程调用`fork()`函数时,系统会为新进程分配所需的资源,并将父进程的状态复制给子进程。这意味着除了少数几个特定值外,子进程与父进程具有相同的内存空间、环境变量和其他属性。这样的设计使得子进程可以...
1. **复制进程上下文**:当`fork()`被调用时,操作系统为子进程分配新的内存空间,并复制父进程的当前状态,包括代码、数据、堆栈、环境变量等。 2. **返回值区分父子进程**:`fork()`调用后,它在父进程和子进程...
在众多的Git UI客户端中,Fork被誉为macOS和Windows平台上的优秀选择。本文将详细探讨Fork作为Git UI客户端的优势及其核心特性。 标题中的"Fork目前发现最好用的git-ui免费客户端"表明,Fork在用户界面设计、功能集...
当`fork()` 被调用时,操作系统会分配一个新的进程ID(PID)给新创建的进程,并复制父进程的当前状态,包括内存空间、文件描述符、环境变量等。这个过程称为进程的克隆。新进程(子进程)和旧进程(父进程)会从`...
5. **冲突解决**: 当发生代码冲突时,FORK提供了一套直观的冲突解决工具,帮助开发者更容易地解决冲突问题。 6. **代码审查**: FORK支持代码审查功能,团队成员可以对代码提交进行评论和审批,保证代码质量。 7. *...
在 Fork 的主界面上,你可以看到仓库的提交历史,分支列表以及其他信息。 创建分支: 在 Fork 中,你可以点击 "Branches"(分支)按钮来查看分支列表。 点击 "New Branch"(新建分支)按钮来创建一个新的分支,然后...
fork一个进程,fork()函数fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,这个新产生的进程称为子进程。一个进程调用fork()函数后,系统先给新的进程...
这个函数的工作方式非常独特,当一个进程(我们称之为父进程)调用`fork()`时,它会创建一个新的进程(我们称之为子进程)。这两个进程在`fork()`调用后具有几乎完全相同的内存状态,包括代码、数据、堆和栈,但它们...
- 当执行 `fork` 函数时,会产生一个与父进程状态相同的子进程。 - 父进程继续执行 `fork` 后的代码,而子进程从 `fork` 函数处开始执行。 2. **关键点:** - 父进程执行了所有代码,子进程仅执行 `fork` 后的...
然而,复制并非字面意义上的物理复制,而是采用写时复制(Copy-On-Write,COW)技术,只有当某个进程试图修改已复制的数据时,才会真正分配新的内存并复制数据。 二、Fork的返回值与父子进程的交互 2.1 返回值:在...
当子任务足够小或者无法再拆分时,任务会直接执行计算,然后通过`join()`方法等待子任务的结果并返回最终的总和。 下面是对`Fork/Join`框架的详细解释: 1. **ForkJoinPool**:这是`Fork/Join`框架的主要工作单元...
### c语言中的`fork()`函数详解 #### 一、引言 `fork()`函数作为操作系统提供的核心系统调用之一,在进程管理和并发编程中扮演着重要角色。本文将深入探讨`fork()`函数的基本概念、工作原理及其在C语言中的具体应用...
https://git-fork.com/update/win/ForkInstaller.exe windows桌面版的图形化Git管理工具
### Fork使用教程(Git GUI页面可视化工具) #### 一、仓库克隆 **1.1 打开Fork软件,点击File,点击Clone** - **步骤解析:** 使用Fork进行仓库克隆的第一步是在软件中打开“File”菜单,然后选择“Clone”选项...
5. **接受连接**:当有客户端连接请求时,使用`accept()`函数获取新的套接字,用于与客户端通信。 ```c struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_socket = accept...
当子进程结束时,通常会产生一个SIGCHLD信号,父进程可以通过捕获这个信号来知道子进程的状态变化,这在进程管理中非常重要。 在`pthread.c.lnk`中,尽管文件扩展名是`.lnk`,这通常关联到Windows的快捷方式,但在...
当工作线程没有任务时,它会从其他工作线程的任务队列中“窃取”任务,这就是工作窃取算法的体现。 2. **ForkJoinTask**: 这是所有可由ForkJoinPool执行的任务的基类,有两个主要的子类:RecursiveAction(无返回值...