css hack技巧

在本文中,我们将探讨五种方法,这些方法可以使用有效的编码来帮助垃圾回收器花费更少的CPU时间分配和释放内存,并减少GC开销。 较长的GC通常会导致我们的代码在回收内存时停止(也称为“停止世界”)。

一些背景

建立GC的目的是处理大量短期对象的分配(例如渲染网页等,其中大部分分配的对象在服务页面后就已过时)。

GC使用所谓的“年轻”来完成此工作–分配新对象的堆段。 每个对象都有一个“年龄”(放置在对象的标题位中),该年龄定义了在没有回收的情况下“生存”了多少个集合。 一旦达到一定年龄,该对象将被复制到堆中称为“幸存者”或“旧”一代的另一部分。

该过程虽然有效,但仍然要付出代价。 能够减少临时分配的数量确实可以帮助我们提高吞吐量,尤其是在大规模应用程序中。

下面是五种我们可以编写日常代码的方法,这些代码可以提高内存效率,而不必花费大量时间或减少代码的可读性。

1.避免隐式字符串

字符串几乎是我们管理的每个数据结构不可或缺的一部分。 它们比其他原始值重得多,它们对内存使用量的影响要大得多。

要注意的最重要的事情之一是字符串是不可变的 。 分配后不能修改它们。 用于连接的运算符(例如“ +”)实际上分配了一个新的String,其中包含要连接的字符串的内容。 更糟糕的是,有一个隐式的StringBuilder对象被分配来实际进行组合它们的工作。

例如 -

a = a + b; // a and b are Strings

编译器在后台生成可比较的代码:

StringBuilder temp = new StringBuilder(a).
temp.append(b);
a = temp.toString(); // a new String is allocated here.// The previous “a” is now garbage.

但情况变得更糟。

让我们看看这个例子–

String result = foo() + arg;
result += boo();
System.out.println(“result = “ + result);

在此示例中,我们在后台分配了3个StringBuilder-每个加号操作一个,另外两个Strings-一个用于保存第二个赋值的结果,另一个用于保存传递给print方法的字符串。 那是另外5个对象 ,否则它们看起来很简单。

想一想在实际的代码场景中会发生什么,例如生成网页,使用XML或从文件读取文本。 嵌套在循环结构中,您可能正在查看成百上千个隐式分配的对象。 尽管VM具有处理此问题的机制, 但它是有代价的 –由用户支付。

解决方案:减少这种情况的一种方法是主动使用StringBuilder分配。 下面的示例获得与上面的代码相同的结果,同时仅分配一个StringBuilder和一个String来保存最终结果,而不是原来的五个对象。

StringBuilder value = new StringBuilder(“result = “);
value.append(foo()).append(arg).append(boo());
System.out.println(value);

通过注意Strings和StringBuilders的隐式分配方式,可以从实质上减少大规模代码位置中的短期分配量。

2.计划清单的能力

诸如ArrayLists之类的动态集合是保存动态长度数据的最基本的结构之一。 ArrayList和其他集合(例如HashMaps和TreeMaps)是使用基础Object []数组实现的。 像字符串(char []数组本身包装)一样,数组也是不可变的。 显而易见的问题变成了-如果底层数组的大小是不变的,我们如何在集合中添加/放置项目? 答案也很明显–通过分配更多的数组

让我们看看这个例子–

List<Item> items = new ArrayList<Item>();for (int i = 0; i < len; i++)
{Item item = readNextItem();items.add(item);
}

len的值确定循环结束后项目的最终长度。 但是,此值对于ArrayList的构造方法未知,该方法会分配一个具有默认大小的新Object数组。 每当超出内部阵列的容量时,它就会被具有足够长度的新阵列替换,从而使先前的阵列成为垃圾。

如果要执行数千次循环,则可能会强制分配一个新数组,并多次收集前一个数组。 对于在大规模环境中运行的代码,这些分配和取消分配都从计算机的CPU周期中扣除。

解决方案:尽可能分配具有初始容量的列表和地图,如下所示:

List<MyObject> items = new ArrayList<MyObject>(len);

这样可以确保在运行时不会发生内部数组的不必要分配和释放,因为列表现在具有足够的容量开始。 如果您不知道确切的大小,最好对平均大小进行估计(例如1024、4096),并添加一些缓冲区以防止意外溢出。

3.使用有效的原始集合

Java编译器的当前版本通过使用“装箱”来支持具有原始键或值类型的数组或映射-将原始值包装在可由GC分配和回收的标准对象中。

这可能会带来一些负面影响 。 Java使用内部数组实现大多数集合。 对于添加到HashMap的每个键/值条目,分配一个内部对象来容纳两个值。 这在处理地图时是必不可少的,这意味着每次将商品放入地图时都要进行额外的分配和可能的重新分配。 还可能存在容量增加和必须重新分配新的内部阵列的代价。 当处理包含数千个或更多条目的大型地图时,这些内部分配可能会增加GC的成本。

一种非常常见的情况是在原始值(例如Id)和对象之间保留映射。 由于Java的HashMap是为保存对象类型(相对于基元)而构建的,因此这意味着映射中的每个插入都可以潜在地分配另一个对象来保存基元值(“装箱”它)。

标准的Integer.valueOf方法缓存0到255之间的值,但是对于每个大于0的数字,除了内部键/值输入对象之外,还将分配一个新对象。 这可能会使映射的GC开销增加三倍以上。 对于那些来自C ++背景的人来说,这确实是令人不安的消息,因为STL模板可以非常有效地解决此问题。

幸运的是,此问题正在Java的下一版本中进行。 在此之前,一些出色的库已经对其进行了相当有效的处理,这些库为每种Java的原始类型提供了原始树,映射和列表。 我强烈推荐Trove ,我已经使用了很长时间 ,发现它确实可以减少大规模代码中的GC开销。

4.使用流而不是内存中的缓冲区

我们在服务器应用程序中处理的大多数数据都是以文件或数据的形式从网络上从另一个Web服务或DB传给我们的。 在大多数情况下,传入的数据是序列化的形式,在我们开始对其进行操作之前,需要将其反序列化为Java对象。 这个阶段很容易出现大量的隐式分配

通常最简单的方法是使用ByteArrayInputStream,ByteBuffer将数据读取到内存中,然后将其传递给反序列化代码。

这可能是一个不好的举动 ,因为您需要在构造出新的对象时为整个数据分配和释放空间。 而且由于数据的大小可能是未知的,您猜对了–您必须分配和取消分配内部byte []数组,以在数据超出初始缓冲区的容量时容纳它们。

解决方案非常简单。 大多数持久性库(例如Java的本机序列化,Google的协议缓冲区等)都可以直接从传入的文件或网络流中反序列化数据,而不必将其保留在内存中,也不必分配新的内部字节数组来保存数据。随着数据的增长。 如果可以的话,请采用这种方法,而不是将数据加载到内存中。 您的GC将感谢您。

5.汇总列表

不变性是一件美丽的事情,但是在某些大规模情况下,它可能会存在一些严重的缺点。 一种情况是在方法之间传递List对象。

从函数返回集合时,通常建议在方法内创建集合对象(例如ArrayList),将其填充并以不可变的Collection接口的形式返回。

在某些情况下这不能很好地工作 。 最引人注目的是将集合从多个方法调用中聚合到最终集合中。 虽然不变性提供了更多的清晰度,但在大规模情况下,这也可能意味着临时集合的大量分配。

在这种情况下,解决方案不是返回新的集合,而是将值聚合到单个集合中,该集合作为参数传递到这些方法中。

示例1(效率低下)–

List<Item> items = new ArrayList<Item>();for (FileData fileData : fileDatas)
{// Each invocation creates a new interim list with possible// internal interim arraysitems.addAll(readFileItem(fileData));
}

示例2 –

List<Item> items =new ArrayList<Item>(fileDatas.size() * avgFileDataSize * 1.5);for (FileData fileData : fileDatas)
{readFileItem(fileData, items); // fill items inside
}

示例2在不遵守不变性规则(通常应遵守该规则)的同时,可以保存N个列表分配(以及任何临时数组分配)。 在大规模情况下,这可以为您的GC带来福音。

补充阅读

  • 字符串实习– http://plumbr.eu/blog/reducing-memory-usage-with-string-intern
  • 高效的包装器– http://vanillajava.blogspot.co.il/2013/04/low-gc-coding-efficient-listeners.html
  • 使用Trove – http://java-performance.info/primitive-types-collections-trove-library/

此帖子也可以在Speaker Deck上找到

参考:来自Takipi博客的JCG合作伙伴 Iris Shoor的 5种编码技巧以减少GC开销 。

翻译自: https://www.javacodegeeks.com/2013/07/5-coding-hacks-to-reduce-gc-overhead.html

css hack技巧

css hack技巧_5种减少Hack的编码技巧相关推荐

  1. 苹果电子邮件怎么注册_外贸技巧 | 6种简单的电子邮件营销技巧,你知道几个?...

    原标题:外贸技巧 | 6种简单的电子邮件营销技巧,你知道几个? 通过电子邮件销售给他们的产品的消费者比电子邮件营销活动外的消费者高出138%.有了这样的数字,电子邮件是您不能忽视的一个渠道. 为什么要 ...

  2. java编码技巧_两个Java初学者编码技巧

    以下是我在Java-For-Testers面对面培训中教授新开发时口头传递的一些技巧. 首先编写您想要查看的代码 看到它们后立即删除语法错误 编写您想要首先看到的代码 例如,创建博客评论,例如: / ...

  3. 5个编码技巧以减少GC开销

    在本文中,我们将介绍五种方法,这些方法可以使用有效的编码来帮助垃圾回收器减少分配和释放内存的CPU时间,并减少GC开销. 较长的GC通常会导致我们的代码在回收内存时被停止(也称为"停止世界& ...

  4. html css导航栏字体图标,HTML+CSS入门之两种图标字体库

    本篇教程介绍了HTML+CSS入门之两种图标字体库,希望阅读本篇文章以后大家有所收获,帮助大家HTML+CSS入门. < ## 0. 前言 比较基础的图标加载:和块元素的背景background ...

  5. html盒子居中的方式,CSS盒子居中三种方法

    前言 CSS盒子居中,我觉得是很有必要学习一下的.特别是第三种方法,奇淫技巧升级版,也是生产环境中非常常见的一种方法,不需要知道宽度,随着祖先元素的变化而变化! 1.常规方法 常规方法只需要给盒子设置 ...

  6. html如何引入css文件?HTML引入外部css文件的四种方法

    在学习前端的时候,我们应该知道css给html标记添加各种样式,用来告诉浏览器,因该如何显示这些标记里面的内容.既然css是用来给html添加各种样式的,那么,html中如何引入外部的css文呢?本篇 ...

  7. CSS垂直居中的10种实现姿势

    前言 前端开发中元素居中是最常见和最经常使用到的css技巧,不仅开发中经常会用到,面试官出题考核基础时有时候也会问道这类问题.本文主要介绍10种垂直居中的方法.希望对你我都有帮组. 1.line-he ...

  8. Facebook HHVM 和 Hack 手册----1.什么是Hack?

    什么是Hack? Hack 是一种基于HHVM(HipHop VM 是Facebook推出的用来执行PHP代码的虚拟机,它是一个PHP的JIT编译器,同时具有产生快速代码和即时编译的优点)的新型编程语 ...

  9. 采访拍摄镜头技巧_5个现场直播采访的有效技巧

    采访拍摄镜头技巧 The disruption caused by the coronavirus is presenting an opportunity for employers to thin ...

最新文章

  1. android 刷机 备份,安卓刷机后如何还原以前ROM和系统备份
  2. PLC項目任務單2---狀態轉移圖
  3. 1、Hive原理及查询优化
  4. Android利用百度地图定位
  5. 文件操作,列表实例NiceHexSpiral
  6. (转)搭建Spring4.x.x开发环境
  7. 使用parseInt转换规范非法输入
  8. NativeWindow_02_DialogBoxParam_VC6
  9. CORE Transport Technologies宣布蓝牙航空货物跟踪系统重大升级
  10. HDU:2055 An easy problem
  11. oracle 创建会话表,oracle临时会话表在存储过程中的使用
  12. 利用matlab求系统的单位阶跃响应,基于Matlab6_5的归一化二阶系统单位阶跃响应的模拟演示...
  13. 超准的普通话水平测试,敢不敢进来做一下!
  14. Python 一大坑,配置文件中字典引用问题(拷贝)。
  15. 九度1047 1163
  16. httpf发送 json_Java用HttpClient4发送http/https协议get/post请求,发送map,json,xml,txt数据...
  17. JavaCV音视频开发宝典:vb8和vp9编码的webm格式视频文件转成mp4文件
  18. iview table 横向拖动表格内容滚动
  19. 虚拟森林火场生成及蔓延模拟
  20. HTML如何在图片上添加内容(如文字,菜单栏,按钮等)

热门文章

  1. codeforces 938D Buy a Ticket 有初值的Dijkstra、有趣的题目
  2. linux下jdk的安装和配置
  3. 26、临时表的创建和重复数据的处理
  4. 为什么我强烈建议大家使用枚举来实现单例
  5. 关于Icon,Image,ImageIcon的简单的对比参考 上篇
  6. JDK8新特性之Optional
  7. 接口 DataOutput
  8. 树层级处理上万条数据优化!
  9. 红歌合唱之团结就是力量
  10. 《四世同堂》金句摘抄(九)