范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java中的5个代码性能提升技巧,最高提升近10倍

  这篇文章介绍几个 Java 开发中可以进行  性能优化的小技巧  ,虽然大多数情况下极致优化代码是没有必要的,但是作为一名技术开发者,我们还是想追求代码的更小、更快,更强。如果哪天你发现程序的运行速度不尽人意,可能会想到这篇文章。
  提示:我们不应该为了优化而优化,这有时会增加代码的复杂度。
  这篇文章中的代码都在以下环境中进行性能测试。 JMH version: 1.33(Java 基准测试框架) VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724
  通过这篇文章的测试,将发现以下几个操作的性能差异。 预先分配 HashMap 的大小,提高 1/4 的性能。 优化 HashMap 的 key,性能相差 9.5 倍。 不使用 Enum.values() 遍历,Spring 也曾如此优化。 使用 Enum 代替 String 常量,性能高出 1.5 倍。 使用高版本 JDK,基础操作有 2-5 倍性能差异。
  当前文章属于 Java 性能分析优化 系列文章,点击可以查看所有文章。
  当前文章中的测试使用 JMH 基准测试,相关文章: 使用JMH进行Java代码性能测试 。 预先分配 HashMap 的大小
  HashMap 是 Java 中最为常用的集合之一,大多数的操作速度都非常快,但是 HashMap 在调整自身的容量大小时是很慢且难以自动优化,因此我们在定义一个 HashMap 之前,应该尽可能的给出它的容量大小。给出 size 值时要考虑负载因子,HashMap 默认负载因子是 0.75,也就是要设置的 size 值要除于 0.75。
  相关文章: HashMap 源码分析解读
  下面使用 JMH 进行基准测试,测试分别向初始容量为 16 和 32 的 HashMap 中插入 14 个元素的效率。 /**  * @author https://www.wdbyte.com  */ @State(Scope.Benchmark) @Warmup(iterations = 3,time = 3) @Measurement(iterations = 5,time = 3) public class HashMapSize {      @Param({"14"})     int keys;      @Param({"16", "32"})     int size;      @Benchmark     public HashMap getHashMap() {         HashMap map = new HashMap<>(size);         for (int i = 0; i < keys; i++) {             map.put(i, i);         }         return map;     } }
  HashMap 的初始容量是 16,负责因子 0.75,最多插入 12 个元素,再插入时就要进行扩容,所以插入 14 个元素过程中需要扩容一次,但是如果 HashMap 初始化时就给了 32 容量,那么最多可以承载 32 * 0.75 = 24  个元素,所以插入 14 个元素时是不需要扩容操作的。# JMH version: 1.33 # VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724  Benchmark               (keys)  (size)   Mode  Cnt        Score        Error  Units HashMapSize.getHashMap      14      16  thrpt   25  4825825.152   323910.557  ops/s HashMapSize.getHashMap      14      32  thrpt   25  6556184.664   711657.679  ops/s
  可以看到在这次测试中,初始容量为32 的 HashMap 比初始容量为 16 的 HashMap 每秒可以多操作 26% 次,已经有 1/4 的性能差异 了。优化 HashMap 的 key
  如果 HashMap 的 key 值需要用到多个 String 字符串时,把字符串作为某个类属性,然后使用这个类的实例作为 key 会比使用字符串拼接效率更高。
  下面测试使用两个字符串拼接作为 key,和把两个字符串作为 MutablePair 类的属性引用,然后使用 MutablePair 对象作为 key 的运行效率差异。/**  * @author https://www.wdbyte.com  */ @State(Scope.Benchmark) @Warmup(iterations = 3, time = 3) @Measurement(iterations = 5, time = 3) public class HashMapKey {      private int size = 1024;     private Map stringMap;     private Map pairMap;     private String[] prefixes;     private String[] suffixes;      @Setup(Level.Trial)     public void setup() {         prefixes = new String[size];         suffixes = new String[size];         stringMap = new HashMap<>();         pairMap = new HashMap<>();         for (int i = 0; i < size; ++i) {             prefixes[i] = UUID.randomUUID().toString();             suffixes[i] = UUID.randomUUID().toString();             stringMap.put(prefixes[i] + ";" + suffixes[i], i);             // use new String to avoid reference equality speeding up the equals calls             pairMap.put(new MutablePair(prefixes[i], suffixes[i]), i);         }     }      @Benchmark     @OperationsPerInvocation(1024)     public void stringKey(Blackhole bh) {         for (int i = 0; i < prefixes.length; i++) {             bh.consume(stringMap.get(prefixes[i] + ";" + suffixes[i]));         }     }      @Benchmark     @OperationsPerInvocation(1024)     public void pairMap(Blackhole bh) {         for (int i = 0; i < prefixes.length; i++) {             bh.consume(pairMap.get(new MutablePair(prefixes[i], suffixes[i])));         }     } }
  测试结果:# JMH version: 1.33 # VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724  Benchmark              Mode  Cnt         Score         Error  Units HashMapKey.pairMap    thrpt   25  89295035.436   6498403.173  ops/s HashMapKey.stringKey  thrpt   25   9410641.728    389850.653  ops/s
  可以发现使用对象引用作为 key 的性能,是使用 String 拼接作为 key 的 性能的 9.5 倍 。不使用 Enum.values() 遍历
  我们通常会使用 Enum.values()  进行枚举类遍历,但是这样每次调用都会分配枚举类值数量大小的数组用于操作,这里完全可以缓存起来,以减少每次内存分配的时间和空间消耗。/**  * 枚举类遍历测试  *  * @author https://www.wdbyte.com  */ @State(Scope.Benchmark) @Warmup(iterations = 3, time = 3) @Measurement(iterations = 5, time = 3) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public class EnumIteration {     enum FourteenEnum {         a,b,c,d,e,f,g,h,i,j,k,l,m,n;          static final FourteenEnum[] VALUES;         static {             VALUES = values();         }     }      @Benchmark     public void valuesEnum(Blackhole bh) {         for (FourteenEnum value : FourteenEnum.values()) {             bh.consume(value.ordinal());         }     }      @Benchmark     public void enumSetEnum(Blackhole bh) {         for (FourteenEnum value : EnumSet.allOf(FourteenEnum.class)) {             bh.consume(value.ordinal());         }     }      @Benchmark     public void cacheEnums(Blackhole bh) {         for (FourteenEnum value : FourteenEnum.VALUES) {             bh.consume(value.ordinal());         }     } }
  运行结果# JMH version: 1.33 # VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724  Benchmark                   Mode  Cnt         Score         Error  Units EnumIteration.cacheEnums   thrpt   25  15623401.567   2274962.772  ops/s EnumIteration.enumSetEnum  thrpt   25   8597188.662    610632.249  ops/s EnumIteration.valuesEnum   thrpt   25  14713941.570    728955.826  ops/s
  很明显使用缓存后的遍历速度是最快的,使用 EnumSet  遍历效率是最低的,这很好理解,数组的遍历效率是大于哈希表的。
  可能你会觉得这里使用 values()  缓存和直接使用 Enum.values()  的效率差异很小,其实在某些调用频率很高的场景下是有很大区别的,在 Spring 框架中,曾使用 Enum.values()  这种方式在每次响应时遍历 HTTP 状态码枚举类,这在请求量大时造成了不必要的性能开销,后来进行了 values()  缓存优化。
  下面是 这次提交 的截图:
  使用 Enum 代替 String 常量
  使用 Enum 枚举类代替 String 常量有明显的好处,枚举类强制验证,不会出错,同时使用枚举类的效率也更高。即使作为 Map 的 key 值来看,虽然 HashMap 的速度已经很快了,但是使用 EnumMap 的速度可以更快。
  提示:不要为了优化而优化,这会增加代码的复杂度。
  下面测试使用使用 Enum 作为 key,和使用 String 作为 key,在 map.get  操作下的性能差异。/**  * @author https://www.wdbyte.com  */ @State(Scope.Benchmark) @Warmup(iterations = 3, time = 3) @Measurement(iterations = 5, time = 3) public class EnumMapBenchmark {      enum AnEnum {         a, b, c, d, e, f, g,         h, i, j, k, l, m, n,         o, p, q,    r, s, t,         u, v, w,    x, y, z;     }      /** 要查找的 key 的数量 */     private static int size = 10000;     /** 随机数种子 */     private static int seed = 99;      @State(Scope.Benchmark)     public static class EnumMapState {         private EnumMap map;         private AnEnum[] values;          @Setup(Level.Trial)         public void setup() {             map = new EnumMap<>(AnEnum.class);             values = new AnEnum[size];             AnEnum[] enumValues = AnEnum.values();             SplittableRandom random = new SplittableRandom(seed);             for (int i = 0; i < size; i++) {                 int nextInt = random.nextInt(0, Integer.MAX_VALUE);                 values[i] = enumValues[nextInt % enumValues.length];             }             for (AnEnum value : enumValues) {                 map.put(value, UUID.randomUUID().toString());             }         }     }      @State(Scope.Benchmark)     public static class HashMapState{         private HashMap map;         private String[] values;          @Setup(Level.Trial)         public void setup() {             map = new HashMap<>();             values = new String[size];             AnEnum[] enumValues = AnEnum.values();             int pos = 0;             SplittableRandom random = new SplittableRandom(seed);             for (int i = 0; i < size; i++) {                 int nextInt = random.nextInt(0, Integer.MAX_VALUE);                 values[i] = enumValues[nextInt % enumValues.length].toString();             }             for (AnEnum value : enumValues) {                 map.put(value.toString(), UUID.randomUUID().toString());             }         }     }      @Benchmark     public void enumMap(EnumMapState state, Blackhole bh) {         for (AnEnum value : state.values) {             bh.consume(state.map.get(value));         }     }      @Benchmark     public void hashMap(HashMapState state, Blackhole bh) {         for (String value : state.values) {             bh.consume(state.map.get(value));         }     } }
  运行结果:# JMH version: 1.33 # VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724  Benchmark                  Mode  Cnt      Score      Error  Units EnumMapBenchmark.enumMap  thrpt   25  22159.232   1268.800  ops/s EnumMapBenchmark.hashMap  thrpt   25  14528.555   1323.610  ops/s
  很明显,使用 Enum 作为 key 的性能比使用 String 作为 key 的性能高出 1.5 倍。但是仍然要根据实际情况考虑是否使用 EnumMap 和 EnumSet。使用高版本 JDK
  String 类应该是 Java 中使用频率最高的类了,但是 Java 8 中的 String 实现相比高版本 JDK ,则占用空间更多,性能更低。
  下面测试 String 转 bytes 和 bytes 转 String 在 Java 8 以及 Java 11 中的性能开销。/**  * @author https://www.wdbyte.com  * @date 2021/12/23  */ @State(Scope.Benchmark) @Warmup(iterations = 3, time = 3) @Measurement(iterations = 5, time = 3) public class StringInJdk {      @Param({"10000"})     private int size;     private String[] stringArray;     private List byteList;      @Setup(Level.Trial)     public void setup() {         byteList = new ArrayList<>(size);         stringArray = new String[size];         for (int i = 0; i < size; i++) {             String uuid = UUID.randomUUID().toString();             stringArray[i] = uuid;             byteList.add(uuid.getBytes(StandardCharsets.UTF_8));         }     }      @Benchmark     public void byteToString(Blackhole bh) {         for (byte[] bytes : byteList) {             bh.consume(new String(bytes, StandardCharsets.UTF_8));         }     }      @Benchmark     public void stringToByte(Blackhole bh) {         for (String s : stringArray) {             bh.consume(s.getBytes(StandardCharsets.UTF_8));         }     } }
  测试结果:# JMH version: 1.33 # VM version: JDK 1.8.0_151, Java HotSpot(TM) 64-Bit Server VM, 25.151-b12  Benchmark                 (size)   Mode  Cnt     Score     Error  Units StringInJdk.byteToString   10000  thrpt   25  2396.713   133.500  ops/s StringInJdk.stringToByte   10000  thrpt   25  1745.060    16.945  ops/s  # JMH version: 1.33 # VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724  Benchmark                 (size)   Mode  Cnt     Score     Error  Units StringInJdk.byteToString   10000  thrpt   25  5711.954    41.865  ops/s StringInJdk.stringToByte   10000  thrpt   25  8595.895   704.004  ops/s
  可以看到在 bytes 转 String 操作上,Java 17 的性能是 Java 8 的 2.5 倍左右,而 String 转 bytes 操作,Java 17 的 性能是 Java 8 的 5 倍 。关于字符串的操作非常基础,随处可见,可见高版本的优势十分明显。

若不差钱,可以给家里添上这5件智能小家电,用后幸福感强想为枯燥的生活添加仪式感和幸福感,最简单的方式就是添置几件小家电!今天就为大家分享5件智能化小家电,尽管买时割肉,但用后就上瘾!我家里就一直用着它们,连爸妈都夸我买到宝!扫拖一体机CINNO1月国内智能机销量环比增长38。6,OPPO站稳国内智能机销量榜首36氪获悉,根据CINNOResearch数据显示,1月中国市场智能手机销量约3,087万部,同比增长0。4,环比增长38。6。OPPOvivo依旧站稳国内智能机销量排名第一和第二潮评读懂政府工作报告中的数字信号来源浙江在线提请审议的政府工作报告,在强调深入实施创新驱动发展战略的同时,就加强数字中国建设整体布局促进数字经济发展等方面作出部署。5G工业互联网关键软硬件从关键词中可看出数字经济颜值控,不纠结,性能堪比台式机,GPDWIN3到底有何吸引力?提到了游戏掌机,各位男同胞们一定不会陌生的。对于他们而言,掌机更代表着一代人的回忆。时至今日,当今的掌机已不可同日而语,毫不夸张的讲,相比最早接触的红白掌机,它的变化可谓是翻天覆地Linux根目录空间100该如何扩展Linux的根分区如果已经使用率达到100,导致服务不能正常进行,我们可以这样扩展根目录的大小(注意下面所有操作需在root用户下完成)。1。新加一块硬盘(这里使用的是sde),先股票数字货币NFT。等等资本家靠这些收割大众的劳动价值股票数字货币NFT。等等资本家靠这些压榨大众的劳动价值掠夺财富。农业制造业建筑业运输业。等等实体都是人类生活所必须的但相关从业人员总会遇到各种压榨。反观各种虚拟产业从最早的股票开始有人建议取消网贷的第一步就应该将网贷踢出征信系统,你怎么看?这个建议绝对值得支持!我就深受其害!某平台刚开始搞什么呗的时候,听同事们说借钱非常简单,比找亲戚朋友之间借钱要方便很多,小到几百块都可以借。当时由于比较好奇,手也欠,就决定试试。后巩富文委员加速推进元宇宙脱虚向实当前,新一轮科技革命和产业变革加速演进,前瞻布局发展元宇宙,是做大做强数字经济,抢占未来竞争制高点,把握发展主动权的重要现实路径。元宇宙行不行,底层在基础设施。全国政协委员陕西省人温室气体是如何使地球变暖的?温室气体(GreenhouseGasGHG)导致全球变暖和气候变化,其排放对理解和解决气候危机至关重要。虽然大多数温室气体是自然产生的,但人类活动也加剧了温室气体排放量及其在大气中鼎力推荐github6。7kstar开源IM项目OpenIM性能及消息可靠性测试本报告主要分为两部分,性能测试和消息可靠性测试。前者主要关注吞吐,延时,同时在线用户等,即通常所说的性能指标。后者主要模拟真实环境(比如离线,在线,弱网)消息通道的可靠性。先说结论放过iPhone14吧!说说我对iPhone15的期待据悉下半年的iPhone14系列会正式发布,虽然现在还没有发售,但是作为苹果一年一度的旗舰产品线,iPhone14已经开始引起了广泛的关注。最新曝料表明,iPhone14系列部分机
紫光展锐大破大立做数字世界的生态承载者4月20日,以构go为主题的2021紫光展锐创见未来大会在线上举行。会上,展锐重磅发布了5G业务新品牌唐古拉系列,推出了Cat。1bis新技术特性,并分享了创新业务AR领域的最新商苹果春季发布会一文汇总连iPadPro也用上了M1芯片点击右上角关注我们,每天给您带来最新最潮的科技资讯,让您足不出户也知道科技圈大事!4月21日凌晨,苹果举行了踏春而来在线特别活动,带来了全新的iMaciPadProAirTag和紫特斯拉中国犯了两个错误对老车主逃避问题,将媒体当做敌人在上海车展开幕的第一天,特斯拉可能怎么也不会想到,之前还担心车主和媒体找不到自己的展台,精心制作了地图海报。而一位女车主的维权行为,让这家美国公司在今年的中国上海车展上,成为了最大车主维权遭暴力拖拽,特斯拉忘了三星在中国的下场?人间不值得2021年上海车展刚刚开幕,就爆出了特斯拉女车主因为刹车失灵问题,在车展上维权遭到工作人员暴力拖拽的新闻。从上帝就是顾客,到索赔无门只能去车展维权,遭到工作人员暴力拖拽,美团融资约100亿美元以在新战场与阿里巴巴等比拼本文来自PBFX,国内投资者首选黄金外汇加密货币交易平台。外卖巨头美团正加倍努力在诸如互联网杂货等更新的领域与阿里巴巴之类的公司竞争,并已通过发行新股和可转换债券募集了99。8亿美为什么中国邮政还没有倒闭?因为资本走不到的地方,国家替你走在当今这个快节奏的社会当中,快则成为了这个社会的主旋律,这是因为所有人都坚信,时间的快与慢决定了这个企业的生产效率,当机器高速运转的时候,其最终所能造出的产品则会更多,因此在这个唯南瓜电影获腾讯视频海量版权,中国版Netflix正在崛起犀牛娱乐原创文方正编辑夏添南瓜电影又一次成为行业焦点。今日,南瓜电影所属公司恒腾网络在港交所发布公告,称南瓜电影将与腾讯视频深度合作,获取后者独家版权的海量影视作品授权,供南瓜电影一年涨幅超400倍!狗狗币价格涨至历史新高目前狗狗币(DOGE)已登上推特热搜榜首。金十数据统计回溯狗狗币价格发现,狗狗币2021年1月1日开盘报0。004619美元枚,2021年4月16日最高报价已触及0。47美元枚,年iPhone12又要换颜色来圈钱了?苹果急于寻求新商业故事文荀诗林不知道苹果已经淡出大家的视野多久了。4月14日的时候,苹果终于官宣其春季新品发布会将于4月20日举行,也就是北京时间4月21日凌晨1点。从最初的爆料3月23日,到4月12日1299美元起苹果新iMac正式发布7款新配色,4月30日预售苹果终于迭代了很久没有全新设计的iMac一体机产品线,在正在进行的2021苹果春季发布会中,苹果正式发布了全新外观设计的iMac一体机,轻薄的外观以及多种可选的配色都是其最大的亮点欧拉闪电猫登场,2023年销量百万提起女性汽车品牌,第一个想到的品牌可能是MINI,而提起女性电动汽车品牌,第一个想到的,一定是欧拉。从欧拉旗下的产品命名即可看出,这是一个针对女性用户的汽车品牌,黑猫,白猫,好猫等