Java性能优化之实战漫谈[1]

——I can feel the need, the need of speed...
——提前优化是万恶之源

最近由于工作的原因,对Java的性能优化比较关注,其间也看到不少比较好的文章系列,比如Program-Think同学的 Java性能优化系列 。平常工作的时候, 发现稍微有点好想法的时候,把自己独自一个人关在小屋子里集中精力思考,效果很不错,俗称“闭关”,大家也可以试一试。

谈到Java优化,我认为一切开始之前,最最重要的是找到一个合适的profile工具,这里有篇文章介绍的很详细:How to Fix Memory Leaks in Java,里面介绍了许多有用的profile工具,不用花太多时间,找到合适你自己的就行了,我用的是jprofile,感觉还不错。记住,重要的是,在每个优化开始之前,一定要用profile工具分析性能的问题出在哪边,千万不要想当然。

今天就先将两个简单的例子作为开头吧,大家轻松轻松。
例子一:
class A {
    int a_num;
    B b;
}
class B{
    int b_num;
    A a;
}

如果改成下面这样怎么样?

class AB { int a_num; int b_num; }

 

某些Java应用程序当对象太多而垃圾回收器还没有来得及回收的时候,就可能会导致堆内存溢出,其实内存溢出是分为栈内存溢出和堆内存溢出的,关于堆和栈的区别,可以参考program-think的这篇文章,讲的通俗易懂。关于上面的这个例子,就是我在实际编码中发现的一个造成内存消耗严重的一个问题,你或许还会认为上面那种写法更技术,更××。如果A的实例和B的实例个数很少的时候还好,但是如果他们的实例个数达到上百万的级别的时候,你就会思考一下是不是要换成下面这种写法了。首先你要了解怎么去计算一个对象会占多少字节的内存,然后思考为什么下面的写法会比上面的占用更少的内存?


例子二:
如果你用Java写程序,那么你会怎么样把一个数组objct_array:Object[]加到一个list:java.util.List中去?
我并不清楚你是怎么写的,不过我却见过一种非常常用的写法:
list.addAll(java.util.Arrays.asList(objct_array));

 

 

其实,如果不是在内核运算的地方,或者某个对性能要求很高的地方写这句话完全没有问题,但如果在某个关键的地方,比如在某个要调用极多次数的方法里写用这个方法,也许就会出现问题。在这种地方,最好还是不要偷懒,用最原始但很高效的数组来解决问题。

 

Object[] old_array = array;
array = new Object[old_array.length + new_array.length];
System.arraycopy(old_array, 0, array, 0, old_array.length);
System.arraycopy(new_array, 0, array, old_array.lengyh, new_array.length);

 

 

一个数组变成了一个list又变成一个数组又变成一个list,因为内部是这样实现的:

 

public static List asList(Object[] a) {
return new ArrayList(a);   // 新建了一个对象,同时数组变成一个list.
}
public boolean addAll(Collection c) {
Object[] a = c.toArray();       // 看这里, list又变成了一个数组,绕了一圈啊
int numNew = a.length;
ensureCapacity(size + numNew);  // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew); // 这个跟修改后做的差不多
size += numNew;
return numNew != 0;
}

 

 

结果证明:修改后这部分消耗的临时内存没有了,速度也变快了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值