《Linux性能优化实战》学习笔记 Day02

news2024/10/5 16:24:48

02 | 内存池:如何提升内存分配的效率?

原文摘抄

在 Linux 系统中,用 Xmx 设置 JVM 的最大堆内存为 8GB,但在近百个并发线程下,观察到 Java 进程占用了 14GB 的内存。为什么会这样呢?

绝大部分高级语言都是用 C 语言编写的,包括 Java,申请内存必须经过 C 库,而 C 库通过预分配更大的空间作为内存池,来加快后续申请内存的速度。这样,预分配的 6GB 的 C 库内存池就与 JVM 中预分配的 8G 内存池叠加在一起(只有程序申请堆外内存时,才会分配C库内存池;否则不会申请),造成了 Java 进程的内存占用超出了预期。

应用层-C库内存池-操作系统内核
在这里插入图片描述

每个子线程预分配的内存是 64MB(Ptmalloc2 中被称为 Thread Arena,32 位系统下为 1MB,64 位系统下为 64MB)。如果有 100 个线程,就将有 6GB 的内存都会被内存池占用。这也就是为什么平凡的创建销毁线程浪费资源的原因。

通过设置 MALLOC_ARENA_MAX 环境变量,可以限制线程内存池的最大数量。可以更换掉 Ptmalloc2 内存池,选择一个预分配内存更少的内存池,比如 Google 的 TCMalloc。

TCMalloc 适用的场景,它对多线程下小内存的分配特别友好。

Ptmalloc2 假定,如果线程 A 申请并释放了的内存,线程 B 可能也会申请类似的内存,所以它允许内存池在线程间复用以提升性能。

因此,每次分配内存,Ptmalloc2 一定要加锁,才能解决共享资源的互斥问题。然而,加锁的消耗并不小。TCMalloc 针对小内存做了很多优化,每个线程独立分配内存,无须加锁,所以速度更快!线程数越多,Ptmalloc2 出现锁竞争的概率就越高。当应用场景涉及大量的并发线程时,换成 TCMalloc 库也更有优势!

在这里插入图片描述

Ptmalloc2 更擅长大内存的分配。TCMalloc 把内存分为 3 个档次,小于等于 256KB 的称为小内存,从 256KB 到 1M 称为中等内存,大于 1MB 的叫做大内存。TCMalloc 对中等内存、大内存的分配速度很慢,比如我们用单线程分配 2M 的内存,Ptmalloc2 耗时仍然稳定在 32 纳秒,但 TCMalloc 已经上升到 86 纳秒,增长了 7 倍以上。

  • 所以,如果主要分配 256KB 以下的内存,特别是在多线程环境下,应当选择 TCMalloc;否则应使用 Ptmalloc2,它的通用性更好。

提问:如何判断JAVA应用在申请的内存主要是256KB以下的小内存,还是大内存呢?

从栈中分配内存会更快。这是因为,由于每个线程都有独立的栈,所以分配内存时不需要加锁保护,而且栈上对象的尺寸在编译阶段就已经写入可执行文件了,执行效率更高!

  • 所以,当我们分配内存时,如果在满足功能的情况下,可以在栈中分配的话,就选择栈。

小结:

隐藏着的 C 库内存池,对进程的内存开销有很大的影响。当进程的占用空间超出预期时,你需要清楚你正在使用的是什么内存池,它对每个线程预分配了多大的空间。

提问:如何去搞清楚使用的是什么内存池,对每个线程预分配了多大的空间。

即使对第三方组件,我们也可以通过 LD_PRELOAD 环境变量,在程序启动时更换最适合的 C 库内存池(Linux 中通过 LD_PRELOAD 修改动态库来更换内存池,参见示例代码)。

评论区:

  1. bcc的xfsslower和ext4slower工具。可以跟踪大于特定时长的延时。

  2. 解决ptmalloc2内存过大的三种方案(转自http://fengfu.io): 第一种:控制分配区的总数上限。默认64位系统分配区数为:cpu核数*8,如当前环境16核系统分配区数为128个,每个64M上限的话最多可达8G,限制上限后,后续不够的申请会直接走mmap分配和munmap回收,不会进入ptmalloc2的buffer池。 所以第一种方案调整一下分配池上限个数到4: export MALLOC_ARENA_MAX=4 第二种:之前讲到ptmalloc2默认会动态调整mmap分配阈值,因此对于较大的内存请求也会进入ptmalloc2的内存buffer池里,这里可以去掉ptmalloc的动态调整功能。可以设置 M_TRIM_THRESHOLD,M_MMAP_THRESHOLD,M_TOP_PAD 和 M_MMAP_MAX 中的任意一个。这里可以固定分配阈值为128K,这样超过128K的内存分配请求都不会进入ptmalloc的buffer池而是直接走mmap分配和munmap回收(性能上会有损耗,当前环境大概10%)。:

    export MALLOC_MMAP_THRESHOLD_=131072

    export MALLOC_TRIM_THRESHOLD=131072

    export MALLOC_TOP_PAD_=131072

    export MALLOC_MMAP_MAX_=65536

    第三种:使用tcmalloc来替代默认的ptmalloc2。google的tcmalloc提供更优的内存分配效率,性能更好,ThreadCache会阶段性的回收内存到CentralCache里。 解决了ptmalloc2中arena之间不能迁移导致内存浪费的问题。

  3. JAVA堆外内存问题排查

心得体会

  1. java还是在他人的基建上造房子,光写java业务会忽视这样的基建,对自己的new关键字做了什么并不是很清楚。

    是在栈,还是堆中分配内存。(当然,JVM的内存逃逸分析会帮我们把一些分配在堆中的对象直接分配在找上,加速运行)(栈的容量有限,如 CentOS 7 中是 8MB 字节)

    是用的哪一种C语言的内存池。

工作体验

  1. 工作中,内存的分配基本没有太深入了解。对于java程序员,关注的更多是,减少大对象,防止内存泄露。

相关阅读

TCMalloc:线程缓存Malloc以及tcmalloc与ptmalloc性能对比

linux内存管理(十五)-内存池

[Linux 内核内存池]()

03 | 索引:如何用哈希表管理亿级对象?

原文摘抄

索引有很多,哈希表、红黑树、B 树都可以在内存中使用,如果我们需要数据规模上亿后还能提供微秒级的访问速度,那么作为最快的索引,哈希表是第一选择。

用近似的时间复杂度描述运行时间,好过实地运行得出的精确时间。

哈希表基于数组实现,而数组可以根据下标随机访问任意元素.

位图”,它的时间复杂度也是 O(1)。不过本质上,它是哈希表的变种,限制每个哈希桶只有 1 个比特位,所以,虽然它消耗的空间更少,但仅用于辅助数据的主索引,快速判断对象是否存在。

红黑树的时间复杂度就是 O(logN)。如果需求中需要做范围查询、遍历,由于哈希表没办法找到关键字相邻的下一个元素,所以哈希表不支持这类操作,我们可以选择红黑树作为索引。

如果红黑树过大,内存中放不下时,可以改用 B 树,将部分索引存放在磁盘上。

磁盘访问速度要比内存慢很多,但 B 树充分考虑了机械磁盘寻址慢、顺序读写快的特点,通过多分支降低了树高,减少了磁盘读写次数

对于动态(元素是变化的)哈希表,我们无法避免哈希冲突.链接法、开放寻址法。

链接法虽然实现简单,还允许存放元素个数大于数组的大小(也叫装载因子大于 1),但链接法序列化数据的代价很大,因为使用了指针后,内存是不连续的。开放寻址法确保所有对象都在数组里,就可以把数组用到的这段连续内存原地映射到文件中

降低哈希表的冲突概率:第一个办法是调优哈希函数,第二个办法就是扩容。

BKDR 是优秀的哈希算法,但它不能以 2^8 作为基数,这会导致字符串分布不均匀。这里只需要记住,基数必须是素数就可以了。事实上,我们应当找一个合适的素数作为基数,比如 31,Java 标准库的 BKDR 哈希算法就以它为基数,它的计算量也很小:n31 可以通过先把 n 左移 5 位,再减去 n 的方式替换(n31 == n<<5 - n)。

评论区:

Reids中没有使用红黑树而是使用了跳表skiplist,因为skiplist支持区间查找

布隆过滤器是最优于不存在的一定不存在,存在的不一定存在.

心得体会

  1. 索引是对数据结构查询加速的数据结构。
  2. 索引的数据结构多样,如何选用主要取决于需求(精确查找、范围查找),以及数据特征(连续性,区分度)。

工作体验

  1. 对于表、列信息在内存中的数据结构,由List改为Hash,创建后只读的需求。不必进行循环查找,算法复杂度从O(n)变为了O(1),牺牲了空间。

  2. 亿级的数据量,对内存的要求真的会很高。曾经在zookeeper监听一个节点后,消费数据的速度跟不上变化的速度,在客户端的无界队列中滞留了4亿条消息,导致OOM(jvm堆内存4G)。

    另外,也层遇到过文件导出的需求,从ElasticSearch中查询百万级的数据并生成Excel,也遭遇了OOM。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图论】「极简复习版」最短路径 Java/C++ 实现

文章目录Dijkstra —— 单源最短路讲解图解Java朴素使用堆优化C朴素使用堆优化Floyd —— 多源最短路讲解JavaCDijkstra —— 单源最短路 讲解 时间复杂度 朴素 Dijkstra&#xff1a;O(n2)O(n^2)O(n2) &#xff0c;nnn 是顶点数。堆优化 Dijkstra&#xff1a;O(mlogn)O(m\ l…

第五届字节跳动青训营 前端进阶学习笔记(三)CSS基本概念

文章目录前言CSS是什么1.CSS基本结构2.在面中使用CSS的方式3.CSS是如何工作的选择器1.通配选择器2.标签选择器3.id选择器4.类选择器5.属性选择器6.伪类选择器7.选择符颜色1.RGB颜色2.HSL颜色3.alpha透明度字体1.font-family2.font-size3.line-height4.text-align5.space6.text-…

从头搭建pytorch Docker镜像

目录前言正文从docker hub下载镜像创建容器并运行更新容器*安装python*安装anaconda安装pytorch参考文献&#xff1a;前言 此文不需要前言&#xff0c;请从正文开始 开始搭建 正文 默认大家都是有一定docker基础的&#xff0c;没有的话建议去花个20分钟学一下基础知识。相对…

如何利用极狐GitLab 轻松管理NPM依赖发布与更新?

本文来自&#xff1a; 任治桐 极狐(GitLab) 前端工程师 NPM 是 Node.js 的包管理工具&#xff0c;用来安装各种 Node.js 的扩展。本文将分享如何通过极狐GitLab&#xff0c;让 NPM 依赖发布更新更加快速和自动化&#xff0c;让你轻松管理依赖&#xff0c;拥有更多时间专注于核…

【Java|golang】1814. 统计一个数组中好对子的数目

给你一个数组 nums &#xff0c;数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) 321 &#xff0c; rev(120) 21 。我们称满足下面条件的下标对 (i, j) 是 好的 &#xff1a; 0 < i < j < nums.length nums[i] rev(…

算法之美~时间复杂度

时间复杂度 时间复杂度的全称是渐进时间复杂度&#xff0c;表示算法的执行时间与数据规模之间的增长关系1、只关注循环执行次数最多的一段代码2、加法法则&#xff1a;总复杂度等于量级最大的那段代码的复杂度3、乘法法则&#xff1a;嵌套代码的复杂度等于嵌套内外代码复杂度的…

文末有福利 | 零代码连接邮箱腾讯云企业网盘,附件管理超轻松

在日常工作中&#xff0c;想必大家每天都会收到各种各样的工作邮件&#xff0c;并且很多重要的文件材料也是通过邮件附件的形式来传输的&#xff0c;那么如何一站式管理这些文件&#xff0c;对于提高办公效率就至关重要了。关于邮件附件&#xff0c;相信大家也都碰到过这样的困…

【软件相关】Typora配置图片上传

文章目录0 前言1 确定需求2 开始配置2.1 软件储备2.2 插件安装2.3 gitee配置3 其他配置3.1 获取SMMS token参考链接0 前言 对于喜欢写Markdown文档的人来说&#xff0c;Typora无疑是一个写作利器&#xff0c;它有别于其他的Markdown软件&#xff0c;不是一边编辑一边渲染&#…

excel区分工时制度:如何计算996与955的工时差异

什么是996呢&#xff1f;是指早上9点上班&#xff0c;晚上9点下班&#xff0c;中午和晚上各有1小时吃饭时间&#xff0c;每周工作6天的工作模式。而955&#xff0c;也就是朝九晚五&#xff0c;中午就餐在工作时间内&#xff0c;但不能休息&#xff0c;共计8小时工作时间&#x…

[FUNC]在AHK中实现Pyhton的range函数

本文是用AutoHotkey复刻Python的range函数函数语法range(start, stop, step)参数说明&#xff1a;参数描述start计数从 start 开始。默认是从 0 开始。例如&#xff1a;range&#xff08;6&#xff09;等价于range(0,6)。stop计数到 stop 结束&#xff0c;但不包括 stop。例如&…

5、Ubuntu20常用操作_进程管理重定向和管道常用命令网络管理

进程管理 进程的概念 大家比较熟悉 Windows 下的可执行文件&#xff0c;就是那些扩展名为exe的文件。 大家知道&#xff0c;只需要鼠标双击这些程序&#xff0c; 就可以运行了。 程序运行起来后&#xff0c;我们把这个程序正在运行的 实例 称之为 进程 。 操作系统对每个进…

acwing86场周赛题解(模拟,dp,数学推导式)

目录 第一题&#xff1a;AcWing 4794. 健身 思路 核心代码 完整代码 第二题&#xff1a;4795. 安全区域 思路 核心代码 完整代码 第三题&#xff1a;4796. 删除序列 思路 核心代码 完整代码 谢谢您的阅读 第一题&#xff1a;AcWing 4794. 健身 4794. 健身 李华…

配置与管理DNS服务器

DNS概念 DNS是一种新的主机名称和IP地址转换机制&#xff0c;使用分层的分布式数据库来处理Internet上众多的主机和IP地址转换。当一个应用需要将域名翻译成为IP地址时&#xff0c;这个应用便成为域名系统的一个客户。这个客户将待翻译的域名放在一个DNS请求信息中&#xff0c;…

CHAPTER 10 Web服务与应用(二)

Web服务与应用10.1 Tomcat10.1.1 准备工作10.1.2 编写dockerfile10.1.3 创建tomcat用户和密码脚本文件10.1.4 编写启动脚本10.1.5 创建和测试镜像10.1.6 相关资源10.2 Jetty10.2.1 使用官方镜像10.2.2 相关资料10.3 LAMP10.3.1 使用官方镜像10.4 持续开发与管理10.4.1 Jenkins及…

[前端笔记——HTML介绍] 5.文档与网站架构

[前端笔记——HTML介绍] 5.文档与网站架构1.文档的基本组成部分&#xff08;1&#xff09;页眉&#xff08;2&#xff09;导航栏&#xff08;3&#xff09;主内容&#xff08;4&#xff09;侧边栏&#xff08;5&#xff09;页脚2.用于构建内容的HTML3.HTML布局元素细节3.1无语义…

205:vue+openlayer: 点击某feature,列表滑动,定位到相应的点的列表位置

第205个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers做一个互动,点击某个feature,在左侧的列表中显示出来,滚动条滑动,能显示在视觉区内。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其…

HTB打靶(Active Directory 101 Resolute)

nmap扫描 nmap -A -T4 10.10.10.169 Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-16 01:30 EST Stats: 0:00:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 74.65% done; ETC: 01:30 (0:00:01 remaining) St…

Maven学习(一):Maven简介及安装配置

Maven简介及安装配置一、Maven简介1.1、Maven是什么1.2、Maven的作用二、Maven安装配置2.1、大前提2.2、Maven下载2.3、windows版1、安装2、配置环境3、配置本地仓库2.4、mac版1、安装2、配置环境3、需要注意的点4、配置本地仓库一、Maven简介 1.1、Maven是什么 先对Maven做一…

从 Spectral Clustring 推导到 Regularized Diffusion Process

Spectral Clustring 参考&#xff1a;bilibili 机器学习-白板推导系列(二十二)-谱聚类&#xff08;Spectral Clustering&#xff09; Background 首先看一种数据分布&#xff1a; 对于以上分布的数据&#xff0c;可以直接利用K−meansK-meansK−means或者GMM&#xff08;高…

2、linux_CentOS_6_64位常用命令远程操作--yum云用不了_建议学习Ubuntu

Linux的概述 学习Linux之前先了解Unix Unix是一个强大的多用户、多任务操作系统。于1969年在AT&T的贝尔实验室开发。UNIX的商标权由国际开放标准组织&#xff08;The Open Group&#xff09;所拥有。UNIX操作系统是商业版&#xff0c;需要收费&#xff0c;价格比Microsof…