spring_Spring Boot应用程序浪费了内存
spring
内存是当今世界上广泛浪费的资源之一。 由于编程效率低下,浪费了令人惊讶的(有时是“震撼”的)内存。 我们看到这种模式在多个企业应用程序中重复出现。 为了证明这种情况,我们进行了一项小型研究。 我们分析了著名的spring boot pet诊所应用程序,以查看浪费了多少内存。 该应用程序是由社区设计的,目的是展示如何使用spring应用程序框架来构建简单但功能强大的面向数据库的应用程序。
环境
- Spring Boot 2.1.4。发布
- Java SDK 1.8
- Tomcat 8.5.20
- 带有MySQL Connector / J 8.0.15MySQL 5.7.26
压力测试
我们使用了流行的开源负载测试工具Apache JMeter进行压力测试。 我们使用以下设置执行了30分钟的负载测试:
- 线程数(用户)– 1000(连接到目标的用户数)
- 加速周期(以秒为单位)– 10.所有请求开始的时间范围。 根据我们的配置,每0.01秒,将启动1个新线程,即100个线程/秒。
- 循环计数–永远。 这1000个线程背对背执行测试迭代。
- 持续时间(秒)-1800。 加速后,1000个线程连续运行1800秒。
我们在负载测试中采用了以下方案:
- 将新的宠物主人添加到系统。
- 查看与宠物主人有关的信息。
- 将新宠物添加到系统。
- 查看有关宠物的信息。
- 将有关访问的信息添加到宠物的访问历史中。
- 更新有关宠物的信息。
- 更新有关宠物主人的信息。
- 通过搜索其姓名查看所有者信息。
- 查看所有所有者的信息。
如何测量内存浪费?
工业上有数百种工具可以显示所使用的内存量。 但是我们很少遇到能够测量由于编程效率低下而浪费的内存量的工具。 HeapHero是一个简单的工具,可以分析堆转储并告诉您由于编程效率低而浪费了多少内存。
测试运行时,我们从Spring Boot Pet Clinic应用程序捕获了堆转储。 (有7种不同的选项可从Java / Android应用程序捕获堆转储。您可以选择最方便的选项)。
我们将捕获的堆转储上传到HeapHero工具中。 工具生成了一个漂亮的报告,显示由于效率低下而浪费了65%的内存。 是的,这是一个简单的原始应用程序,应该在其中实现所有最佳实践,在一个广为人知的框架上也浪费了65%的内存。
分析内存浪费
从报告中,您可以注意到以下内容:
- 字符串重复导致浪费了15.6%的内存
- 由于原始数组效率低下,浪费了14.6%的内存
- 由于原始数组重复,浪费了14.3%的内存
- 由于收集效率低下,浪费了12.1%的内存
在此Spring引导应用程序(和大多数企业应用程序)中浪费内存的主要原因是字符串重复。 该报告显示了由于重复字符串而浪费了多少内存,它们是什么字符串,谁在创建它们以及如何对其进行优化。
您会注意到由于重复的字符串浪费了15.6%的内存。 请注意
- 'Goldi'字符串已被创建207,481次。
- “访问”字符串已创建132,308次。 “访问”是我们在测试脚本中提到的描述。
- “班加罗尔”字符串已创建75,374次。 “ Banglore”是我们在测试脚本中指定的城市名称。
- '123123123'已被创建37,687次。
- “ Mahesh”字符串已创建37,687次。
显然,“ Goldi”是通过测试脚本在屏幕上输入的宠物的名称。 “访问”是通过测试脚本在屏幕上输入的描述。 同样,是值。 但是,为什么要创建这些相同字符串对象的次数如此之多呢?
我们都知道字符串是不可变的(即一旦创建,就无法修改)。 鉴于为什么要创建成千上万个重复的字符串?
HeapHero工具还报告创建这些重复字符串的代码路径。
这是修复应用程序中重复字符串的高级建议。 您可以采用适用于您的应用程序的策略。
弹簧靴宠物诊所应用中内存浪费的另一个主要原因是收集效率低下。 以下是HeapHero报告的摘录:
您会注意到,内存中99%的LinkedHashSet中没有任何元素。 如果没有元素,为什么还要创建LinkedHashSet? 当您创建一个新的LinkedHashSet对象时,将在内存中保留16个元素的空间。 现在为这16个元素保留的所有空间都被浪费了。 如果您对LinedHashset进行了延迟初始化,则不会出现此问题。
不良做法:
private LinkedHashSet<String, String>myHashSet = new LinkedHashSet();public void addData(String key, String value) {myHashSet.put(key, value);}
最佳实践:
private LinkedHashSet<String, String>myHashSet;public void addData(String key, String value) { If (myHashSet == null ) {myHashSet = new LinkedHashSet();}myHashSet.put(key, value);}
同样,另一个观察结果是:68%的ArrayList中仅包含1个元素。 创建ArrayList对象时,将在内存中保留10个元素的空间。 这意味着在88%的ArrayList中9个元素的空间被浪费了。 如果可以使用容量初始化ArrayList,则可以避免此问题。
不良做法:默认情况下初始化集合。
new ArrayList();
最佳实践:使用容量初始化集合
new ArrayList( 1 );
内存不便宜
一个人可以反驳说,内存是如此便宜,那么为什么我要担心它呢? 公平的问题。 但是在云计算时代,我朋友的记忆并不便宜。 有4种主要的计算资源:
- 中央处理器
- 记忆
- 网络
- 存储
您的应用程序可能在AWS EC2实例上运行的数十万个应用程序服务器上运行。 在上述4种计算资源中,哪个资源在EC2实例中变得饱和? 我要求您在这里稍等一下,然后再继续阅读。 考虑一下,首先确定哪些资源已饱和。
对于大多数应用程序,它是*内存*。 CPU始终为30 – 60%。 总是有大量的存储空间。 网络很难饱和(除非您的应用程序正在流式传输大量视频内容)。 因此,对于大多数应用程序来说,首先要达到饱和的是内存。 即使CPU,存储和网络未充分利用,仅由于内存变得饱和,您最终还是会配置越来越多的EC2实例。 这将使您的计算成本增加几倍。
另一方面,由于效率低下的编程习惯,现代应用程序毫无例外地浪费了30%至90%的内存。 即使在没有太多业务逻辑的Spring Boot宠物诊所之上,也浪费了65%的内存。 实际的企业应用程序将浪费相似的数量,甚至更多。 因此,如果您可以编写内存有效的代码,那么它将降低您的计算成本。 由于内存是第一个达到饱和的资源,因此,如果您可以减少内存消耗,则可以在较少数量的服务器实例上运行应用程序。 您也许可以减少30 – 40%的服务器。 这意味着您的管理人员可以减少30-40%的数据中心(或云托管提供商)成本,再加上维护和支持成本。 它可以节省数百万/数十亿美元的成本。
结论
除了减少计算成本,编写内存效率高的代码后,您的客户体验也将变得更好。 如果您可以减少为服务新的传入请求而创建的对象数量,则响应时间将大大缩短。 由于创建的对象较少,因此在创建和垃圾回收对象上将花费较少的CPU周期。 减少响应时间将提供更好的客户体验。
翻译自: https://www.javacodegeeks.com/2019/11/memory-wasted-by-spring-boot-application.html
spring
spring_Spring Boot应用程序浪费了内存相关推荐
- Spring Boot应用程序浪费了内存
内存是当今世界上被广泛浪费的资源之一. 由于编程效率低下,令人吃惊的(有时是"令人震惊的")内存浪费被浪费了. 我们看到这种模式在多个企业应用程序中重复出现. 为了证明这种情况,我 ...
- spring_Spring Boot登录选项快速指南
spring "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...
- Spring Boot之程序性能监控
转载自 Spring Boot之程序性能监控 Spring Boot特别适合团队构建各种可快速迭代的微服务,同时为了减少程序本身监控系统的开发量,Spring Boot提供了actuator模块,可以 ...
- Java应用程序中的内存泄漏和内存管理
Java平台最突出的功能之一是其自动内存管理. 许多人错误地将此功能转换为Java中没有内存泄漏 . 但是,事实并非如此,我给人的印象是,现代Java框架和基于Java的平台,尤其是Android平台 ...
- springboot actuator_Spring Boot之程序性能监控
今天跟大家分享Spring Boot之程序性能监控的知识. 1 Spring Boot之程序性能监控 Spring Boot特别适合团队构建各种可快速迭代的微服务,同时为了减少程序本身监控系统的开发量 ...
- java程序占用实际内存大小
一.java程序占用实际内存大小 1.1.java命令启动参数-Xms -Xmx的问题 启动命令如下:java -server -Xms128m -Xmx128m -jar ****. ...
- 谁说.NET没有GC调优,只改一行代码就让程序不再占用内存
经常看到有群友调侃"为什么搞Java的总在学习JVM调优?那是因为Java烂!我们.NET就不需要搞这些!"真的是这样吗?今天我就用一个案例来分析一下. 昨天,一位学生问了我一个问 ...
- java应用程序占用高内存_对Java应用程序中的内存问题进行故障排除
java应用程序占用高内存 重要要点 解决内存问题可能很棘手,但是正确的方法和正确的工具集可以大大简化此过程. Java HotSpot JVM可以报告几种OutOfMemoryError消息,因此务 ...
- 微信小程序超级占内存_6款宝藏微信小程序,简单又实用,节约内存就靠它了...
目前手机对生活的影响越来越重要,各种APP在生活中扮演着极其重要的角色.但是随着APP功能的增多,所占内存也是越来越大,很多手机都在超负荷运行,这样对手机的使用寿命会大大折损.最开始了解微信小程序是里 ...
最新文章
- c语言宏嵌套和展开规则
- Winform开发框架的业务对象统一调用方式
- JDBC为什么要使用PreparedStatement而不是Statement
- 阿里云终端连接与实例管理
- php mysql查询例子_php mysqli多个查询的例子
- hihocoder 1043 完全背包
- junit单元测试步骤
- 分享可用的谷歌学术(google scholar) hosts
- Linux程序设计(Linux shell编程五)
- 2019-4给学员试讲内容分享
- 天下武功唯快不破--速度要快
- 计算机网口速率修改,win7系统修改无线网卡连接速率的操作方法
- windows防火墙是干什么的_我可以用windows防火墙做什么
- MetaAI的融合怪:BlenderBot
- Java读取Excel,03版本和07版本
- nas文件服务器访问限制,nas文件服务器远程访问
- 【Earth Engine】基于GEE对季节性地物进行分类(多源数据叠图+监督分类)
- Redis地理算法GEO解析和应用
- sharding jdbc 的雪花算法中的属性worker.id和max.vibration.offset
- 安装 Windows XP 时出现错误信息“STOP:c0000218 {Registry File Failure}”(STOP: c0000218 {注册表文件失败})
热门文章
- Groovy初体验:构建高性能JVM应用
- 强生进军医疗机器人、Deepmind利用深度学习算法检查乳腺癌X光,AI医疗的风口已到来?...
- 如何理解高光谱图像数据
- nfs服务端服务停掉,导致的客户端访问挂载目录卡死的情况
- 线程介绍,异步,对象锁
- win8中离线安装net framework 3.5
- [杭电ACM]3336Count the string
- DIV与SPAN之间有什么区别
- 继续- 管理百人研发团队的烦恼(下)
- linux qemu 报错 Unable to reserve 0xfffff000 bytes of virtual address space at 0x1000 解决方法