性能优化

author author     2022-08-06     343

关键词:

最近在做框架性能优化的时候,发现了一些之前不是很在意却对性能很有影响的内容,同时和以前知道的东西一起做了整理

1、关于比较

最老生常谈的就是==,equals,一个比较绝对值,一个比较引用地址,一般字符串的比较我们直接用equals

但如果我们的数据类型是Integer的时候呢,比较2个Integer是否相等,你是否会写成==?。如果你写了,那么就错了,比较整型的数值你需要这样来写:a.intValue() == b.intValue()

 

2、ArrayList删除一个元素
   作为集合类中最常用的ArrayList,删除一个元素一般有.remove(obj)、和.remove(index)2种方式,通常我们不会太在意调用哪个,写到哪个是哪个。尤其是我们要实现从list中找到满足条件的多个元素,然后删除掉的时候,为了避免使用i--,出现index混乱的问题,我们会使用一个临时的list来存储好满足条件的obj,最后调用list.removeAll(list)来进行。殊不知,这样的写法大大消耗了性能。最近在做性能优化,跟踪cpu消耗的时候,发现了这个removeAll的问题。它内部实现原理会去重新定位找到这个obj对象,然后调用remove删除,而定位obj的过程需要用到equals来进行2个对象的比较,一般我们定义的对象并不会去实现equals方法,所以这个性能消耗就有一点了

 

3、序列化 Serializable
   在集群开发的时候,我们经常会涉及到序列化对象存储到redis中,比如我们的上传控件,为了支持集群上传,我们action里面定义的上传model会进行序列化保存,来保证不同服务器接收到客户端传来的文件片可以使用同一套业务逻辑来进行处理,所以涉及到的类上面我们都需要添加这个关键字。然后会出现一个黄色惊叹号,点出来后建议大家生成一串随机数值,而不是1L,这样保证在编译反序列化时不会出现不同版本代码导致反序列化失败的问题。另外某些同事启动tomcat的时候,经常会发现有警告,某某类不能序列化,但是不影响使用,实际上就是这些类上面没有加上序列化接口导致。


4、transient关键字
很多人不认识或者没有使用过这个关键字,它不同于public、private、protected这么常见。但是在集群模式的web开发中,这个东西就会派上用场。这个关键字修饰的成员变量,将不会进行序列化。某些变量我们是不能序列化的,比如Log4j的日志对象,或者我们的Service、Dao对象,都不能进行序列化,或者是本身序列化就不支持会报错,或者反序列化出来使用的时候会出现问题,不一而足。

 

5、初始化大小
StringBuffer 、ArrayList

stringbuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建stringbuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

例子:        
public class rsbc {
    void method () {
        stringbuffer buffer = new stringbuffer(); // violation
        buffer.append ("hello");
    }
}    
更正:        
为stringbuffer提供寝大小。        
public class rsbc {
      private final int max = 100;
    void method () {
        stringbuffer buffer = new stringbuffer(max);
        buffer.append ("hello");
    } 
}
当你要创建一个比较大的hashMap时,充分利用另一个构造函数

public HashMap(int initialCapacity, float loadFactor)避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认initialCapacity只有16,而 loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。

 

6、单一对象转list
        FrameOu ou = new FrameOu();
        ou.setOuname("test");

        //一般我们会这样来写:       

        List<FrameOu> list = new ArrayList<FrameOu>();
        list.add(ou);
        BeanXmlUtil.beanListToXml(list);

        //其实我们一句话就搞定了:       

        BeanXmlUtil.beanListToXml(Arrays.asList(ou));

 

7、将try/catch块移出循环

把try/catch块放入循环体内,会极大的影响性能,如果编译jit被关闭或者你所使用的是一个不带jit的jvm,性能会将下降21%之多!
        
例子:        
import java.io.fileinputstream;
public class try {
    void method (fileinputstream fis) {
        for (int i = 0; i < size; i++) {
            try {                                      // violation
                _sum += fis.read();
            } catch (exception e) {}
        }
    }
    private int _sum;
}

        
更正:        
将try/catch块移出循环        
 
 void method (fileinputstream fis) {
        try {
            for (int i = 0; i < size; i++) {
                _sum += fis.read();
            }
        } catch (exception e) {}
    }

 

8、尽量使用final修饰符
带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如 java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高 50%。

简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”

例子:
class maf {
    public void setsize (int size) {
         _size = size;
    }
    private int _size;
}


更正:
class daf_fixed {
    final public void setsize (int size) {
         _size = size;
    }
    private int _size;
}

我们实体的get、set,action里面的基本都可以考虑加上final来提升效率

9、HaspMap的遍历

我们常常会这样来写:

Set<String> keys = map.keySet();
    for (String item : keys) {
        String value =  map.get(item) ;
   }
}

实际上更高效的应该是这样:
Map<String, String[]> paraMap = new HashMap<String, String[]>();
for( Entry<String, String[]> entry : paraMap.entrySet() )
{
    String appFieldDefId = entry.getKey();
    String[] values = entry.getValue();
}

 

10、在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。

 

11、StringBuffer,StringBuilder的抉择
区别在于:java.lang.StringBuffer 线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用 StringBuilder类,因为她支持所有相同的操作,但由于她不执行同步,所以速度更快。为了获得更好的性能,在构造StringBuffer或 StringBuilder时应尽量指定她的容量。当然如果不超过16个字符时就不用了。
相同情况下,使用StringBuilder比使用 StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer

12、避免在循环条件中使用复杂表达式

在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。
比如
for(int i=0;i<list.size();i++)

应修改为
for(int i=0,len=list.size();i<len;i++)

 

13、采用在需要的时候才开始创建的策略。
例如:
String str="abc";
if(i==1){ list.add(str);}

应修改为:
if(i==1){String str="abc"; list.add(str);}

 

14、io读取
之前解决过一个下载大文件很慢的问题,查看发现每次读取一个子节点,性能都消耗在循环上面了

            int ch = 0;
            while ((ch = fis.read()) != -1) {
                baos.write(ch);
            }

改成缓冲区读取后快了很多:

            byte[] buffer = new byte[1024 * 4];
            baos = new ByteArrayOutputStream();
            int ch = 0;
            while ((ch = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, ch);
            }

15、缓存中使用的同步集合

   当我们做数据本地缓存需要使用到集合的时候,推荐使用自带同步功能的ConcurrentHashMap和CopyOnWriteArrayList,虽然性能有所下降,但对于改动不是太频繁,而且并发安全来说,是最佳的选择。

性能优化方法论系列四性能优化的注意事项

性能优化方法论系列目录《一、性能优化的本质》《二、性能优化方法论的思想源泉》《三、性能优化的核心思想(1)》《三、性能优化的核心思想(2)》《三、性能优化的核心思想(3)》《四、性能优... 查看详情

性能优化简介

性能优化性能优化的重要性及方向优化方法性能优化的四个方向流畅性优化方向页面显示速度启动速度优化响应速度内存优化常见内存泄露原因优化内存空间稳定性优化流量优化安装包大小优化减少安装包大小的常用方案总结性... 查看详情

性能优化之java(android)代码优化

本文为Android性能优化的第三篇——Java(Android)代码优化。主要介绍Java代码中性能优化方式及网络优化,包括缓存、异步、延迟、数据存储、算法、JNI、逻辑等优化方式。(时间仓促,后面还会继续完善^_*)目前性能优化专题... 查看详情

性能优化方法论系列三性能优化的核心思想(代码片段)

性能优化方法论系列目录《一、性能优化的本质》《二、性能优化方法论的思想源泉》《三、性能优化的核心思想(1)》《三、性能优化的核心思想(2)》《三、性能优化的核心思想(3)》《四、性能优... 查看详情

性能优化之java(android)代码优化

性能优化之Java(Android)代码优化本文为Android性能优化的第三篇——Java(Android)代码优化。主要介绍Java代码中性能优化方式及网络优化,包括缓存、异步、延迟、数据存储、算法、JNI、逻辑等优化方式。(时间仓促,后面还会... 查看详情

性能优化方法论系列二性能优化方法论的思想源泉

性能优化方法论系列目录《一、性能优化的本质》《二、性能优化方法论的思想源泉》《三、性能优化的核心思想(1)》《三、性能优化的核心思想(2)》《三、性能优化的核心思想(3)》《四、性能优... 查看详情

性能优化方法论系列三性能优化的核心思想(代码片段)

性能优化方法论系列目录《一、性能优化的本质》《二、性能优化方法论的思想源泉》《三、性能优化的核心思想(1)》《三、性能优化的核心思想(2)》《三、性能优化的核心思想(3)》《四、性能优... 查看详情

性能优化方法论系列三性能优化的核心思想(代码片段)

性能优化方法论系列目录《一、性能优化的本质》《二、性能优化方法论的思想源泉》《三、性能优化的核心思想(1)》《三、性能优化的核心思想(2)》《三、性能优化的核心思想(3)》《四、性能优... 查看详情

优化性能和优化内存有啥区别?

优化内存。其实就是加内存。适合低配置的。优化系统性能的,说到底是没什么用的。参考技术A优化性能是对整个系统的优化,优化内存只针对内存使用的优化,因为现在内存白菜价,所以优化内存已经丧失了意义你的低配置... 查看详情

前端性能优化:jquery性能优化

...实有部分操作也是可以改进的。大部分情况下,封装的后性能是会降低的,如果发现很影响,就可以改为原生的。另外使用jQuery需要注意一下几点来提高性能:1不使用each,jQuery的each循环比原生的for循环性能相差几十倍。前端性... 查看详情

性能优化——存储性能优化

核心知识点:存储性能优化无非从磁盘类型、数据结构以及存储备份方式来进行,根据业务场景选择最合适的方案。1.机械vsSSD(磁盘类型)  a.机械:由于每次访问数据,都需要移动磁头臂,因此连续访问和随机访问性能差别... 查看详情

android性能优化——性能优化的难题总结

前言现在都在谈性能优化或者在面试的时候被问到性能优化相关问题,那么我们为什么要做性能优化呢?以及性能优化的难点是什么?在整个项目周期中不同的阶段该做什么?优化效果如何长期保持?作为一... 查看详情

android性能优化——性能优化的难题总结

前言现在都在谈性能优化或者在面试的时候被问到性能优化相关问题,那么我们为什么要做性能优化呢?以及性能优化的难点是什么?在整个项目周期中不同的阶段该做什么?优化效果如何长期保持?作为一... 查看详情

前端性能优化

1)性能优化指标2)性能优化工具3)性能优化法制4)HTTP协议头缓存5)资源按需加载6)不同网络类型的优化7)优化实战案例如今的前端开发已经从严重依赖后端演变成了node做中间层,MVVM框架进行服务端渲染做view层。性能优化也变得异常... 查看详情

性能优化指南:性能优化的一般性原则与方法

  作为一个程序员,性能优化是常有的事情,不管是桌面应用还是web应用,不管是前端还是后端,不管是单点应用还是分布式系统。本文从以下几个方面来思考这个问题:性能优化的一般性原则,性能优化的层次,性能优化的... 查看详情

前端性能优化jquery性能优化

...适的选择器$("#id");1.使用id来定位DOM元素无疑是最佳提高性能的方式,因为jQuery底层将直接调用本地方法document.getElementById();如果这个方式不能直接找到你需要的元素,那么你可以考虑调用find()方法,代码如下:$("#domo").find("div");... 查看详情

c++应用程序性能优化

C++应用程序性能优化C++应用程序性能优化系列博客主要依据《C++应用程序性能优化》(第2版)学习整理而来,同时参考部分网络博客。C++应用程序性能优化(一)——应用程序性能优化简介https://blog.51cto.com/9291927/2388608 查看详情

android性能优化--网络优化

网络优化维度网络优化工具网络流量消耗的精准获取 查看详情