内存是当今世界上被广泛浪费的硬件资源之一。由于编程效率低下,惊人量的内存被浪费了。这种模式在多个企业应用程序中重复出现。为了证明这种情况,我们进行了一项小型研究。我们分析了著名的spring boot pet诊所应用程序,以查看浪费了多少内存。该应用程序是由spring社区设计的,旨在显示spring应用程序框架如何用于构建简单但功能强大的面向数据库的应用程序。

源码地址:

https://github.com/spring-projects/spring-petclinic

1

环境准备

Spring Boot 2.1.4

Java SDK 1.8

Tomcat 8.5.20

MySQL 5.7.26

2

压力测试

我们使用了流行的开源负载测试工具Apache JMeter进行压力测试。

我们使用以下设置执行了30分钟的负载测试:

线程数(用户)– 1000(连接到目标的用户数)

加速周期(以秒为单位)–所有请求开始的时间范围。根据我们的配置,每0.01秒,将启动1个新线程,即100个线程/秒。

循环计数–这1000个线程背靠背执行测试迭代。

持续时间(秒)–加速后,1000个线程连续运行1800秒。

我们在负载测试中采用了以下方案:

将新的宠物主人添加到系统。

查看有关宠物主人的信息。

向系统添加新宠物。

查看有关宠物的信息。

将有关访问的信息添加到宠物的访问历史中。

更新有关宠物的信息。

更新有关宠物主人的信息。

通过搜索其姓名查看所有者信息。

查看所有所有者的信息。

3

如何测量内存浪费?

业界有数百种工具可以显示所使用的内存量。但是我们很少遇到能够测量由于编程效率低下而浪费的内存量的工具。HeapHero是一个简单的工具,可以分析堆转储并告诉您由于编程效率低而浪费了多少内存。

测试运行时,我们从Spring Boot Pet Clinic应用程序捕获了堆转储。

我们将捕获的堆转储上传到HeapHero工具中。工具生成了这个漂亮的报告,显示由于效率低下的编程浪费了65%的内存。是的,这是一个简单的原始应用程序,应该在其中实现所有最佳实践,在一个广为人知的框架上也浪费了65%的内存。

4

分析内存浪费

从报告中,您可以注意到以下内容:

字符串重复导致浪费了15.6%的内存

由于原始数组效率低下,浪费了14.6%的内存

由于重复的原始数组浪费了14.3%的内存

由于收集效率低下,浪费了12.1%的内存

字符串重复

在此Spring启动应用程序

(和大多数企业应用程序)

中浪费内存的主要原因是字符串重复。该报告显示了由于重复字符串而浪费了多少内存,它们是什么字符串,谁在创建它们以及如何对其进行优化。

您会注意到由于重复的字符串浪费了15.6%的内存。

请注意

'Goldi'字符串已被创建207,481次。

“Visit”字符串已创建132,308次。“访问”是我们在测试脚本中提到的描述。

“Banglore”字符串已创建75,374次。“ Banglore”是我们在测试脚本中指定的城市名称。

'123123123'已被创建37,687次。

“ Mahesh”字符串已创建37,687次。

显然,“Goldi”是通过测试脚本在屏幕上输入的宠物的名称。“访问”是通过测试脚本在屏幕上输入的描述。同样,是值。但是有一个问题,为什么要创建相同的字符串对象那么几千次。

我们都知道字符串是不可变的

(即一旦创建,就无法修改)

。鉴于为什么要创建成千上万个重复的字符串?

HeapHero工具还报告创建这些重复字符串的代码路径。

收款效率低下

在弹簧靴宠物诊所应用中造成内存浪费的另一个主要原因是收集效率低下。

以下是HeapHero报告的摘录:

您会注意到,内存中99%的LinkedHashSet中没有任何元素。如果没有元素,为什么还要创建LinkedHashSet?当您创建一个新的LinkedHashSet对象时,将在内存中保留16个元素的空间。现在为这16个元素保留的所有空间都被浪费了。如果对LinedHashset进行延迟初始化,则不会出现此问题。

不良做法:

private LinkedHashSetmyHashSet = new LinkedHashSet();

public void addData(String key, String value) {

myHashSet.put(key, value);

}

最佳实践:

private LinkedHashSetmyHashSet;

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);

5

内存不便宜

一个人可以反驳说,内存是如此便宜,那么为什么我要担心它呢?公平的问题。但是在云计算时代,我朋友的记忆并不便宜。有4种主要的计算资源:中央处理器、内存、网络、存储。

您的应用程序可能在AWS EC2实例上运行的数十万个应用程序服务器上运行。在上述4种计算资源中,哪个资源在EC2实例中已饱和?

对于大多数应用程序,它是内存。CPU始终为30 – 60%。总是有大量的存储空间。很难饱和网络

(除非您的应用程序正在流式传输大量视频内容)

。因此,对于大多数应用程序来说,首先是内存饱和。即使CPU,存储和网络未充分利用,仅由于内存变得饱和,您最终还是会配置越来越多的EC2实例。这将使您的计算成本增加几倍。

另一方面,由于编程效率低下,现代应用程序无一例外地浪费了30%-90%的内存。即使在没有太多业务逻辑的Spring Boot宠物诊所之上,也浪费了65%的内存。实际的企业应用程序将浪费相似的数量,甚至更多。因此,如果您可以编写内存有效的代码,那么它将降低您的计算成本。由于内存是第一个达到饱和的资源,因此,如果可以减少内存消耗,则可以在较少数量的服务器实例上运行应用程序。您也许可以减少30 – 40%的服务器。这意味着您的管理层可以减少30%-40%的数据中心

(或云托管提供商)

成本,再加上维护和支持成本。它可以节省数百万/数十亿元的成本。

6

结论

除了减少计算成本,编写内存效率高的代码后,您的客户体验也将变得更好。如果您可以减少为服务新的传入请求而创建的对象数量,则响应时间将大大缩短。由于创建的对象较少,因此在创建和垃圾回收对象上将花费较少的CPU周期。减少响应时间将提供更好的客户体验。

用Java写一个浪费cpu的程序_Java程序是如何浪费内存的相关推荐

  1. java写一个简单的浪漫代码_程序员的浪漫弹窗表白,圣诞节给Ta惊喜吧(附源码,简单易学哦)...

    不要以为程序员都是木讷的,浪漫起来也会让很多妹子心动的.而程序员的表白方式也很不一般,通过一堆代码,无限释放浪漫.今天教给大家通过改写脚本语言,利用弹窗可充分自由发挥,用来表白或者恶搞都是不错的选择. ...

  2. java写一个服务定时采集数据_java实现定时任务解决方案

    1. 总结常见的实现定时任务的几种方法 thread实现 [原理:通过创建一个线程,让他在while循环里面一直运行,用sleep() 方法让其休眠从而达到定时任务的效果.] Timer类 Sched ...

  3. java写一个会动的圆_JAVA实现一个圆形的移动,画出来的圆形移动,我的圆它不动呀...

    展开全部 import java.awt.Graphics; import java.awt.Image; import javax.swing.JFrame; public class JoinDe ...

  4. 怎样用java写一个简单的文件复制程序

    怎样用java写一个简单的文件复制程序 代码来源:https://jingyan.baidu.com/article/c35dbcb0d6f1398916fcbc07.html package Num ...

  5. 面试必问:用 Java 写一个内存泄漏程序

    编译:ImportNew/唐尤华 原文链接:stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java 问题: 刚参加的一 ...

  6. 用JAVA写一个画图小程序(JAVA 大作业)

    第一次写博客 且是稍微大点的程序 看看就行 重新写的在这,更加清晰明了:点击进入:用JAVA写一个画图小程序(JAVA 大作业)重排版本 设计思路 首先我直接去了Windows自带画图程序去实践模拟, ...

  7. java递归怎么写_什么是递归?用Java写一个简单的递归程序

    什么是递归?用Java写一个简单的递归程序 递归的定义 递归(recursion):以此类推是递归的基本思想,将规模大的问题转化为规模小的问题来解决. 递归的要素 自定义递归函数,并确定函数的基本功能 ...

  8. 还在动手画棋盘 ?20分钟带你用Java写一个井字棋!

    还在动手画棋盘 ?20分钟带你用Java写一个井字棋! 文章目录 还在动手画棋盘 ?20分钟带你用Java写一个井字棋! 前言 设计过程 1.创建窗体类MyGameWindow 2.创建窗体的构造器 ...

  9. java实现迷你计算机,用JAVA写一个迷你编辑器.doc

    用JAVA写一个迷你编辑器 用JAVA编写一个迷你编辑器 WINDOWS的记事本程序是非常方便的一个文字处理工具,用它来编辑纯文本文件快捷而灵巧.我用JAVA写了一个编辑器程序,模仿"记事本 ...

  10. 用Java写一个简易五子棋游戏

    一. 程序基本思路: 1.写窗口.棋盘面板.控制面板: 2.绘制棋盘: 3.绘制棋子: 4.添加组件功能: 5.判断输赢: 6.悔棋: 7.复盘. 二.实际操作 1.创建窗口.添加面板 package ...

最新文章

  1. pandas基于时序数据计算模型预测推理需要的统计数据(累计时间、长度变化、变化率、方差、均值、最大、最小等):范围内的统计量、变化率、获得数据集最后的几条数据的统计量、变化率、获得范围内的统计量
  2. Spring Security教程 Vol 9. AccessDecisionManager组件介绍
  3. etcd分布式之消息发布与订阅
  4. LVS负载均衡基础总结
  5. list agg cause ORA-06502 PL/SQL: numeric or value error
  6. Java数组及二维数组初始化与赋值方法总结
  7. 把偷快递的贼炸到怀疑人生!不愧是NASA工程师,奇思妙想
  8. linux的定制和发布(二)
  9. 内存管理, 对象的生命周期
  10. php+高德地图webapi 高德jsapi 实现 当前位置与目标位置距离 并按照距离排序(坐标逆转换)...
  11. linux execl 错误信息,Excel:自动隐藏错误结果的显示信息(转)
  12. asp.net mvc 伪静态添加
  13. Tomas Mikolov's Recurrent Neural Networks Language Modeling Toolkit
  14. Mac盖上屏幕后外接屏幕持续黑画面的解决方法
  15. C# 插件构架实战(Jack H Hansen )
  16. WinEdt 参考文献格式
  17. ARP表 MAC表 路由表
  18. arm服务器测评_ARM:异军突起
  19. 用GitHub Actions自动部署Hexo
  20. (三)JMockit API:@Mocked -基础篇

热门文章

  1. LGOJP2831 愤怒的小鸟
  2. 阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第3节 注解_12_注解_概念
  3. 修改PHP上传文件的大小限制(post)
  4. oracle之三 自动任务调度
  5. 【GStreamer开发】GStreamer基础教程05——集成GUI工具
  6. c++ 类的定义和使用
  7. GMap.Net开发之自定义Marker
  8. mysql(安装、启动、删除)服务
  9. 《修炼之道:.NET开发要点精讲》读书笔记(三)
  10. vue+django2.0.2-rest-framework 生鲜项目(五)