ImageVerifierCode 换一换
格式:DOCX , 页数:18 ,大小:216.83KB ,
资源ID:21723735      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/21723735.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(JVM初探使用堆外内存减少FullGCWord文档格式.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

JVM初探使用堆外内存减少FullGCWord文档格式.docx

1、05. */public class DirectByteBufferApp extends AbstractAppInvoker Test Override public void invoke(Object. param) Map map = createInHeapMap(SIZE); / move in off-heap byte bytes = serializer.serialize(map); ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); buffer.put(bytes); buffer.flip();

2、 / for gc map = null; bytes = null; System.out.println(write down); / move out from off-heap byte offHeapBytes = new bytebuffer.limit(); buffer.get(offHeapBytes); deserMap = serializer.deserialize(offHeapBytes); for (int i = 0; i SIZE; +i) String key = key- + i; FeedDO feedDO = deserMap.get(key); ch

3、eckValid(feedDO); if (i % 10000 = 0) read + i); free(buffer); private Map createInHeapMap(int size) long createTime = System.currentTimeMillis(); map = new ConcurrentHashMap(size); size; FeedDO value = createFeed(i, key, createTime); map.put(key, value); return map;由JDK提供的堆外内存访问API只能申请到一个类似一维数组的Byte

4、Buffer, JDK并未提供基于堆外内存的实用数据结构实现(如堆外的Map、Set), 因此想要实现Cache的功能只能在write()时先将数据put()到一个堆内的HashMap, 然后再将整个Map序列化后MoveIn到DirectMemory, 取缓存则反之. 由于需要在堆内申请HashMap, 因此可能会导致多次Full GC. 这种方式虽然可以使用堆外内存, 但性能不高、无法发挥堆外内存的优势. 幸运的是开源界的前辈开发了诸如Ehcache、MapDB、Chronicle Map等一系列优秀的堆外内存框架, 使我们可以在使用简洁API访问堆外内存的同时又不损耗额外的性能.其中又以

5、Ehcache最为强大, 其提供了in-heap、off-heap、on-disk、cluster四级缓存, 且Ehcache企业级产品(BigMemory Max / BigMemory Go)实现的BigMemory也是Java堆外内存领域的先驱.示例2: MapDB API实现堆外Cachepublic class MapDBApp extends AbstractAppInvoker private static HTreeMap mapDBCache; static mapDBCache = DBMaker.hashMapSegmentedMemoryDirect() .expire

6、MaxSize(SIZE) .make(); FeedDO feed = createFeed(i, key, System.currentTimeMillis(); mapDBCache.put(key, feed); FeedDO feedDO = mapDBCache.get(key);结果 & 分析DirectByteBufferApp S0 S1 E O P YGC YGCT FGC FGCT GCT0.00 0.00 5.22 78.57 59.85 19 2.902 13 7.251 10.153the last one jstat of MapDBApp0.00 0.03 8.

7、02 0.38 44.46 171 0.238 0 0.000 0.238运行DirectByteBufferApp.invoke()会发现有看到很多Full GC的产生, 这是因为HashMap需要一个很大的连续数组, Old区很快就会被占满, 因此也就导致频繁Full GC的产生. 而运行MapDBApp.invoke()可以看到有一个DirectMemory持续增长的过程, 但FullGC却一次都没有了.实验: 使用堆外内存减少Full GC实验环境java -versionjava version 1.7.0_79Java(TM) SE Runtime Environment (bui

8、ld 1.7.0_79-b15)Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)VM Options-Xmx512M-XX:MaxDirectMemorySize=512M+PrintGC+UseConcMarkSweepGC+CMSClassUnloadingEnabledCMSInitiatingOccupancyFraction=80+UseCMSInitiatingOccupancyOnly实验数据 170W条动态(FeedDO).实验代码第1组: in-heap、affect by GC、no serial

9、izeConcurrentHashMapApppublic class ConcurrentHashMapApp extends AbstractAppInvoker private static final Map cache = new ConcurrentHashMap(); / write String key = String.format(key_%s, i); FeedDO feedDO = createFeed(i, key, System.currentTimeMillis(); cache.put(key, feedDO); / read FeedDO feedDO = c

10、ache.get(key);GuavaCacheApp类似, 详细代码可参考完整项目.第2组: off-heap、not affect by GC、need serializeEhcacheApppublic class EhcacheApp extends AbstractAppInvoker private static Cache cache; ResourcePools resourcePools = ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(1000, EntryUnit.ENTRIES) .offheap(480, M

11、emoryUnit.MB) .build(); CacheConfiguration configuration = CacheConfigurationBuilder .newCacheConfigurationBuilder(String.class, FeedDO.class, resourcePools) cache = CacheManagerBuilder.newCacheManagerBuilder() .withCache(cacher, configuration) .build(true) .getCache(, String.class, FeedDO.class); O

12、bject o = cache.get(key); checkValid(o);MapDBApp与前同.第3组: off-process、not affect by GC、serialize、affect by process communicationLocalRedisApppublic class LocalRedisApp extends AbstractAppInvoker private static final Jedis cache = new Jedis(localhost, 6379); private static final IObjectSerializer seri

13、alizer = new Hessian2Serializer(); byte value = serializer.serialize(feedDO); cache.set(key.getBytes(), value);write byte value = cache.get(key.getBytes(); FeedDO feedDO = serializer.deserialize(value);结果分析对比前面几组数据, 可以有如下总结:将长生命周期的大对象(如cache)移出heap可大幅度降低Full GC次数与耗时;使用off-heap存储对象需要付出serialize/deser

14、ialize成本;将cache放入分布式缓存需要付出进程间通信/网络通信的成本(UNIX Domain/TCP IP)附:off-heap的Ehcache能够跑出比in-heap的HashMap/Guava更好的成绩确实是我始料未及的O(_)O, 但确实这些数据和堆内存的搭配导致in-heap的Full GC太多了, 当heap堆开大之后就肯定不是这个结果了. 因此在使用堆外内存降低Full GC前, 可以先考虑是否可以将heap开的更大. 性能测试框架在main函数启动时, 扫描com.vdian.se.apps包下的所有继承了AbstractAppInvoker的类, 然后使用Javass

15、ist为每个类生成一个代理对象: 当invoke()方法执行时首先检查他是否标注了Test注解(在此, 我们借用junit定义好了的注解), 并在执行的前后记录方法执行耗时, 并最终对比每个实现类耗时统计.依赖 monsartifactIdcommons-proxyversion$commons.proxy.version/dependencyorg.javassistjavassist$javassist.versioncom.cauchohessian$hessian.versioncom.google.guavaguava$guava.versionjunit$junit.version

16、 STATISTICS_MAP = new HashMap public static void main(String args) throws IOException, IllegalAccessException, InstantiationException SetClass? classes = PackageScanUtil.scanPackage(com.vdian.se.apps for (Class clazz : classes) AbstractAppInvoker invoker = createProxyInvoker(clazz.newInstance(); inv

17、oker.invoke(); /System.gc();* statistics * for (Map.Entry entry : STATISTICS_MAP.entrySet() method + entry.getKey() + total cost + entry.getValue() + ms private static AbstractAppInvoker createProxyInvoker(Object invoker) ProxyFactory factory = w JavassistProxyFactory(); Class superclass = invoker.g

18、etClass().getSuperclass(); Object proxy = factory .createInterceptorProxy(invoker, new ProfileInterceptor(), new Classsuperclass); return (AbstractAppInvoker) proxy; private static class ProfileInterceptor implements Interceptor public Object intercept(Invocation invocation) throws Throwable clazz = invocation.getProxy().getClass(); Method method = clazz.getMethod(invocation.getMethod().getName(), Object.class); Object result = null; if (method.isAnnotationPresent(Test.class) & method.getName().equals(invoke)

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1