记一次Memory Leak分析

 起因:最近公司的一个web产品遇到了内存溢出,于是开始着手调查。

调查:首先当务之急是找到那个或那些API导致Memory Leak,这个应该不难,根据监控分析,在内存上升时间段内有哪些API被访问,再就是根据开发人员提供信息,评估可能内存溢出的API。

案例分析:划定API范围后,用压力测试来重现问题,进一步定位具体是哪个方法,哪个技术点出问题,这些应该也不难,难的是知道什么地方有问题,但不知道怎么解决。

下面是经过精简后,分离出的有问题的代码。

项目文件csproj:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net6.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><ServerGarbageCollection>false</ServerGarbageCollection><ConcurrentGarbageCollection>true</ConcurrentGarbageCollection></PropertyGroup><ItemGroup><PackageReference Include="ClosedXML" Version="0.96.0" /><PackageReference Include="QRCoder" Version="1.4.2" /></ItemGroup>
</Project>

具体代码program.cs:

using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using QRCoder;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using Color = System.Drawing.Color;Console.WriteLine("回车开始");
Console.ReadLine();
var qrGenerator = new QRCodeGenerator();
while (true)
{using var workBook = new XLWorkbook();var ws = workBook.Worksheets.Add("TestSheet");for (var i = 1; i < 200; i++){using var qrCodeData = qrGenerator.CreateQrCode($"{i}_{DateTime.Now.ToString("yyMMddHHmmssfffffff")}_01PAe8np5m7pVULUiuxwwZTWQ9KZ8JUgQyWiyUrsiHqi4FKrCzhRAcddCkkJKDgVEkpmqD7kYJz5GTpe4oHvJdJDnNMMCTwbV19G", QRCodeGenerator.ECCLevel.L);using var qrCode = new QRCode(qrCodeData);using var qrCodeImage = qrCode.GetGraphic(20, Color.Black, Color.White, false);using var imgStream = new MemoryStream();qrCodeImage.Save(imgStream, ImageFormat.Png);using var image = ws.AddPicture(imgStream).MoveTo(ws.Cell(i, 1), new Point(50, 10));image.Width = 60;image.Height = 60;}workBook.SaveAs(@$"/app/images/{i}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx");Console.WriteLine($"完了:{DateTime.Now}");Console.ReadLine();
}

很有趣的是,这块代码在docker里运行时会有memory leak,但在windows上是没有问题的。

上面代码主要有两个功能,生成二维码,然后保存在Excel里,最后保存本地。具体表现是,每生成一个Excel,内存就会增加,不释放,直到容器重启。

其实找性能问题是一个排查的过程,首先要一点一点把认为有问题的代码修正,再次进行测试,看是否有改善,比如主动去释放一些对象,使用using,或者直接用GC.Collect()来测试。经过一轮后发现没有改善内存只涨不降的现象。于是就进行功能分享,把QR生成换成静态图片,查看Excel生成部分是否有问题,这样很快就定位到了QR生成有问题,但QR生成能有什么问题呢?并且这个功能一直在用,从.net 5用到.net 6,都没有变更过这里的代码。那只能查看是QR生成有无问题了。

下面是经过一番查找后的结果,果然ORCode类对.net 6.0不能很好的支持,只能换掉它了,替代的方式是用PngByteQRCode。

https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#2-overview-of-the-different-renderers

f49be545e7b92960a87128242d26953e.png

修改后的代码是:

using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using QRCoder;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using Color = System.Drawing.Color;Console.WriteLine("回车开始");
Console.ReadLine();
var qrGenerator = new QRCodeGenerator();
while (true)
{using var workBook = new XLWorkbook();var ws = workBook.Worksheets.Add("TestSheet");for (var i = 1; i < 200; i++){      byte[] qrCodeAsBitmapByteArr = PngByteQRCodeHelper.GetQRCode(DateTime.Now.ToString("yyMMddHHmmssfffffff") + "01PAe8np5m7pVULUiuxwwZTWQ9KZ8JUgQyWiyUrsiHqi4FKrCzhRAcddCkkJKDgVEkpmqD7kYJz5GTpe4oHvJdJDnNMMCTwbV19G", QRCodeGenerator.ECCLevel.Q, 20, false);var imgStream = new MemoryStream(qrCodeAsBitmapByteArr);imgStream.Seek(0, SeekOrigin.Begin);using var image = ws.AddPicture(imgStream).MoveTo(ws.Cell(i, 1), new Point(50, 10));image.Width = 60;image.Height = 60;}workBook.SaveAs(@$"C:\Users\axzxs\Pictures\{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx");Console.WriteLine($"完了:{DateTime.Now}");Console.ReadLine();
}

其实单看上面过程,很简单,其实测试过程中的一些指标表象,以及个人对技术点的认知,都会让性能分析起来要走一些弯路。比如上面功能,其实我们花了很多时间在Excel的生成找问题,甚至换了Excel生成组件来进行测试,经过多轮出修改方案,修改代码,压力测试,结果分析,才最终定义QR码,又经过多轮对QR码生成的方案优化,最后才找到是因为QR不支持导致的结果。

性能分析就是找疑难杂症,是个痛苦过程,同时,解决掉,又是一个很喜悦的收获。

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

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

相关文章

WebSocket教程

一、为什么需要 WebSocket&#xff1f; 初次接触 WebSocket 的人&#xff0c;都会问同样的问题&#xff1a;我们已经有了 HTTP 协议&#xff0c;为什么还需要另一个协议&#xff1f;它能带来什么好处&#xff1f; 答案很简单&#xff0c;因为 HTTP 协议有一个缺陷&#xff1a…

C# WPF十个美观的界面设计展示

概述很多时候&#xff0c;我们设计的界面总是感觉缺乏美感&#xff0c;不是我们不会开发好看的界面&#xff0c;而是不知道怎么才算美观&#xff0c;这时候我们不妨看看别人好的页面是怎么做的.下面展示一些我觉得做的比较好的cs界面&#xff0c;希望能给大家在平时做界面设计时…

MySQL5.6二进制软件包编译安装详解(三)

一、软件环境 [rootlocalhost ~]# uname -r 3.10.0-862.el7.x86_64 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) 二、安装部署过程详解 MySQL安装3种方式&#xff1a;1>rpm包安装应用文件默认安装在/usr/local 目录下2>源码编译需…

使用autok3s 安装k3s 集群 和 kuboard 管理集群

一、k3s介绍1.1 什么是k3s?k3s 是经过 CNCF 认证的由 Rancher 公司开发维护的一个轻量级的 Kubernetes 发行版&#xff0c;内核机制还是和 k8s 一样&#xff0c;但是剔除了很多外部依赖以及 K8s 的 alpha、beta 特性&#xff0c;同时改变了部署方式和运行方式&#xff0c;目的…

社区纠纷不断:程序员何苦为难程序员

出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013)今年年初&#xff0c;我们报道“因为被多人侮辱大吼&#xff0c;Swift 之父正式退出 Swift 核心团队”。诸如此类的“语言暴力”、“网络暴力”事件在开源社区乃至整个 IT 社区屡见不鲜。多个技术社区&#xff0c;都出…

PHP 分布式集群中session共享问题以及session有效期的设置

一、Session的原理 以下以默认情况举例&#xff1a; session_start();之后&#xff0c;会生成一个唯一的session_id&#xff0c;每一个用户对应唯一一个session_id&#xff0c;每一个session_id对应服务器端的一个session文件。这个session文件存储着当前session_id的信息&am…

[SDOI2009]Bill的挑战——全网唯一 一篇容斥题解

全网唯一一篇容斥题解 Description Solution 看到这个题&#xff0c;大部分人想的是状压dp 但是我是个蒟蒻没想到&#xff0c;就用容斥切掉了。 并且复杂度比一般状压低&#xff0c; &#xff08;其实这个容斥的算法&#xff0c;提出来源于ywy_c_asm&#xff09; &#xff08;然…

对象存储OSS服务

一、oss是什么 阿里云对象存储服务&#xff08;Object Storage Service&#xff0c;简称OSS&#xff09;为您提供基于网络的数据存取服务。使用OSS&#xff0c;您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种非结构化数据文件。 阿里云OSS将数据文件以…

《Access 2007开发指南(修订版)》一一1.5 什么是数据库对象

本节书摘来自异步社区出版社《Access 2007开发指南(修订版)》一书中的第1章&#xff0c;第1.5节&#xff0c;作者&#xff1a; 【美】Alison Balter&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.5 什么是数据库对象 Access 2007开发指南(修订版)正如前…

ETL工具kettle的组件--生成记录

今天介绍下kettle的一个比较实用的组件——生成记录&#xff1b;当我们想将一部分文本数据变成数据行&#xff0c;每个字段作为一个数据行的一个列&#xff0c;那么我们可以利用这个组件&#xff1b;它的位置在双击点开根据自己的实际需要进行设置当设置后&#xff0c;可以点击…

Linux学习笔记一

linux  kernel lib module shell tools ls -la&#xff1a; 显示所有文件包括隐藏文件  cat /proc/cpuinfo&#xff1a; 显示cpu信息 man man  /string&#xff1a; 向上搜索string字符串 继续按下小写n向上搜索  ?string&#xff1a; 向下搜索string字符串 继续按下大…

PHP中路由和rewrite的使用

一、场景介绍&#xff1a; 1、简化url地址&#xff0c;方便大家记忆 2、有利于搜索引擎优化 3、安全&#xff08;让用户看不出网站的目录结构&#xff09; 举例&#xff1a;比如我这里将main控制器中的bb方法路由到kk&#xff0c;这样&#xff0c;我们a标签请求跳转到cp.xi…

《NoSQL权威指南》导读

引言 NoSQL权威指南“没有什么会比引入新秩序更难&#xff0c;因为创新者必须要面对那些在旧环境中已经做得很好的对手&#xff0c;以及那些在新环境中做得很好的冷漠者。” ——Niccolo Machiavelli [1] 在过去的几十年&#xff0c;我已经通过Elsevier/Morgan Kaufmann出版社出…

PHP开发常见功能实现流程

一、pc端网站登录 1、获取并过滤用户提交的用户名和密码以及验证码 2、验证用户提交验证码和session中的验证码是否一致 3、验证用户名是否存在 4、根据用户名获取密码&#xff0c;并校验密码是否一致 5、密码一致&#xff0c;则登录成功&#xff0c;跳转到对应的首页 图示…

七牛直播云服务技术揭秘

以下根据七牛云首席布道师何李石现场演讲内容整理。 直播模型及其实现 一个通用的直播模型一般包括三个模块&#xff1a;主播方、服务器端和播放端。 首先是主播方&#xff0c;它是产生视频流的源头&#xff0c;由一系列流程组成&#xff1a; 第一&#xff0c;通过一定的设备来…

golang 标准库间依赖的可视化展示

简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内容,网上也要讨论,但是没有发现直接能拿过来用的.标准库之间,是必然存在依赖关系的,不同库被依赖的程…

《HTML5 2D游戏编程核心技术》——第1章,第1.3节特别功能

本节书摘来自华章出版社《HTML5 2D游戏编程核心技术》一书中的第1章&#xff0c;第1.3节特别功能&#xff0c;作者&#xff3b;美&#xff3d; 戴维吉尔里&#xff0c;更多章节内容可以访问云栖社区“华章计算机”公众号查看。 1.3 特别功能 Snail Bait游戏有3个特别的功能&a…

XunSearch的安装和加入服务器开机脚本以及将目录写入系统变量

一、安装xunserach 1、cd ~ 2、wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2 #下载最新xunsearch包 3、tar -xjf xunsearch-full-latest.tar.bz2 #解压xunsearch包 4、cd xunsearch-full-1.4.11/ #进入xunsearch包目录 5、sh setup.sh #执…

dubbo源码解析-zookeeper创建节点

前言 在之前dubbo源码解析-本地暴露中的前言部分提到了两道高频的面试题,其中一道dubbo中zookeeper做注册中心,如果注册中心集群都挂掉,那发布者和订阅者还能通信吗?在上周的dubbo源码解析-zookeeper连接中已经讲到,这周解析的是另一道,即服务提供者能实现失效踢出是根据什么原…

配置mysql为主主复制步骤

mysql版本&#xff1a;mysql-5.6.24-solaris10-sparc-64bit.tar 操作系统&#xff1a;solaris 11g u10 操作用户&#xff1a;使用非root进行操作安装&#xff0c;a路服务器ip地址为192.168.1.1 b路ip地址为192.168.1.2&#xff08;应改为实际ip地址&#xff09; 1&#xff0c;安…