zoukankan      html  css  js  c++  java
  • Java 代码性能优化之路

    一、前言

    最近了解了企业项目开发,对代码优化方面有了一点兴趣。

    二、Java 基础
    2.1 字符串拼接
    在我们的系统中,存在着大量的缓存,这些缓存的 key 值根据请求参数的不同而拼接起来,如下代码所示:

    JAVA
    优化前

    public class LastPriceCache {
    private String keySuffix = "last_price_%s";

    public double getLastPrice(int id) {
    return redisService.get(this.generatorKey(id));
    }

    private String generatorKey(int id) {
    return String.format(keySuffix, id);
    }
    }
    字符串拼接存在性能损耗,如果 id 值是可预期的,完全可以将其在内存中缓存起来,如下代码所示:

    JAVA
    优化后

    public class LastPriceCache {
    private String keySuffix = "last_price_%s";

    private Map<Integer, String> keyMap = new HashMap<>();

    public double getLastPrice(int id) {
    return redisService.get(this.generatorKey(id));
    }

    private String generatorKey(int id) {
    String result;
    if(!keyMap.containsKey(id)) {
    result = keyMap.get(id);
    } else {
    result = String.format(keySuffix, id);
    keyMap.put(id, result);
    }
    return result;
    }
    }
    2.2 装箱类型
    在我们项目中的问题代码,是在使用 BigDecimal 进行除法操作时,精度保留的小数位数的变量使用了包装类型。可惜在我自己的电脑上没有办法复现出来,也许是公司的电脑配置太低了,哈哈。

    因此我就用包装类型累加来举例把,虽然例子都烂大街了,但能说明问题。将如下代码中的 Long 改成 long,就会得到不一样的耗时结果。

    JAVA

    Long value = 0;
    for(int i = 0; i < 100_0000; i ++) {
    value += i;
    }
    2.3 Stream 合并
    在我们的系统中,存在分页查询用户订单的需求,涉及到对源数据的过滤/截取/排序操作,如下代码所示:

    JAVA
    优化前

    List<Order> sourceOrder = ...;

    List<Order> result = sourceOrder.stream().filter(e -> e.getAmount() > 0).collect(Collectors.toList());

    if(startId > 0) {
    result = result.stream().filter(e -> e.getId() >= startId).collect(Collectors.toList());
    }
    if(endId > 0) {
    result = result.stream().filter(e -> e.getId() < endId).collect(Collectors.toList());
    }

    if(result.size() > limit) {
    result = result.subList(0, limit);
    }

    Collections.reverse(result);
    JDK 1.8 中引入了流式操作,很大程度上使代码变得更加简洁,但是使用不当也会拖慢性能。在上面代码中,滥用了流式操作,完全可以进行合并操作,且后续的截取和排序操作也可以整合在流式操作中,如下代码所示:

    JAVA
    优化后
    List<Order> sourceOrder = ...;

    Stream<Order> stream = sourceOrder.stream();

    stream = stream.filter(e -> e.getAmount() > 0);

    if(startId > 0) {
    stream = stream.filter(e -> e.getId() >= startId);
    }
    if(endId > 0) {
    stream = stream.filter(e -> e.getId() < endId);
    }

    Comparator<Order> comparator = Comparator.comparingLong(Order::getId);
    if(!isAsc) {
    comparator = comparator.reversed();
    }

    List<Order> result = stream.limit(limit).sorted(comparator).collect(Collectors.toList());
    三、三方包
    3.1 FastJson 预热
    在我们项目中,采用 FastJson 作为序列化库。FastJson 虽然号称速度非常快,但是其在首次序列化时速度却是让人大跌眼镜,在压测环境下,一下次就被暴露出来了。

    只需要在程序启动时,静态加载以下两个 FastJson 类,问题就可以解决。

    JAVA

    static {
    new ParserConfig();
    new SerializeConfig();
    }
    3.2 浅拷贝
    之前项目中,直接使用 spring 框架的 BeanUtils 进行浅拷贝,在压测中也发现其耗时比较严重。而使用同为 spring 提供的 BeanCopier 则性能很好。

    JAVA
    BeanCopier 工具类

    public class BeanCopierUtils {
    private static final Map<String, BeanCopier> CACHE = new ConcurrentHashMap<>();

    public static void copyProperties(Object source, Object target) {
    BeanCopier copier = getBeanCopier(source.getClass(), target.getClass());
    copier.copy(source, target, null);
    }

    private static BeanCopier getBeanCopier(Class<?> sourceClazz, Class<?> targetClazz) {
    String key = generatorKey(sourceClazz, targetClazz);
    BeanCopier copier;
    if(CACHE.containsKey(key)) {
    copier = CACHE.get(key);
    } else {
    copier = BeanCopier.create(sourceClazz, targetClazz, false);
    CACHE.put(key, copier);
    }
    return copier;
    }

    private static String generatorKey(Class<?> sourceClazz, Class<?> targetClazz) {
    return sourceClazz + "_" + targetClazz;
    }
    }

  • 相关阅读:
    FEniCS 1.1.0 发布,计算算术模型
    Piwik 1.10 发布,增加社交网站统计
    淘宝褚霸谈做技术的心态
    CyanogenMod 10.1 M1 发布
    Druid 发布 0.2.11 版本,数据库连接池
    GNU Gatekeeper 3.2 发布
    Phalcon 0.9.0 BETA版本发布,新增大量功能
    EUGene 2.6.1 发布,UML 模型操作工具
    CVSps 3.10 发布,CVS 资料库更改收集
    Opera 移动版将采用 WebKit 引擎
  • 原文地址:https://www.cnblogs.com/charles-s/p/14941465.html
Copyright © 2011-2022 走看看