简述垃圾对象产生_使用零垃圾创建数百万个对象

简述垃圾对象产生

如性能优化第一规则中所述,垃圾是快速代码的敌人。 通过使用垃圾收集器的服务,它不仅会破坏任何确定性的性能,而且我们开始用垃圾填充CPU高速缓存,这将导致程序的高速缓存未命中。

那么,我们可以在不创建垃圾的情况下使用Java吗? 例如,在自然Java中是否可以解决此问题:

创建10m个金融工具对象,将它们存储在地图中,检索它们并使用每个对象执行计算,而完全不会产生任何垃圾。

如果您使用Chronicle ! Chronicle提供了库,因此您可以轻松地以对象的内存映射文件形式使用堆外存储。 (有关本文的完整源代码,请参见此处 。)

让我们看一下实现上述问题的解决方案。

首先,让我们看一下如何在普通Java中执行此操作,以确保我们理解问题以及如果使用标准Java库进行实现会发生什么情况。

package zeroalloc;import org.junit.Assert;
import org.junit.Test;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** Class to demonstrate zero garbage creation.* Run with -verbose:gc -Xmx4G*/
public class CreateOnHeapTest {private static final int ITERATIONS = 10_000_000;@Testpublic void testOnHeapMap() {System.out.println("----- HASHMAP ------------------------");Map<Integer, BondVOImpl> map = new ConcurrentHashMap<>(ITERATIONS);long actualQuantity = 0;long expectedQuantity = 0;long time = System.currentTimeMillis();System.out.println("*** Entering critical section ***");for (int i = 0; i < ITERATIONS; i++) {BondVOImpl bondVo = new BondVOImpl();bondVo.setQuantity(i);map.put(Integer.valueOf(i), bondVo);expectedQuantity += i;}long putTime = System.currentTimeMillis() - time;time = System.currentTimeMillis();System.out.println("************* STARTING GET *********************");for (int i = 0; i < map.size(); i++) {actualQuantity += map.get(i).getQuantity();}System.out.println("*** Exiting critical section ***");System.out.println("Time for putting " + putTime);System.out.println("Time for getting " + (System.currentTimeMillis() - time));Assert.assertEquals(expectedQuantity, actualQuantity);printMemUsage();}public static void printMemUsage() {System.gc();System.gc();System.out.println("Memory(heap) used " + humanReadableByteCount(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(), true));}public static String humanReadableByteCount(long bytes, boolean si) {int unit = si ? 1000 : 1024;if (bytes < unit) return bytes + " B";int exp = (int) (Math.log(bytes) / Math.log(unit));String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);}
}

这是程序的输出:

*** Entering critical section ***
[GC (Allocation Failure)  98816K->92120K(125952K), 0.0317021 secs]
[Full GC (Ergonomics)  92120K->91917K(216576K), 0.2510530 secs]
[GC (Allocation Failure)  125197K->125430K(224256K), 0.0449051 secs]
[GC (Allocation Failure)  166390K->166686K(244224K), 0.0504341 secs]
[Full GC (Ergonomics)  166686K->165777K(387072K), 0.6243385 secs]
[GC (Allocation Failure)  226705K->226513K(388096K), 0.0785121 secs]
[GC (Allocation Failure)  293073K->293497K(392704K), 0.0825828 secs]
[Full GC (Ergonomics)  293497K->292649K(591872K), 1.2479519 secs]
[GC (Allocation Failure)  359209K->359433K(689664K), 0.0666344 secs]
[GC (Allocation Failure)  449033K->449417K(695296K), 0.1759746 secs]
[GC (Allocation Failure)  539017K->539385K(747008K), 0.1907760 secs]
[GC (Allocation Failure)  632569K->633009K(786944K), 0.2293778 secs]
[Full GC (Ergonomics)  633009K->631584K(1085952K), 2.1328028 secs]
[GC (Allocation Failure)  724768K->723368K(1146368K), 0.3092297 secs]
[GC (Allocation Failure)  827816K->825088K(1174016K), 0.3156138 secs]
[GC (Allocation Failure)  929536K->929952K(1207296K), 0.3891754 secs]
[GC (Allocation Failure)  1008800K->1009560K(1273856K), 0.4149915 secs]
[Full GC (Ergonomics)  1009560K->1007636K(1650688K), 3.4521240 secs]
[GC (Allocation Failure)  1086484K->1087425K(1671680K), 0.3884906 secs]
[GC (Allocation Failure)  1195969K->1196129K(1694208K), 0.2905121 secs]
[GC (Allocation Failure)  1304673K->1305257K(1739776K), 0.4291658 secs]
[GC (Allocation Failure)  1432745K->1433137K(1766912K), 0.4470582 secs]
[GC (Allocation Failure)  1560625K->1561697K(1832960K), 0.6003558 secs]
[Full GC (Ergonomics)  1561697K->1558537K(2343936K), 4.9359721 secs]
[GC (Allocation Failure)  1728009K->1730019K(2343936K), 0.7616385 secs]
[GC (Allocation Failure)  1899491K->1901139K(2413056K), 0.5187234 secs]
[Full GC (Ergonomics)  1901139K->1897477K(3119616K), 5.7177263 secs]
[GC (Allocation Failure)  2113029K->2114505K(3119616K), 0.6768888 secs]
[GC (Allocation Failure)  2330057K->2331441K(3171840K), 0.4812436 secs]
[Full GC (Ergonomics)  2331441K->2328578K(3530240K), 6.3054896 secs]
[GC (Allocation Failure)  2600962K->2488834K(3528704K), 0.1580837 secs]
*** Exiting critical section ***
Time for putting 32088
Time for getting 454
[GC (System.gc())  2537859K->2488834K(3547136K), 0.1599314 secs]
[Full GC (System.gc())  2488834K->2488485K(3547136K), 6.2759293 secs]
[GC (System.gc())  2488485K->2488485K(3559936K), 0.0060901 secs]
[Full GC (System.gc())  2488485K->2488485K(3559936K), 6.0975322 secs]
Memory(heap) used 2.6 GB

跳出此问题的两个要点是:一是垃圾回收的数量和开销(显然可以调整),二是使用了2.6GB的堆数量。 简而言之,无法摆脱它,该程序会产生大量垃圾。

我们这次使用ChronicleMap尝试完全相同的操作。

这是解决问题的代码:

package zeroalloc;import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import net.openhft.lang.values.IntValue;
import org.junit.Assert;
import org.junit.Test;import java.io.File;
import java.io.IOException;/*** Class to demonstrate zero garbage creation.* Run with -verbose:gc* To run in JFR use these options for best results* -XX:+UnlockCommercialFeatures -XX:+FlightRecorder*/
public class CreateChronicleTest {private static final int ITERATIONS = 10_000_000;@Testpublic void demoChronicleMap() throws IOException, InterruptedException {System.out.println("----- CHRONICLE MAP ------------------------");File file = new File("/tmp/chronicle-map-" + System.nanoTime() + ".map");file.deleteOnExit();ChronicleMapBuilder<IntValue, BondVOInterface> builder =ChronicleMapBuilder.of(IntValue.class, BondVOInterface.class).entries(ITERATIONS);try (ChronicleMap<IntValue, BondVOInterface> map =builder.createPersistedTo(file)) {final BondVOInterface value = map.newValueInstance();final IntValue key = map.newKeyInstance();long actualQuantity = 0;long expectedQuantity = 0;long time = System.currentTimeMillis();System.out.println("*** Entering critical section ***");for (int i = 0; i < ITERATIONS; i++) {value.setQuantity(i);key.setValue(i);map.put(key, value);expectedQuantity += i;}long putTime = (System.currentTimeMillis()-time);time = System.currentTimeMillis();for (int i = 0; i < ITERATIONS; i++) {key.setValue(i);actualQuantity += map.getUsing(key, value).getQuantity();}System.out.println("*** Exiting critical section ***");System.out.println("Time for putting " + putTime);System.out.println("Time for getting " + (System.currentTimeMillis()-time));Assert.assertEquals(expectedQuantity, actualQuantity);printMemUsage();} finally {file.delete();}}public static void printMemUsage(){System.gc();System.gc();System.out.println("Memory(heap) used " + humanReadableByteCount(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(), true));}public static String humanReadableByteCount(long bytes, boolean si) {int unit = si ? 1000 : 1024;if (bytes < unit) return bytes + " B";int exp = (int) (Math.log(bytes) / Math.log(unit));String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);}
}

这是程序的输出:

[GC (Allocation Failure)  33280K->6595K(125952K), 0.0072065 secs]
[GC (Allocation Failure)  39875K->12177K(125952K), 0.0106678 secs]
[GC (Allocation Failure)  45457K->15289K(125952K), 0.0068434 secs]
[GC (Allocation Failure)  48569K->18357K(159232K), 0.0098287 secs]
[GC (Allocation Failure)  84917K->21008K(159232K), 0.0156393 secs]
*** Entering critical section ***
*** Exiting critical section ***
Time for putting 8554
Time for getting 4351
[GC (System.gc())  36921K->21516K(230400K), 0.0331916 secs]
[Full GC (System.gc())  21516K->15209K(230400K), 0.0630483 secs]
[GC (System.gc())  15209K->15209K(230912K), 0.0006491 secs]
[Full GC (System.gc())  15209K->15209K(230912K), 0.0234045 secs]
Memory(heap) used 18.2 MB

显然,这里的要点是,关键部分没有 GC,整个程序仅使用18MB的堆。 我们已经设法创建了一个程序,该程序通常会产生千兆字节的垃圾,而根本不会产生任何垃圾。

关于时间的注意事项

ChronicleMap显然不是ConcurrentHashMap的替代品,它们的用法有很大不同,并且超出该讨论范围的内容不在本文的讨论范围之内。 但是功能上的主要区别是ChronicleMap是持久的,并且可以在许多JVM之间共享。 (ChronicleMap也具有可以复制tcp的功能。)尽管如此,快速地比较时间安排还是很有趣的,除非要确保我们在同一个球场。 ChronicleMap的投放速度更快,从32秒提高到8.5秒。 但是ConcurrentHashMap中的大部分时间都花在GC上,并且可能会在某种程度上进行调整。 ConcurrentHashMap的获取速度比4.3s快了0.5s。 不过,在其他运行中,由于该部分中发生了GC,因此我看到ConcurrentHashMap占用了7s。 即使ChronicleMap所做的工作要多得多,但实际上由于缺少垃圾而使计时与ConcurrentHashMap相当。

重新启动程序

ChronicleMap真正发挥作用的地方是重新启动。 假设您的程序崩溃了,您需要重新计算与之前相同的计算。 在ConcurrentHashMap的情况下,我们必须完全按照之前的方法重新填充地图。 使用ChronicleMap,由于地图是持久的,因此只需将地图指向现有文件,然后重新运行计算以产生totalQuantity。

摘要

并发哈希图 编年史
gc暂停 许多 没有
更新时间 32秒 8秒
读取允许gc 7秒 4秒
不读gc 0.5秒 4秒
堆大小 2.6GB 18MB
坚持不懈 没有
快速重启 没有

翻译自: https://www.javacodegeeks.com/2015/03/creating-millions-of-objects-with-zero-garbage.html

简述垃圾对象产生

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

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

相关文章

光学模拟 Android,基于Android平台的光学字符识别应用的设计与实现

摘要&#xff1a;随着数字化时代的蓬勃发展,信息量以指数级的速度增长,然而手工录入并存储信息的速度远不及信息的产生速度.光学字符识别(OCR)技术能够自动化地检测信息并识别出来,有效地解决了信息录入速度和正确率的问题.目前,基于PC设备的光学字符识别已经被广泛的应用于办公…

C语言“fread”函数的用法?

C语言“fread”函数的用法为“size_tf read(void *buffer,size_t size,size_t count,FILE *stream)”&#xff0c;其作用是从一个文件流中读数据&#xff0c;读取count个元素&#xff0c;每个元素size字节。示例1#include #include #include int main(){ FILE *stream; c…

html怎么设置数据条的颜色,jQuery EasyUI 数据网格 – 条件设置行背景颜色 | 菜鸟教程...

jQuery EasyUI 数据网格 - 条件设置行背景颜色本教程将向您展示如何根据一些条件改变数据网格(datagrid)组件的行样式。当 listprice 值大于 50 时&#xff0c;我们将为该行设置不同的颜色。数据网格(datagrid)的 rowStyler 函数的设计目的是允许您自定义行样式。以下代码展示如…

C语言中for语句的执行过程是什么?

C语言中for语句的执行过程是&#xff1a;for语句的一般形式为&#xff1a;for&#xff08;单次表达式;条件表达式;末尾循环体&#xff09;{中间循环体&#xff1b;}。for循环执行时&#xff0c;会先判断条件表达式是否成立&#xff0c;如果条件成立则执行中间循环体&#xff0c…

解耦,未解耦的区别_幂等与时间解耦之旅

解耦,未解耦的区别HTTP中的幂等性意味着相同的请求可以执行多次&#xff0c;效果与仅执行一次一样。 如果用新资源替换某个资源的当前状态&#xff0c;则无论您执行多少次&#xff0c;最终状态都将与您仅执行一次相同。 举一个更具体的例子&#xff1a;删除用户是幂等的&#x…

c语言getch()的用法是什么?

C语言中getch()函数功 能&#xff1a; 从stdio流中读字符&#xff0c;即从控制台读取一个字符&#xff0c;但不显示在屏幕上用 法:int getchar(void);这个函数是一个不回显函数&#xff0c;当用户按下某个字符时&#xff0c;函数自动读取&#xff0c;无需按回车&#xff0c;有的…

rx.observable_在Spring MVC流中使用rx-java Observable

rx.observableSpring MVC现在已经支持异步请求处理流程了一段时间&#xff0c;该支持内部利用了Tomcat / Jetty等容器的Servlet 3异步支持。 Spring Web Async支持 考虑一下需要花一点时间处理的服务呼叫&#xff0c;该服务呼叫具有延迟&#xff1a; public CompletableFutur…

淮安中专学计算机哪个学校好,2021淮安初中十强排名 哪些初中比较好

对于淮安的学生来说&#xff0c;了解淮安初中排名会更有利于选择初中。那么&#xff0c;2021淮安初中十强有哪些学校呢?下面小编整理了一些相关信息&#xff0c;供大家参考!2021淮安十大初中排名1、淮安兴隆中学2、淮安郑梁梅中学华禹分校3、淮安高堰九年制学校4、淮安长江路中…

C 隐式类型转换是什么?

C 隐式类类型转换《C Primer》中提到&#xff1a;“可以用 单个形参来调用 的构造函数定义了从 形参类型 到 该类类型 的一个隐式转换。”这里应该注意的是&#xff0c; “可以用单个形参进行调用” 并不是指构造函数只能有一个形参&#xff0c;而是它可以有多个形参&#xff0…

maven 插件未找到_防止在多模块Maven中找到“未找到插件”

maven 插件未找到在多模块Maven项目的子模块上定义Maven插件会给我们一个“未找到插件”错误。 特别是如果我们有一个多模块项目&#xff0c;并且只想在一个特定模块中应用Maven插件&#xff0c;则此错误会经常发生。 假设我们有一个看起来像这样的多模块root pom。 <proj…

文科女生单招学计算机,文科女生走单招学什么专业好

对于文科女生来说&#xff0c;想要走高职单招选择什么专业好呢?有哪些专业适合文科女生来学习呢?有途网小编为大家整理了一些专业。语言类专业对于高职单招的专业来说&#xff0c;如今的社会发展对于纯中文的专业并不看好&#xff0c;所以说如果文科女生想要学习语言类高职单…

工程师必备:C/C 单元测试万能插桩工具

研发效能是一个涉及面很广的话题&#xff0c;它涵盖了软件交付的整个生命周期&#xff0c;涉及产品、架构、开发、测试、运维&#xff0c;每个环节都可能影响顺畅、高质量地持续有效交付。在腾讯安全平台部实际研发与测试工作中我们发现&#xff0c;代码插桩隔离是单元测试工作…

html拖拽手势,h5实现手势操作放大缩小拖动等

最近开发遇到了这个需求&#xff0c;使用vue开发h5加一个手势放大缩小的功能&#xff0c;移动端的手势操作用原生的写法太麻烦&#xff0c;而且体验还不好&#xff0c;所以从github找到一个hammer.js的一个手势操作插件。官方文档地址&#xff1a;http://hammerjs.github.io/文…

selenium持续集成_使用Selenium进行Spring Boot集成测试

selenium持续集成Web集成测试允许对Spring Boot应用程序进行集成测试&#xff0c;而无需进行任何模拟。 通过使用WebIntegrationTest和SpringApplicationConfiguration我们可以创建加载应用程序并在正常端口上侦听的测试。 Spring Boot的这一小增加使使用Selenium WebDriver创建…

这才是你想要的C语言学习路线!

点击上方蓝字关注我&#xff0c;了解更多咨询作为一门古老的编程语言&#xff0c;大家熟知它不仅是因为拥有48年的发展历程&#xff0c;更主要还是因为当下大部分程序员走入编程世界第一个学习的语言就是C语言。而近年来高速发展的物联网和智能设备&#xff0c;又把C语言推向了…

html流式布局插件,Jquery瀑布流网格布局插件

插件描述&#xff1a;一款简单且高度可定制的jQuery瀑布流网格布局插件。通过该瀑布流网格插件你可以动态添加和删除各种尺寸的图片&#xff0c;定义图片宽度&#xff0c;设置网格的列数&#xff0c;或使用流式布局方式&#xff0c;甚至还可以通过URL动态添加图片。使用该瀑布流…

mongodb上限集合_用Java创建MongoDB上限集合

mongodb上限集合在MongoDB中&#xff0c;可以以循环方式将文档的插入顺序保留到集合中。 这些类型的集合在MongoDB中称为上限集合。 MongoDB文档描述了上限集合&#xff1a; 上限集合是固定大小的集合&#xff0c;它们支持高吞吐量操作&#xff0c;这些操作根据插入顺序来插入…

编程语言:C语言与Java的细致对比,你知道选谁了吗?

点击上方蓝字关注我&#xff0c;了解更多咨询1.Java与C语言各自的优势C语言是面向过程的语言&#xff0c;执行效率高;Java是面向对象的语言&#xff0c;执行效率比C语言低。C语言最关键的是比Java多了指针&#xff0c;这也说明了Java的健壮性&#xff0c;还有Java的多线程机制使…

ajax实现表单验证 html,Ajax+ajax做的表单验证

//Ajx实现异步示例&#xff0c;blur实现失去焦点触发jQuery(#formname).blur(check);function check(){alert("开始执行Ajax");//判断用户是否存在var formname jQuery("#formname").val();if(formname""){jQuery(#msgName).html(表单名称不能为…

java ee maven_针对新手的Java EE7和Maven项目–第8部分

java ee maven第一部分 &#xff0c; 第2部分 &#xff0c; 第3部分 &#xff0c; 第4部分 &#xff0c; 第5部分 &#xff0c; 第6部分 &#xff0c; 第7部分 第8部分 自上一篇文章以来&#xff0c;这一系列教程已经有很长时间了。 是时候恢复并在我们的简单项目中添加…