在《一文读懂 HugePages的原理》一文中介绍了 HugePages(大内存页)的原理和使用,现在我们来分析一下 Linux 内核是怎么实现 HugePages 分配的。
传统的存储设备例如HDD,SSD,nvme,SAN LUNS等以blocks为单位提供存储功能。Block以字节为单位的可寻址存储单元。传统的硬盘的block大小是512字节。Newer设备通常是4K或者8K,但也可以选择逻辑/模拟的512字节的block。
要想一个系统不崩溃,性能还得好,同步技术是非常关键的。但是,完全避免竞态条件几乎是难于上青天。因为它要求对内核各个功能模块之间的交互得有一个清晰深刻的理解。下面我们看一下Linux内核中一些具体保护数据访问的示例,加深对其理解,甚至可以在自己的内核设计上借鉴一下。
最近看了glibc的ptmaoolc,Goolge的tcmalloc和jemalloc,顺便做了一点记录。可能有些地方理解地不太对,如有发现还请大神指出。
2017年末,手Q春节红包项目期间,为保障活动期间服务正常稳定,我对性能不佳的Ark Server进行了改造和重写。重编发布一段时间后,结果发现新发布的Svr的机器内存一直在上涨。如下图示:
libpcap为了提高效率,调用setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,(void *) &req, sizeof(req))时采用kmalloc分配内存。 可以参考: https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt kmalloc底层依赖linux的slab内存分配机制,在2.6.22内核之后,slub取代slab成为默认的内存分配器。空间和时间上都有所提升。
前言: 使用了mlock,会把内存lock在内存中,不会被交换,在一定场景下,可以提高性能。 虚拟化场景下,qemu也可以选择lock住一部分内存,来提高Guest的性能。 下文来分析一下mlock的
对于用户空间的应用程序,我们通常根本不关心page的物理存放位置,因为我们用的是虚拟地址。所以,只要虚拟地址不变,哪怕这个页在物理上从DDR的这里飞到DDR的那里,用户都基本不感知。那么,为什么要写一篇论述页迁移的文章呢?
mmap是linux中提高文件读写效率的一种手段,这里简单整理一下mmap的原理和使用。
对性能不佳的Ark Server进行了改造和重写。重编发布一段时间后,结果发现新发布的Svr的机器内存一直在上涨。如下图示:
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道: 地址映射 内存管理的方式 缺页异常 先来看一些基本的知识,在进程看来,内
1 压力测试过程中,发现被测对象性能不够理想,具体表现为: 进程的系统态CPU消耗20,用户态CPU消耗10,系统idle大约70 2 用ps -o majflt,minflt -C program命令查看(pidstat也可以),
当第一次听到这个说法的时候确实有点惊讶。一直记得map容器底层红黑树会自动析构节点,并释放内存。在同事进行了代码验证,并百度了答案后,我也变得不确定起来了。
1.如果分配一个对象的内存超出了某个值就会吧这个对象放到这块空间中,可以理解为针对大对象的分配单独创建了一个largeobjectspace空间进行分配内存。
Linux 内核中的同步机制:原子操作、信号量、读写信号量、自旋锁的API、大内核锁、读写锁、大读者锁、RCU和顺序锁。 1、介绍 在现代操作系统里,同一时间可能有多个内核执行流在执行,即使单CPU内核也需要一些同步机制来同步不同执行单元对共享的数据的访问。 主流的Linux内核中的同步机制包括: 原子操作 信号量(semaphore) 读写信号量(rw_semaphore) 自旋锁spinlock 大内核锁BKL(Big Kernel Lock) 读写锁rwlock、 brlock(只包含在2.4内核中
在虚拟地址空间那一节,我们知道,每一个进程都有一个列表vm_area_struct,指向虚拟地址空间的不同的内存块,这个变量的名字叫mmap。
众所周知,程序需要加载到物理内存才能运行,多核时代会出现多个进程同时操作同一物理地址的情况,进而造成混乱和程序崩溃。计算机当中很多问题的解决都是通过引入中间层,为解决物理内存使用问题,虚拟内存作为中间层进入了操作系统,从此,程序不在直接操作物理内存,只能看到虚拟内存,通过虚拟内存,非常优雅的将进程环境隔离开来,每个进程都拥有自己独立的虚拟地址空间,且所有进程地址空间范围完全一致,也给编程带来了很大的便利,同时也提高了物理内存的使用率,可同时运行更多的进程。
以前经常遇到2C3G的vmware续集上环境上安装上vpp后,能直接运行,而每次当系统重启后总是报内存不足的问题。当把系统内存调整到4G后,就能正常运行了。一直也不清楚原因。最近工作中遇到一个问题在2c2g的环境上跑vpp,一段时间后,总是报内存不足。后来查询发现hugepage内存大小是1G,但是只使用了不到三分之一的大页内存。
作者遇到了业务的一个性能抖动问题,在这里介绍一下它的原因和解决办法。 分析 1,page fault 在Linux上,进程分配到的内存是虚拟内存,经过内核的页表管理,会把虚拟内存映射成物理内存。 a,在第一次访问内存的时候,会触发page fault,内核会给进程分配好内存,进程继续执行。 b,内核进行内存回收,可能会把进程的部分内存进行回收,swap到磁盘上,下次访问到再换回来。当然,这个在实际业务上未必会启用swap以防止性能下降。 c,进程自己判断,认为部分内存段时间内不会使用,会尝试把它归还给内核。它的好处是不需要修改进程的虚拟地址空间,只是把内存页面(page)归还给内核,下一次访问到的时候,会因为page fault而重新分配物理内存。 另外需要注意的时候,处理page fault的过程中,需要持有进程的内存的锁(current->mm->mmap_sem)。 2,TLB shootdown 例如某服务器有40CPU,那么就意味着可以同时运行40个task。 例如某业务有30个线程,且这30个线程都很忙,并行执行在30个CPU上。 因为30个线程共享地址空间,它们使用的是相同的页表(page table)。所以在运行这30个线程的CPU上,会加载相同的页表。 当代CPU为了加速TLB查找的速度,会使用cache,也就是说会把对应的页表项(page table entry)加载到TLB cache中。 在运行的某一个时刻,某1个线程执行了上述的page fault的case 3,也就是执行了系统调用int madvise(void *addr, size_t length, MADV_DONTNEED),想要释放1个page(4K大小),除了需要修改页表释放该page外,还需要确保CPU的TLB cache中也是没有该page的PTE的。因为如果TLB cache还有该PTE,那么CPU访问这个page就不会出错,而这个page已经被释放并分配给其他进程使用的话,就会造成安全问题。 在多核场景下,这个问题就变得更加复杂了。除了运行madvise的线程之后,还需要确保另外的29个线程运行的CPU的TLB cache也是没有该PTE的。为了实现这种效果,需要当前的CPU通知另外的29个CPU,执行clflush或者重新加载cr3。这个通知的过程需要发送IPI(inter processor interrup)。 发送IPI的这个过程,在x86上的体现就是需要CPU执行wrmsr指令,对应的操作是触发ICR。了解虚拟化的朋友应该知道,wrmsr这条指令在虚拟机上需要经过Hypervisor处理,性能更低一些。 除此之外,在执行madvise的过程中,还需要持有当前进程的内存的锁(current->mm->mmap_sem),而且这个锁的粒度比较大。 而jemalloc库,默认情况下,则会释放过期的内存,调用madvise(void *addr, size_t length, MADV_DONTNEED)。 3,smaps/smaps_rollup cat /proc/PID/smaps,可以查看进程的每一段VMA信息。
如果 SQL 在执行过程中读到的数据无法直接得到结果,那么就需要额外的内存来保存中间结果,得出最终结果,这个额外的内存就是内部临时表。比如 group by 执行时,就需要构建一个临时表,需要额外的字段保存聚合函数的结果,当然为了防止内存使用过大,一般超出某个限制后就会放到磁盘上。关于哪些操作会产生内部临时表,可以查看官方文档:https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-tables.html,下面主要介绍 MySQL 8.0 内部临时表存放方式的变化。
内存是计算机的重要资源,虽然今天大多数的服务对内存的需求都没有那么高,但是数据库以及 Hadoop 全家桶这些服务却是消耗内存的大户,它们在生产环境动辄占用 GB 和 TB 量级的内存来提升计算的速度,Linux 操作系统为了更好、更快地管理这些内存并降低开销引入了很多策略,我们今天要介绍的是 HugePages,也就是大页[^1]。
本文转自:https://www.cnblogs.com/huxiao-tee/p/4660352.html
本文想和大家来探讨一下JVM是如何对堆内存进行管理和垃圾回收,相关书籍如深入理解JVM第三版中已经介绍过了相关的垃圾回收算法及其实现,但是基于文字介绍无法让大家对垃圾回收有具象的理解,所以本文想从c内存模式和malloc函数介绍起,带领大家回顾一下如何使用c语言完成堆内存的申请和释放。
最近游戏已上线运营,进行服务器内存优化,发现一个非常奇妙的问题,我们的认证服务器(AuthServer)负责跟第三方渠道SDK打交道(登陆和充值),由于采用了curl阻塞的方式,所以这里开了128个线程,奇怪的是每次刚启动的时候占用的虚拟内存在2.3G,然后每次处理消息就增加64M,增加到4.4G就不再增加了,由于我们采用预分配的方式,在线程内部根本没有大块分内存,那么这些内存到底是从哪来的呢?让人百思不得其解。 探索 一开始首先排除掉内存泄露,不可能每次都泄露64M内存这么巧合,为了证明我的观点,首先,我使用了valgrind。
这些参数主要是用来调整virtual memory子系统的行为以及数据的写出(从RAM到ROM)。 这些节点(参数)的默认值和初始化的过程大部分都可以在mm/swap.c中找到。 目前,/proc/sys/vm目录下有下面这些节点:
之前在实习时,听了 OOM 的分享之后,就对 Linux 内核内存管理充满兴趣,但是这块知识非常庞大,没有一定积累,不敢写下,担心误人子弟,所以经过一个一段时间的积累,对内核内存有一定了解之后,今天才写下这篇文章记录,分享。
分配 虚拟内存页 : 应用进程 调用 mmap 函数后 , 在 Linux 系统中 创建 " 内存映射 “ 时 , 会在 ” 用户虚拟地址空间 “ 中 , 分配一块 ” 虚拟内存区域 " ;
之前在实习时,听了 OOM 的分享之后,就对 Linux 内核内存管理充满兴趣,但是这块知识非常庞大,没有一定积累,不敢写下,担心误人子弟,所以经过一个一段时间的积累,对内核内存有一定了解之后,今天才写下这篇博客,记录以及分享。
这几天遇到一个比较奇怪的问题,觉得有必要和大家分享一下。我们的一个服务,运行在docker上,在某个版本之后,占用的内存开始增长,直到docker分配的内存上限,但是并不会OOM。版本的更改如下:
Linux 内存管理模型不是咱们这个系列的讨论重点,我们这里只会简单提一些对于咱们这个系列需要了解到的,如果读者想要深入理解,建议大家查看 bin 神(公众号:bin 的技术小屋)的系列文章:一步一图带你深入理解 Linux 虚拟内存管理
内存池(memory pool)是在当前系统中请求一大片连续的内存空间,然后在运行时根据实际需要分配出去的技术。使用内存池的优点如下: 1、速度远比 malloc/free 快,因为减少了系统调用的次数,特别是频繁申请/释放内存块的情况。 2、避免了频繁申请/释放内存之后,系统的大量内存碎片。 3、节省空间
来源:高效运维 ID:greatops 前言 之前在实习时,听了 OOM 的分享之后,就对 Linux 内核内存管理充满兴趣,但是这块知识非常庞大,没有一定积累,不敢写下,担心误人子弟,所以经过一个一段时间的积累,对内核内存有一定了解之后,今天才写下这篇博客,记录以及分享。 【OOM - Out of Memory】内存溢出 内存溢出的解决办法: 1、等比例缩小图片 2、对图片采用软引用,及时进行 recycle( ) 操作。 3、使用加载图片框架处理图片,如专业处理图片的 ImageLoader 图片加
使用 malloc 函数申请内存原理 : " 堆内存 " 动态分配 的 系统调用 过程 ;
6月1号,我提交了一个linux内核中的任意递归漏洞。如果安装Ubuntu系统时选择了home目录加密的话,该漏洞即可由本地用户触发。如果想了解漏洞利用代码和短一点的漏洞报告的话,请访问https:/
linux 内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍 linux 内存组织结构和页面布局,内存碎片产生原因和优化算法,linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的机制和奥秘。
导语 linux 内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍 linux 内存组织结构和页面布局,内存碎片产生原因和优化算法,linux
作者:freeboy1015 来源:http://lib.csdn.net/article/linux/62126 一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。 当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用.但需注意,直
已经过去的中间件性能挑战赛,和正在进行中的 第一届 PolarDB 数据性能大赛 都涉及到了文件操作,合理地设计架构以及正确地压榨机器的读写性能成了比赛中获取较好成绩的关键。正在参赛的我收到了几位公众号读者朋友的反馈,他们大多表达出了这样的烦恼:“对比赛很感兴趣,但不知道怎么入门”,“能跑出成绩,但相比前排的选手,成绩相差10倍有余”…为了能让更多的读者参与到之后相类似的比赛中来,我简单整理一些文件IO操作的最佳实践,而不涉及整体系统的架构设计,希望通过这篇文章的介绍,让你能够欢快地参与到之后类似的性能挑战赛之中来。
glibc 提供的 ptmalloc 函数 , FreeBSD 提供的 jemalloc 函数 , Google 提供的 tcmalloc 函数 ,
① 用户应用程序调用 : 开发者 在 " 用户空间 “ 的 应用程序 中调用 malloc 等函数 , 申请 动态分配 ” 堆内存 " ,
Java 凭借着自身活跃的开源社区和完善的生态优势,在过去的二十几年一直是最受欢迎的编程语言之一。步入云原生时代,蓬勃发展的云原生技术释放云计算红利,推动业务进行云原生化改造,加速企业数字化转型。
以交友平台用户中心的user表为例,单表数据规模达到千万级别时,你可能会发现使用用户筛选功能查询用户变得非常非常慢,明明查询命中了索引,但是,部分查询还是很慢,这时候,我们就需要考虑拆分这张user表了。
在开发微信看一看期间,为了进行耗时优化,基础库这层按照惯例使用tcmalloc替代glibc标配的ptmalloc做优化,CPU消耗和耗时确实有所降低。但在晚上高峰时期,在CPU刚刚超过50%之后却出现了指数上升,服务在几分钟之内不可用。最终定位到是tcmalloc在内存分配的时候使用自旋锁,在锁冲突严重的时候导致CPU飙升。为了弄清楚tcmalloc到底做了什么,仔细了解各种内存管理库迫在眉睫。
领取专属 10元无门槛券
手把手带您无忧上云