网站的邀请怎么做的,北京正规网站建设有几种,定制v软件免费下载,网站添加备案如性能优化第一规则中所述#xff0c;垃圾是快速代码的敌人。 通过使用垃圾收集器的服务#xff0c;它不仅会破坏任何形式的确定性性能#xff0c;而且我们开始在CPU高速缓存中填充垃圾#xff0c;这将导致程序的高速缓存未命中。 那么#xff0c;我们可以在不创建垃圾的… 如性能优化第一规则中所述垃圾是快速代码的敌人。 通过使用垃圾收集器的服务它不仅会破坏任何形式的确定性性能而且我们开始在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 ------------------------);MapInteger, 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();ChronicleMapBuilderIntValue, BondVOInterface builder ChronicleMapBuilder.of(IntValue.class, BondVOInterface.class).entries(ITERATIONS);try (ChronicleMapIntValue, 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