粉丝1.8万获赞9.4万

今天我们看一下如何在线上排查我们 gpm 内存易出的问题。那首先看到这个界面,这是我们国人法的一个内存监控界面,我们可以看到这是我们的一个内存使用情况,以及我们的 cpu 的一些使用情况。 ok, 那么接下来我们模拟一下我们的内存飙升。好,那首先设置我们一个启动参数,将我们的堆的最小值和堆的最大值设成一百兆,还去设置这个参数,那这个参数他当我们 om 发生时,他会自动当铺一个堆内存信息,那下面他可以改变我们一个地址。 ok, 好, 那这里我们有三个 u r l, 好,我们去代码里面看一下这三个 u r l。 首先看到我们这里,我们这里有 test up 一和我们的 test up 二以及我们的 test out of memory。 好,那我们点进去看一下,我们看到这里我们的 test up 一和我们的 test up 二,它, 它是不是对我们的一个开启 map 做了修改。好,我们点进去看一下它是不是循环给它铺的值,对不对?好,那再看到我们一个 testo memory, 好,这里它是不是对我们那个 memory map, 是不是对它进行一个循环添加,是不是?好,那么现在我们看到我们这里 是不是有两个 map, 对不对? ok, 那这时候我们模拟一下我们的内存飙升。好,那首先是我们的一个第一个 ul, 好,我们访问一下我们的第一个 url, 好,请求成功,我们看一下他现在是不是已经执行完了,对不对?好,那这个时候看一下我们内存的一个使用情况,我们先是百分之二十九了,是不是?是不是在升高,对不对?好,我们再刷新一下, 我们稍微等待一下。 好,我们可以看到我们这个定律层是不是已经使用了百分之五十几了,是不是? ok, 那现在我们继续让它再继续飙升。好,访问我们的第二个 url。 好,我们看一下我们后台,我们这里是不是也执行完了?是不是我们那个 test r 牌啊?是不是?好,那现在我们再去看它内存的一个使用情况。 好,我们现在可以看到他现在是百分之七十八点几,并且他颜色都变了,对不对?他现在是不是已经在告警了?好, 那这个时候我们去分析一下我们一个内存的一个使用情况。好,那么下面看,那么我们可以通过我们那个 gps 查看一个进程,通过我们的降谱,我们去下载他的一个对内存信息,那么我们因为我们这边已经安装好我们那个 x 为头,所以说 我们可以通过他来下载我们的当谱文件。好,那么现在我们用这个来去下载我们的当谱文件。好,这是我们的 ipip 改成幺二七点零点零点幺,那么是我们的 pod, 是我们的一个八零八零端口,是不是?好,那么现在我去下载这个当谱文件。 好,他现在是不是已经下载完了?那么现在这个时候我们用我们的一个工具去分析下他这个灯内存一个使用情况。好,那这里有我们的一个 mat, 以及我们还可以使用我们的一个 jprofer, 还有我们的一个微锁 vm。 ok, 那么现在我们去打开我们的刚刚下载的这个当谱文件,那么这里选择我们的一个 warfare。 ok, 我们可以看到我们的一个 hype 当谱,是不是?好,那么等它加载完成。 ok, 好,那么 现在我们看到这里,我们这里是不是有很多个选项?好,那首先点击我们这个地方,我们可以看一下他这里是不是将我们那个内存的一个使用情况和一个占比是不是都显示出来了?并且他是按照从大到小的一个顺序排列的,是不是?好,那么现在我们去看一下他这里面 是什么样子的? ok, 这里是不是我们看占比最高的,是不是?好,那我们再看这个好像都看不出什么信息出来,那么接着我们往下面看, ok, 好像也看不出什么信息出来,那么再往下面看。好,我们看到这里,他这里是不是说,哎,我们这里是不是有三个属性?我们有一个 random, 还有两个哈西 map, 是不是?好,再往里看, 我们可以看到这里是不是有两个哈西 map, 这两个哈西 map, 我们有一个哈西 map, 他的一个占比的内存是不是比较高?哎,那这个时候我现在到底是哪个哈西 map? 我再点进去看一下。好, 那我们是这样看,是不是看不出太多信息?我不知道他是哪一个还是 map, 对不对?好,那这时候怎么办? ok, 那现在在这个页面我们看一下,我们点击这个地方,好,我们点进去看一下,我们看到这里 他是不是分析出我们这里有一个问题,是不是?好,我们看一下,我们在这里是不是看不出太多信息?但是我们在这里可以看到他一个内存占比是不是占了一个百分之八十六点三五,对不对?这是我们的一个内存占比,这是我们一个内存的一个占的一个使用情况。好, 那接下来我们可以看到它是不是提示我们一个哈士 map, 是不是?那是哪个哈士 map? 我现在是不是还是没有分析出来,对不对?好,那这时候点击我们的一个 detail, 我们再进去看一下。哎,在这里我们可以看到这边是它的一个内存的一个使用情况,是不是?好,那我们再看到这里,我们这里是不是 它的一个内存占率是不是也比较高?这是谁?这是我们的是不是 catch map, 对不对?好,那么我们看到我们的 catch map, 他在我们哪个内里面?他是不是在我们一个 test service 一个实现内里面?好,那我们找到我们的 test service 实现内,我们是不是这里?那找到我们的一个开启 map, 我们可以看到他现在是不是有三个地方,第一个是我们一个初始化,然后是我们的 test app 一和我们 test app 二,我们这两个地方是不是有使用到了我们的这个 catch map, 对不对?好,我们点进去看一下 他这里是不是在便利去给他铺的值。 ok, 那说明他这个时候他铺的这个占的内存比较高,说明他铺的这个值比较多,是不是?好? 王大萌,现在是不是找到这个内存升高的一个原因了?是不是说明是我们的一个开启 map, 它占用内存比较多?好,那继续我们让我们的一个内存一出。 好,我们再看一下,让我们内存一出。 哎,他现在是不是还在执行?我们可以看到之前我们执行我们的 test up 一和我们 test up 二,他是不是很快执行完的?那在这里为什么他执行这么慢?那是因为我们现在内存是不占用已经很高了,所以说这时候他会影响到我们一个执行速度,对不对?甚至我们内存溢出还可能导致我们一个程序崩溃。好,那么现在我们等他执行完 好,我们这里可以看到它是不是帮我们生成了一个 p i d 三二九六的,而且 profit 文件,对不对?并且这时候它是不是这里报错了?哇?下面看一下它是报什么错误? 它这里是不是提示我们一个 out of memory 异常是不是?好,那这时候我们去分析下我们这个 p i d 文件。好,那我们刷新一下我们的项目。好,我们可以看到我们这项目这里是不是也有对应的一个 p i d 文件,对不对?好,那这个时候我们去分析我们的 p i d 文件。好,找到我们这个项目所在的文件夹。 ok, 我们可以看到这是不是这个三二九六?是不是?我们打开它,好,我们等待加载完成。 ok, 那么接下来我们分析一下我们这个三二九六这个文件。好,我们点到这里,首先还是看他这个内存的一个使用情况,他的占比是什么样子的, 我们可以看到他这里有一个是不是占用了一个百分之五十九点零三,还有一个是百分之二十八点七八,是不是?那我们之前是不是在这 也没有分析出什么原因出来,是不是?那这个时候,哎,那我们直接在这里来分析。好,我们看一下他这里是不是帮我们分析出有两个问题,对不对?那我们看第一个问题,哎,这里是不是有我们一个 test safs 的一个实现类,对不对?他这里说,哎,我们这里是不是有个哈西卖铺,他这个占比是百分之五十九点零三,是不是? 好,那这里我们再往下看,往这里看,是不是也不知道是哪个?它是 map, 对不对?那我们再往里面看。好,我们看到这里,这里是不是说我们这个开启 map, 对不对?我们开启 map, 它不是占比也比较高,它告诉我们这是我们的一个 cast sever 的一个实现内,我们这里是不是导致占用了我们比较多的内存?好, 那再看我们第二个问题,好,我们看第二问题,它的数也是说一个哈士 map, 它的占比是百分之二十八点七八,是不是?那再往里面看,它也是 指向我们的 test seven 实线内,好,那再往里面看,我们这里是不是也不知道是哪个哈西卖普,对不对?因为我们有几个哈西卖普?好,我们再往里面看,这里他被提示了,哎,我们看到他一个内存占比,是不是?这里是不是占的比较高?他这里提示我们有一个 memory map, 是不是?好,他在哪里?是不是在我们的 test service 的一个实现内,对不对?好,那找到我们 test service 的一个实现内,那么我们再去看我们那个 memory map, 好, 我们找到它,哎,它在这里是不是有使用到?还有出在哪里?这是它一个初始化,对不对?好,那我们看到这里说明我们这个 memory map 它占用一个内存比较高,是不是?那,那这时候我们分析出来我们占用内存比较高的原因,那像我们这些缓存是不是? 那我们是不是应该保存到内存里面呢?哦,那我们可不可以换另外一种方案,比如说保持在我们的 reds 里面是不是?好?那这样可以防止我们在档期的情况下,哎,我们的数据丢失,是不是?好? 那以上就是我们线上如何排查我们 g v m 内存溢出问题,那下面还有我们的一些笔记,那里面包括我们一些,嗯,如何去用我们的 mat 软件来去分析我们的这个内存溢出问题? 还有我们的一个 supreme 部特项目,以及我们普罗米修斯的一个环境搭建,以及我们的国人法的一个环境搭建。好,我们这里有一些详细的配置。 另外如果说大家还想学的话,那么我们这里还有我们的一些框架原码,以及我们的性能调优,以及我们的分布式为服务,还有我们的项目实战,以及我们的 ai 人工智能技术简历优化等技术干货,可以在评论区留言或者置顶消息获取。

案例, es 的 内存溢出,盲目加内存,忽略了聚合查询的内存模型。 一个提供商品权威检测的 es 集群,在应对一个复杂聚合查询时,比如按品牌、属性等多维度分组统计节点,频繁发生内存溢出重启。 应用团队持续为 es 数据节点增加多内存,从十六 g 加到三十二 g 加到六十四 g, 同时怀疑是分片不均,进行了大规模的分片重平衡操作。 结果呢?内存加的越大,发生负 g c 的 停顿时间越长,最终整个节点因一次漫长的 g c 而失联,触发分片重分配,引起疾群整大 重平衡操作本身也消耗了大量网络和 i o 资源,在业务高峰期间家具了问题,系统越优化越不稳定。 根本原因,团队对聚合查询的内存消耗原理完全不了解。 e s。 在 执行深度分页,比如 from 等于一万, size 等于十,或者大型聚合,比如它们是聚合的 size 设置过大的时候, 需要在协调数据节点上构建巨大的局域优先级队列或者哈希表,数据量可能远超单个请求的承受范围。 简单加内存治标不治本,而且会延长计算的恢复时间。 低信原理启示,必须理解查询的数据规模和中间结果。对内存的消耗模型优化不是简单的加内存,而是要让查询本身更轻。 正确的优化方向,限制查询范围,通过业务设计,避免用户进行过深的分页或者超大范围的聚合。使用 search after 替代深度分页,让用户只能一页一页往后翻,不能直接跳到第一万页。 优化聚合查询,使用 passing 参数进行聚合结构的分布式处理快使用 composite 聚合进行流式分批访问,避免一次构建过大的数据结构。 监控与防护,在应用层或 es 插件层对查询的 form 加 size、 聚合的 size、 脚本使用等进行限制,拦截危险的查询请求。比如规定聚合的 size 最大不能超过一千,深度分页不能超过一万。 总结,盲目加内存,忽略了聚合查询的内存模型。 搜索引擎不是数据库,别拿它当 o l a p 用。聚合查询越复杂,内存消耗越恐怖,加内存只会让你死得更慢。

明明只是输入一个名字,怎么就让电脑原地爆炸了?欢迎收看本期硬核防黑客指南内存溢出大作战嘿嘿,写个小程序存名字,名字越长越霸气!回车 小宝,你是不是又搞出内存溢出了?冤枉,我只是输了个名字,它就自爆了!看这个杯子,你只申请了十字节,却硬塞五十字节数据,哎呀,水溢出来把我的作业弄湿了!这就是缓冲区溢出,多出的数据会覆盖旁边重要的内存,比如程序的返回地址, 因为在内存占里,变量都是姐挨着存放的。完蛋!地址被覆盖后,程序找不到回家的路,直接崩溃了。 呵呵,崩溃是小事,如果把一处数据改成精心设计的恶意代码,再让返回地址指向它,你的电脑就被我接管了。千密山库,随心所欲,救命! c 家家太可怕了,我要回火星!别怕,这通常是老式写法,比如 stark 不 查边界的锅。可是很多老教材还是这么教啊! 时代变了,现代 c 加加有更安全的工具介绍新朋友,动态数据库 s t d vector 哇,数据放进去,它居然会自己长个子!没错,它动态管理内存,从根源减少溢出。如果要用固定大小的数据库,就用 s t d ray 加 at 访问。 我来摸摸第一百个格子 b, 越界访问,禁止 at 自带边界检查,直接报错停止总比被黑客控制好。记住底线,拒绝裸指真核叉二序组拥抱 stream factor 和 at, 永远别信用户的输入。这次用现代 c 加加重写安全编程,从我做起,喵!

小新电子文盲计划第十三期清理流氓软件这下好了,小时候叫你去网吧搞的跟要害你一样,现在好了,电脑一大堆垃圾就不会清理。 所以这期我将以身入局,亲自下载那些新手很容易下到的流氓软件,并教你如何分辨流氓软件。点赞、关注、收藏,咱们直接开始。当你看到这满屏幕的弹窗,你就知道新手有多无助了吧。刚下载完,他们就开始互相打起来了,而且内存也被他们占用了特别多,这就是很多人觉得电脑卡的原因。接下来跟着我操作,首先搜索控制面板, 再点击卸载,进来后就可以看到所有的软件了,然后教你们怎么分辨流氓软件,三六零就不说了,老流氓了都是, 哈哈哈。这里大家只需要记住,凡是什么优化和什么清理工具都一律视为垃圾软件,按照这个套路就好找一些,后续就是直接删掉就可以,有实力的小伙伴也可以借助工具卸载,比如 hitbit 之类的,别下错就行。 nice!

线上 java 进程 c p u 飙到百分百,动不动就内存溢出,重启就好,过一会又挂,很多人还在一行行看日历,那效率太低了。今天带你用两把瑞士军刀接 m a p 和 m a t, 直接把问题代码揪出来。 本期视频最后,我准备了一份 java 面试场景题合集,需要的直接找我拿。首先我们要获取犯罪现场的证据,也就是 hack dump, 用 jdk 自带的 jmp 命令最直接。先通过拓普或者 jps 找到你那该死的 java 进程 pid, 然后敲下这行命令, 敲黑板。这里有个小技巧,加上逆斧参数,告诉 jvm 指段普存货对象,这样文件更小,分析更准。执行成功后,你就会得到一个点 php 文件, 这个文件就是内存的 ct 扫描片。拿到片子我们得用专业设备看 clevis m a t, 就是 那个毒片医生。打开 m a t, 直接拖入刚才的 help, 点 help 文件加载完,第一个要看的就是立刻输 space 看 m a t 非常智能,它直接给出了问题概要,一个 area list, 占用了百分之九十七的内存。点进去查看 details, 这里会展示这个对象的 g c route 引用链,通俗点说就是谁一直拽着这个对象不撒手,导致垃圾回收器收不掉。 为了更精确地找到代码行数,我们切换到 demote, 按 retain helper 排序。也就是说,如果这个对象被回收,能释放多少内存?排最前面的往往就是元凶。 右键它选择 magi shorttest pass to g c route, 排除弱。引用 看到没,路径指向了我们项目里的 user service 的 第一百一十八行,赶紧打开 id 看看这行代码,哦,原来是一个静态的 map, 把 list 当做缓存了,只增不减。这就是典型的内存泄露。 删除这行代码问题解决排查内存泄露其实就像破案接 m a p 负责取证, m a t 负责分析。学会这招,线上故障从此变得简单。 老规矩,这份详细的加码面试场景题我已经打包好了,需要的同学直接找我领取。我是旧恒,每天一个实战技巧。

慢性胃炎,胃溃疡,很多 java 程序员啊,在线上出现性能问题的时候,根本就做不到认准病,根治胃痛啊, 那么怎么回事呢啊?我们很多 java 程序员在线上出现性能问题的时候,比如说,比如说内存方面的性能问题的时候啊,我们很多 java 程序员呢,他只有一个办法,那就是呢,直接把这个内存呢淡化下来, 淡泊下来之后呢,然后呢用一些工具呢进行分析啊,那么这个方法到底行不行呢啊,其实呢,这个方法呢不太靠谱啊, 因为我们的内存问题呢,他有很多方面的内存问题啊,那我们淡泊呢,我们只能够呢从一个方面呢来看,这个内存方面的问题 好,那么内存方面的问题呢,有几个呢?我这里呢总结了有三个方面的问题啊,首先呢是内存溢出的问题啊,其次呢是内存泄露的问题啊,然后第三个呢是内存啊,就是 g c 过高的问题啊, 好,那么这三个问题呢,我们通过大火能不能解决呢?好,我们呢一个一个来跟大家说啊, 首先呢第一个啊,内存溢出的问题啊,这个问题呢,确实是可以通过档口呢来解决啊,因为呢档口啊,因为呢 啊,我们在内层溢出的时候呢啊,这个呢,我们需要去分析呢,他有哪些大的对象,对吧?导致呢这个内存增长的很快啊,然后呢一直不会被这个垃圾回收呢,进行回收啊,这个是可以的好,那么第二个呢就是内存泄露的问题, 那么内存泄露的问题呢啊,其实呢内存泄露呢,又分两种情况啊啊,一种情况呢,就是我们的 java 对 象呢,一直没有被回收 啊。然后第二种内存泄露的情况呢,就是我们 java 里面呢啊,有一种叫对外内存泄露啊, 好,那么在这个这个内存泄露这个情况,通过大户能不能解决呢啊?答案是肯定不行的啊。啊,我们呢,首先要了解一下啊,这个内存溢出呢,它是一个什么情况 啊?内存,内存泄露啊,内存泄露呢,它是一个什么样的情况啊?那么内存泄露呢, 它指的是啊,一块内存呢,一直被我们的进程呢占用,然后呢一直得不到回收 啊,比如说我们的 java 里面呢,一个对象一直占用这个内存啊,一直得得不到回收啊,这是一种情况,对吧?还有呢,就是对外内存泄露啊,那么这个对外内存泄露呢,跟我们的 c 语言啊,谁家家里面的内存泄露呢是一回事啊, 所以呢,大家想一下啊,这个 diy 内存线路肯定是不行的,对吧?啊,因为呢,它分配内存的方式呢,跟我们 c 语言里面的那个分配内存的方式呢,是一样的啊,所以呢,你大伙肯定解决不了 好,那么那些一直站在内层里面的,也就是一直占用内层的那些对象啊,就是这种类型的呢,能不能分析出来呢啊,其实也分析不出来啊,也就是说通过大分析不出来啊, 因为我们的大户呢,我们虽然说可以把这个对象大户出来,但是呢,我们并不知道这个对象的年龄是多大的,也就是呢,我们不知道这个对象呢,他在内存里面有多久了,不知道吧,所以呢,这个问题通过大户是解决不了的啊, 好,那么要通过什么样的办法呢?啊?这就给大家介绍一个工具啊,也就是呢,用 g 语言写的一个工具啊,就叫这么一个名字啊,大家呢可以自行去解决啊。好,那么第三个就是 g c 过高的问题, 那么 gc 过高的问题啊,它的本质原因是什么呢?啊? gc 高嘛,是不是呢?是不是说呢,我们这个分配的内存呢,分配的很频繁,对吧? 如果说你不断的去啊申请内存,或者是虐对象吧,啊,就是虐对象啊,那这个对象呢,很快又能够被回收,那是不是说这个时候你的 gc 呢就很高了, 所以这个时候你通过 dapp 啊,你能判断出哪些对象啊?他的这个啊,就是创建的频率特别的高吗?这个是你也很难分分辨出来,对吧? 啊,所以呢, g c 过高啊,这个问题呢,我们 dapp 是 dapp 不 出来的啊,啊,甚至有的时候呢,我们 dapp 出来啊,发现了这个 啊,弹拨出来内存呢,特别的低啊,只有,比如说只有一百兆或者那五十兆啊,我们弹弹拨出来的那个内存,但实际上呢,那个机身呢,特别的高啊,就是因为你弹拨的时候它刚好进行了一次 d c, 那 你怎么办呢?啊?所以弹拨不一定能够解决这个问题啊。 好,那么这个问题他的本质是什么呢?啊?就是你分配的这个频率太高了,对吧?所以呢,你要找到啊,他为什么分配的频率太高了,或者呢这个在哪个位置,哪一段大码分配内存的这个频率呢?太高了,是不是你要找到这个东西? 好,怎么找到这个东西呢啊?我给大家介绍一个工具,我肯定是行的啊,我们找到爱尔萨斯呢这个工具啊,找到这个工具呢,我们对它呢进行一个采用 啊,对它进行实践采用啊。啊,这样的话呢,我们就可以找到啊,哪一段大门呢?他在高频的去分配这个内存啊?也就是说呢,我们的内存分配一方面的火焰图啊。

因为内存明明是空的,为什么还会 o o m? 很多资深开发在第一次遇到这个问题时,都会怀疑是监控坏了。但实际上,这是因为内存泄露发生在了我们看不见的地方。通常容器被 care 后,我们去查监控,发现 java 堆内存及其健康完全没有溢出迹象。 真正承包物理内存的,其实是这块处于 a v m 管辖之外的堆外内存,它不受最大堆限制,却实打实占用的物理资源。这时千万别惯性思维去怀疑占一除或者原空间, 这种隐蔽的资源消耗大概率就是 direct buffer memory 在 作祟。要解决这个问题,必须搞清楚底层机制。 在 lady 或 nio 场景下,我们使用的 direct by the buffer 对 象本身很小,一举在 java 堆里,但它背负了一个特殊的 cleaner, 需引用,通过 gna 调用,直接在操作系统层面申请内存。这就形成了一个极不对称的关系, 加奥堆内存只是一个几百字节的引用,但它背后管理的却是几百兆的物理内存,而且逻辑在于这。当这个堆类的对象被 gc 回收时, tina 才会设法去释放底层的物理内存。如果对象一直存活,底层的内存就永远无法释放。这就引出了一个经典的生产事故陷阱。 当 nity 感知到堆外内存不足时,会尝试自救显示调用 c 四等 g c 试图强制回收掉,那就废弃对象。当我们在做界面调优时,为了防止卡顿,通常会配置 disable explicit g c。 这个初衷是好的配置,在这里直接屏蔽了 nity 的 求救信号。 结果就是街飞们认为堆内存还很空,不需要 gc, 而堆沃内存因为没有 gc 触发 cleaner 进不出,最终物理内存被耗尽,不直接宕机。遇到这种情况,不要靠拆开启 nmt 后置内存分布,或者用 top 配合 gdp 分 析拿到确凿证据 来解决这个死锁的终极方案不是禁用 g c, 而是驯服 g c, 将参数调整为 explicitity g c invoke concurant, 它允许 c 次的 g c 生效享用框架的轻低请求,但通过并发回收来避免全量停顿,既保住了内存安全,又保住了服务性能。

我看你简历上写的 g m 啊,你跟我讲一下,就是如果发生了 o m, 你 会怎么解决?嗯,就看它是不是堆内存溢出吧。呃,解决 o m 问题啊,首先呢,你要明确问题的类型对吧?你刚刚讲的堆内存溢出只是一种,还有堆外内存溢出和占溢出。 如果是堆内存溢出呢,一般就是内存泄露或者说堆大小设置不合适引起的啊,那么设置如果不合理呢,很好解决,直接去调整 g m 的 参数,增加堆内存就可以了。如果你担心简历上的东西讲不出来,我已经把面试经常问到的一些技术站 场景图都整理在两百万字的面试文档了,里面针对每个知识点都有很详细的解析思路,只要你是我的粉丝,留言六六六就可以打包带走。内存泄露呢,会稍微麻烦点啊,要么呢,就是通过 g m 的 参数,这里有一个 hit bump on auto memory arrow, 在 发生 o m 的 时候呢,我会自动挡不出堆的信息。要么呢就是用 gmap 导 找出内存快照,然后用 mac 工具去分析我们弹幕日制。一般呢,需要关注几个点,第一个查找内存对象里面的分布,特别是占内存最多的一个对象。而第二个分析这些对象的引流面,确定是哪部分代码引起的内存泄露,或者说过度消耗。如果是对外内存溢出呢,一般是 java 直接使用的非堆内存耗尽。 是的,大部分的情况。下面呢,还是出现在 java 里面的 nio 库啊,因为它允许 java 程序啊,以更加接近操作系统的方式去管理内存。解决办法呢,就是要么调整对外内存的大小,要么呢就是优化内存的使用,或者说用 v 四 v m 或者说呃 g profile, 然后排查是否有内存泄露的问题, 因为到问题以后呢,就及时的手动去释放内存,占一处呢是最好解决的,因为本质问题啊,就是现成请求的深度超过了 g m 的 最大深度,一般就是无限递归或者说方法调用的占过深引起的。

内存现在正在跳水啊,而且感觉这还只是一个开始,先看一下内存现在的实时价格,十六 g 的 ddr 五套调差不多在一千九左右,从最高点的两千四到现在差不多跌了快有百分之三十了, 虽然跌了不少,但是消费级市场的销量依然是铺盖状态啊,反而是硬盘市场比较坚挺,因为 ai 现在最擅长的东西就是海量的制造容与垃圾, 而且它生产垃圾的速度太快了,导致需要的存储空间是巨大的。但是内存这个玩意怎么说呢,高端市场其实并没有想象过那么全,毕竟老美很多的 h b m 还没有跑起来,堆在仓库里面吃灰。这个从 token 的 交易量是可以看出来的,就如果都跑起了,他们的 token 交易量一定是我们的好机会, 现在的电量还没有我们这边的多,他们可以买了不用,但是不能让我们有。现在真正是有 hbm 大 量需求的是咱们国内的企业,但是因为各方面的原因啊,咱们国内没有买,他们又不缺,所以内存这个玩意,这不就是跌到零头了吗?虽然已经跌了一部分,但是兄弟们别急啊,你不买我不买,明天还能降两百。

今天给大家分享一篇文章,这个解决方案几乎要把现在绝大部分瑞克的使用场景直接废掉,因为它能在几乎没有这种长上下文的资源损耗的情况下,能达到原身上下文窗口四倍以上, 并且它的大海捞针的这种性能能达到近乎完美的准确率,跟全量上下文加载的准确率是几乎一致。跟其他的解决方案 c、 d、 e 解决方案比起来,它的性能提高了,而且它的这种内存损耗也降低了非常的多。 它总体的一个解决原理就是通过把文档发给这个原始的大模型,然后通过一些 q a 问答,然后把这种每一层的一些东西弄出来,弄出来直接抽象成一个 lora 的 小模型,然后加载到这个之前的大模型上面, 再用查询的方式直接出来的结果。这个就是他们的一个解决方案的思路,他们跟这个全量上下文加载的性能是差不多的,我们来详细看一下这篇文章。这篇文章叫可 to lora, 就是直接从文本到 laura 模型,而不是需要去一点一点的老师和这种学生的训练。 他首先就说了一下,现在大模型的上下文窗口是有限的,然后要不然就是做这种外接的,比如说不做训练的就是做 red, 或者直接使用全量上下文,这种全量上下文就是最好的性能,是最好的一个存在,但是它的内存消耗是非常大的,而且它的上下文窗口是有限的。 第二个点就是 regreg, 就是 外接的一个知识库,然后内置的主要有 sft, sft 就 不说了,它就是直接训练进去了,然后就是上下文真流。上下文真流的方式是通过一个教师模型,比如说教师模型去看这个文档,然后使用这种查询 q, 然后收集 a, 然后把这种 q a 问答对, 再去训练这个学生模型,学生模型这个时候就不会再去看这些文档了,这样的话就相当于把这个文档的信息类化到了这个学生模型里面,这样这个学生模型就学习到了这个文档的一些知识,但是又不会突破他的上下文, 它推理的上下文的话是没有做改变的,但是它在训练的时候其实是消耗了巨大的这种资源损耗的。但是如果用它这个方式,相当于是把文档直接训练成一个 lora 的 小模型。但是它跟之前那种做 lora 训练还有点不同,之前的 lora 训练它其实是在你和这个 q a, 但是这个它不是在你和 q a, 它更像是把 q a 放进了模型,然后直接从模型里面的参数权重直接抽象出来 lora, 然后它用了一种超参数和这种分批的方式,它可以把这个训练可以一次性就搞定,只需要看一遍,直接把这个 laura 就 可以弄出来,不是像之前的可能需要多次的训练,嗯,多次的反向传播。而且它这个有一个特别好的好处,就是它可以直接突破它的上下文限制,它把 他把这些文档可以分快,分快了之后再给到这个模型。比如说之前的模型只有八 k, 你 的文档是超过八 k 的, 你可以把它拆分,拆分了之后再丢到大模型里面去,再去做推理,推理的时候他可以把这些参数弄来叠加,叠加到一个超网络里面, 他就可以去学习到这么多东西。但是他这个东西还是有限的,因为你的这个超网络他的参数是有限的,他们实验下来他们的这一个的话是能达到四到五倍,并且不会下降性能。 但是如果说你想要哦你的上下文再增加的话,可能是需要再增加它的这个超网络的参数。可以看到它如果原始模型它在这里的时候,到它它上下文之后,它性能就急剧下降了,然后这后面基本上就没有性能了,然后它是可以达到更高的倍数的,然后才会开始下降这个模型的性能, 然后是它内存的损耗,它的内存损耗是一样的,永远不会改变,它只会多出来它 laura 的 那个小模型的内存损耗。而原始的模型的话,它的内存损耗是呈指数增加的,这也是现在所有模型的一个通病,就是它上下文是呈指数增加的。 然后从结果来看,我们直接看他结果吧,其实他这个图我有点看不懂,他更新的延迟消耗的内存和性能几乎都是索塔的水平,比之前的那种 cd 的 方式他的性能都要好了很多,而且他训练的内存消耗都降低了非常多, 所以说这个解决方案还是非常不错的。如果说你的这种文档他不算特别多,没有超过这个模型上下文的四到五倍或者十倍以内都可以用。他们这个解决方案还有一个好处,他们这个解决方案就是他在推理的时候是不需要那么多长上下文的, 所以说你的这个设备他的性能,他的资源是有限的情况下,你又需要他的这种文档回复效果好,就可以使用他这个方案。他这个方案也是已经开源了的, 从结果上来讲它这个效果都非常好,而且消耗的资源都很少,它肯定比 reg 的 方式要更好,但是比其他的这种解决方案它消耗的资源都要更少得多。

嗯,你看你姐姐上写的 g m 这一块啊,那假如说,呃,有一个场景啊,就我 g m 对 吧?它系统啊频繁地进行了 for g c, 那 你会怎么处理?就可以调大对内存或者就是换机的垃圾回收器。 ok, 面试的时候呢,每个问题啊都要扩展一下,就是结构化的去表达, 那么这个问题你就可以从 for gc 导致的问题,对吧,它的原因,然后我再解决方案这三个步骤去回答。如果你担心简历上的东西讲不出来,我已经把面试经常问到的一些技术站场景题都整理在两百万字的面试文档了,里面针对每个知识点都有很详细的解析思路, 只要你是我的粉丝,留言六六六就可以打包带走。首先,为什么不能频繁的负二 g c? 因为负二 g c 它会触发 s t w, 也就是会暂停我们所有的应用进程。如果每隔几秒就来一次负二 g c, 那 么应用就会卡顿,导致接口响应变慢,吞吐量下降。更加严重的时候呢,如果内存没法回收,那么最终会导致内存泄露或者说系统崩溃。 那么是什么原因导致负二 g c 频繁发生呢?最常见原因主要有三个,第一个,老年 g c 过后,存活的对象就会进城,到老年代时, 如果老年带剩余的空间不够,就会触发频繁的 for g c, 用 for g c 去清空我们老年带里面的对象,这种情况通常呢与对象过早晋升和大对象过多有关系。然后第二呢,就是 meta space 不 足啊, meta space 用于存储类的元数据,如果应用动态地去生成大量的类,比如说通过自己内部频繁地去生成代理类,且没有设置 meta space 的 大小限制,那么就会引发 for g c。 第三个呢,就是内存泄露,比如说静态集合内持续的增长,或者说数据库连接文件流等资源没有及时的关闭,导致对象无法被及时回收,那么最终呢,会去承包我们的老年袋 啊,至于具体啊,是哪个原因,我们需要借助一些怎样的工具啊,来定位。那么几个工具啊,来,第一个就为 svm, 它可以监控我们的内存, cpu 和现成,还能分析我们的档位啊,快速的去查看哪些对象占用了大量的内存。 第二个 mate, 专门用来分析我们代码文件的,能够去直接的定位到内存泄露的可疑对象和隐秘,然后阿尔萨斯在线诊断工具,可以用 vm tour 命令,然后实时的去查看对象的隐秘关系。 ok, 找到原因以后呢?然后我们去呃解决也比较清晰了。那如果是老年代空间不足,那么可以从几个方向去调整 g m 的 参数, 比如说增大我们的对内存,调整新生代与老年代的比例,或者说增大我们的 survive, 去提高对象继承老年代的预值,让对象在新生代里面去多活几次, 避免过早的晋升。然后如果是 meta space 溢出,那么可以通过像 meta space size 啊,然后限制其大小,防止无限增长。如果是内存泄露,那么就需要从代码层面去修复了,那么怎么样去修复呢?第一个找问题对吧?我们可以通过 mate 分 析大姆日制,然后找出占用内存最大的对象,然后定位到具体的引链, 看看是哪个静态的集合,或者说没有关闭的资源导致了这个问题。那最后呢,就去修复袋嘛,比如说移出一些无效的引用,然后呢或者说用 uh maker has map 来去代替强引用等等,对吧?就是这是我们 three 的 local 里面的一个设计思想嘛, 总的来说呢,就是解决频繁负荷计算的思路啊,就是因为原因啊,可能是内存泄露过早的进深啊,以及内存空间不足,然后再针对性的调整啊,堆大小,对吧?回收器等等我们都可以去调整。

不会真以为所有软件都装到 d 盘, c 盘就能腾出一大堆空间吗?没发现你 c 盘在逐渐爆满吗?那是因为软件生成数据依然默认储存在 c 盘。想要解决很简单, 双击打开此电脑,在左侧找到文档,右击打开属性,就能看到它无形之中占用了多少内存,用久了只会越来越卡。点击上方位置,将文件路径前面 c 根改成 d, 它就会将磁盘的数据迁移到 d 盘,释放 c 盘大量的空间。学会了吗?关注我,学习更多电脑知识!

十七亿未必能换到一颗真心,但全部砸金装机,你就能堆出一台让所有硬件发烧友仰望一生的珠穆朗玛峰。开篇直接上天花版 g c p u 县城撕裂者九九九五生产力直接拉满到一出,搭配华硕叉九零旗舰主板,三十二箱供电镇压全场 显卡,不讲道理,六张 r t 叉 pro 六千直接满配排开,合计五百七十六 g b 超大显存,从此再也没人敢跟你提包。显存三个字, 散热直接上定制一凯分体水冷冷头,紧紧贴合 c p u 与服务器显卡。所谓的散热焦虑根本不存在。内存直接插满到极限,八根二百五十六 g b, 六千四百频率服务器内存 组成二特波八通道存储,先拉满四条三星九幺零零 pro 八特波固态,再加八块细节,二十特波企业级机械盘,组成一百九十二特波磁盘阵列,速度与容量双峰顶供电,由四颗台达两千七百瓦钛金电源把关, 彻底告别一切供电焦虑。这样的主机,我们直接造二十五台,整套集群总显存高达十四点四特步, 最后才是真正的排面内外双球木有,整整二十万块十二寸弧形 led 模组拼接而成,内屏三千八百四十赫兹刷新率,加上十六 k 无损分辨率,恭喜你亲手造了一个拉斯维加斯大圆球!

依旧是咱们的赛博开合环节,今天要看的是这台纯黑小主机,还先来开散热器,这个大块头是来自九州凤城的阿萨心四,如果按正常的开合顺序,咱们看完散热之后应该看主板,但因为机子的体积太小,整张主板只露出了右上角这一小块,但是问题不大,先跳过一下来看看内存,这款内存是来自阿斯加特雷神索尔,而雷神索尔这个型号目前只有 ddr 五版本 主板就能排除掉一大堆用第四的型号了。接下来将目光聚焦到这个非常难拔出的二十四 p 供电之下,能看见这块地方,并没有另一个也很难拔出的机箱前置 usb 三点零接口。那这么多的主板厂商,到底是谁这么爱搞特殊,把 usb 三零零和主板二十四 p 供电分开放的?答案就是咱们的爱国家。同时这个板子没有显卡快拆装置,只有机箱前置 type c 放在内存的右下角,所以能够进一步排除掉 b 八六零和 b 八五零这两个型号。 还有一个很重要的细节,就是这块板子有一个很小的按钮藏在二十四屏下面,虽然这个东西在 b 七六零上面也有搭载,但是不是装了两个,就是装在主板的右下角。到这一步也就剩下两张板子了,一张是 b 六五零 m r s 伊利特小雕,另一张是 b 六五零 r s a 叉电竞标。最后再稍微对比一下机主,这块板子在二十四 p 供电左侧有很多小雕都没有的原件,那最终的答案也很显而易见了,这张板子是来自 g 家的 b 六五零 m r s pro a 叉电竞雕到这一步,觉得牛逼的兄弟可以把公屏打在牛逼上,剩下来的就很好开了。显卡的外观一看就是 g 家的四零系魔音, 不是四零七零 super 就是 四零七零太 super, 这边就盲拆一个四零七零太 super 好 了。旁边这个电源则 t t 的 钢影 g f e 八百五十瓦。外面这个机箱也是出镜很多次的闪灵 g 三百。最后还是把所有的配置都写在屏幕上,不知道这次能对几个呢? ok, 以上就是本期视频的所有内容了,下次攒够一波素材再更新。

里面监控显示对内存还有很多空闲,为什么系统还在频繁的发生负极 c 导致浮卡顿呢?当你面对这样一个线上问题的时候,那种感觉啊,就像是汽车油表显示满格,发动机呢却不断的熄火一样,令人困惑和抓狂。这恰恰是 gvm 性能调优里面最经典最考验功力的场景 之一。今天我们就来深入 gvm 的 案发现场,去揪出那些在内存充足的情况下依然会频繁触发负极 c 的 隐形杀手。 首先我们必须要建立一个核心认知,负极 c 的 触发条件远远不止老年代空间不足这一种,它是一系列复杂条件判断的结果, 即使堆内存总体充足,但是在某些特定的场景或者错误的配置下,垃圾回收器会认为有必要进行一次全聚回。 一般有两类问题,如果你担心简历上的东西讲不出来,我已经把面试经常问到的一些技术站场景题都整理在两百万字的面试文档了,里面针对每个知识点都有很详细的解析思路,只要你是我的粉丝,留言六六六就可以打包带走。 第一类就是对象的分配行为异常,比如应用存在瞬时的超高吞吐量,疯狂的创建新对象,即使年轻代总的空间足够,但一等区可能在样机 c 以后依然存 火。比如一些临时的缓存或者绘画对象,并且幸存者 smart 区它的空间不足或者动态年龄判断,就会导致大量本应该在年轻代多历练几次的对象提前进入到老年代,而老年代呢,就被这些早熟的对象快速填满,从而触发了负极 c。 其次就是频繁的创建大数据库,大支付串,比如说处理文件啊,报表这些场景,这些大对象会绕过年轻代,直接在老年代分配,如果频率很高,就会迅速的消耗老年代空间。 第二类就是内存区配置与碎片化,比如即便内存区划分不合理,你像堆很大,比如说有十六个 g, 但是呢,年轻代设置的很小,比如说一个 g, 那 这类配置会让一等区很快填满,导致样机 c 异常频繁。 每一次样机 c 之后呢,都会有对象晋升,主要使得老年代增长速度加快,同时呢,频繁的样机 c 本身也会消耗 cpu, 影响存储量。 其次就是内存碎片导致的进行内存压缩, 长时间运行以后呢,老年带会产生大量的内存碎片,当触发了一样 g c 之后,有对象需要晋升到老年带,但是老年带总的剩余空间足够,却找不到一块连续的空间来去存放这个晋升对象,那这个时候基本就没有办法呀,只能去触发一次负二 g c 了。还有一种就是从 java 八开始呢,永久带被原空间取代,它使用了本地内存,如 夹子类过多,原空间会不断的膨胀,达到这样一个预值以后呢,就会触发负极 c。 以上呢,就是我对这个问题的理解和回答思路。我是迈克,关注我,每天收获一个,加我一盒干货。如果内容对你有帮助,请点赞收藏,我们下期再见!