锁定老帖子 主题:关于性能优化
精华帖 (2) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2010-11-17
最后修改:2010-11-17
ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 String str ="aaa" + "bbb" +"ccc" + "ddd"; StringBuilder sb = new StringBuilder(); sb.append("aaa"); sb.append("bbb"); sb.append("ccc"); sb.append("ddd"); String str = sb.toString(); 哪种效率高? 答案是第一种. 对于新手来说想优化很容易适得其反. 反编译看一下就知道为什么了. 我们项目经理不让用第一种 |
|
返回顶楼 | |
发表时间:2010-11-17
ironsabre 写道 flysnowxf 写道 ironsabre 写道 flysnowxf 写道 汗,这是很基础的概念了。
百度百科:http://baike.baidu.com/view/714962.htm 引用 当以前分配的一片内存不再需要使用或无法访问时,但是却并没有释放它,那么对于该进程来说,会因此导致总可用内存的减少,这时就出现了内存泄漏。 再说一次,向集合里一直加东西不删除,这个不叫内存泄漏。 那是你的理解了。我的理解是,分配了内存,但这些内存不再被使用,比如过期了、没用了,但又没有去删除,造成内存占用越来越多。HashMap的使用就容易出现这个问题。 哎。你这个没过期,也有用。你可以通过HashMap取出来值的,这怎么能叫泄漏呢? 我现在总是你,如果你向cache里放了100个对象,永远keep住,如果我应用程序经常来访问它,叫不叫泄漏? 如果我应用程序再也不来访问它,叫不叫泄漏? 按你的理解,第一种不叫,第二种叫。可这两种没有区别。我不可能用由第三方来判断我自己是不是泄漏,明白吗? 下面这个Stack,在被别人用的时候,可能会引起泄漏。你先找找看哪行会出总是。然后再理解一下跟你这个有什么区别。 import java.util.Arrays; import java.util.EmptyStackException; public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly doubling the capacity * each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } 你这个封装Object[]的Stack跟封装HashMap的Cache有什么区别? 内存泄漏是指存在无法释放的无用引用,从这点来说,HashMap里面的内容也是内存泄漏。 |
|
返回顶楼 | |
发表时间:2010-11-17
bitray 写道 赞成2楼和三楼的观点。虽然可能平时大家注意的并不是真正的性能瓶颈。但是如果不重视自己代码的书写规范和简洁,那么写出来的代码就是隐藏的瓶颈,是你最后很难优化出来的东西。有习惯的程序员用stringbuffer和stringbuilder,但是如果是不重视,就会有人用+连接,在多处,一定数据量的情况下,都可能产生隐含问题等
jdk6的字符串拼接内部是用Stringbuilder实现的,现在在sb上纠缠是不明智的。大多情况下+的性能比StringBuilder高 |
|
返回顶楼 | |
发表时间:2010-11-17
抛出异常的爱 写道 kingkan 写道 在下的一点愚见:性能优化在于平时开发习惯的积累,新手因为知识深度面的缺乏而想不到程序高效的写法很正常,老手开发一般写出来的代码都是比较高效的,所以在开发过程中对于过于考虑性能优化是没多大必要,关键是开发前考虑的吞吐量,系统框架在I/O上瓶颈,还有热路径等,进入开发后就是代码工作啦,测试,Beta,Release,上线,维护。
不要犯错就差不多了 设计的好就不太需要考虑优化的事. 必竟j2ee又不是c 我平时很少进行coding时考虑性能问题. 呵呵,老手一般在潜意识里面已经coding优化了,写出来的代码通常都没问题,剩下就交给QA吧 |
|
返回顶楼 | |
发表时间:2010-11-17
蔡华江 写道 ironsabre 写道 flysnowxf 写道 ironsabre 写道 flysnowxf 写道 汗,这是很基础的概念了。
百度百科:http://baike.baidu.com/view/714962.htm 引用 当以前分配的一片内存不再需要使用或无法访问时,但是却并没有释放它,那么对于该进程来说,会因此导致总可用内存的减少,这时就出现了内存泄漏。 再说一次,向集合里一直加东西不删除,这个不叫内存泄漏。 那是你的理解了。我的理解是,分配了内存,但这些内存不再被使用,比如过期了、没用了,但又没有去删除,造成内存占用越来越多。HashMap的使用就容易出现这个问题。 哎。你这个没过期,也有用。你可以通过HashMap取出来值的,这怎么能叫泄漏呢? 我现在总是你,如果你向cache里放了100个对象,永远keep住,如果我应用程序经常来访问它,叫不叫泄漏? 如果我应用程序再也不来访问它,叫不叫泄漏? 按你的理解,第一种不叫,第二种叫。可这两种没有区别。我不可能用由第三方来判断我自己是不是泄漏,明白吗? 下面这个Stack,在被别人用的时候,可能会引起泄漏。你先找找看哪行会出总是。然后再理解一下跟你这个有什么区别。 import java.util.Arrays; import java.util.EmptyStackException; public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly doubling the capacity * each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } 你这个封装Object[]的Stack跟封装HashMap的Cache有什么区别? 内存泄漏是指存在无法释放的无用引用,从这点来说,HashMap里面的内容也是内存泄漏。 HashMap里的内容你仍然可以自由的存取的,这不叫泄漏,你觉得内存不够用了,你可以去删除掉一些。这完全可以自己控制的,这叫什么泄漏??那按你这个说法,只要向容器里放对象就是泄漏了?? 我们现在再看这个Stack类,我把这个Stack类打成一个jar包,然后我提供给你用,你用上面这个Stack作为你的容器,你push一万次,再pop一万次,你的Stack的size已经是0了,但是这一万个对象仍然无法放掉(前提当然是Stack本身要被keep住)。你会有一些内存你已经永远无法使用了,而且你已经没有任何能力去放掉它了(不包括回收到Stack本身)。 看得懂区别了吗?? |
|
返回顶楼 | |
发表时间:2010-11-17
ironsabre 写道 蔡华江 写道 ironsabre 写道 flysnowxf 写道 ironsabre 写道 flysnowxf 写道 汗,这是很基础的概念了。
百度百科:http://baike.baidu.com/view/714962.htm 引用 当以前分配的一片内存不再需要使用或无法访问时,但是却并没有释放它,那么对于该进程来说,会因此导致总可用内存的减少,这时就出现了内存泄漏。 再说一次,向集合里一直加东西不删除,这个不叫内存泄漏。 那是你的理解了。我的理解是,分配了内存,但这些内存不再被使用,比如过期了、没用了,但又没有去删除,造成内存占用越来越多。HashMap的使用就容易出现这个问题。 哎。你这个没过期,也有用。你可以通过HashMap取出来值的,这怎么能叫泄漏呢? 我现在总是你,如果你向cache里放了100个对象,永远keep住,如果我应用程序经常来访问它,叫不叫泄漏? 如果我应用程序再也不来访问它,叫不叫泄漏? 按你的理解,第一种不叫,第二种叫。可这两种没有区别。我不可能用由第三方来判断我自己是不是泄漏,明白吗? 下面这个Stack,在被别人用的时候,可能会引起泄漏。你先找找看哪行会出总是。然后再理解一下跟你这个有什么区别。 import java.util.Arrays; import java.util.EmptyStackException; public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly doubling the capacity * each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } 你这个封装Object[]的Stack跟封装HashMap的Cache有什么区别? 内存泄漏是指存在无法释放的无用引用,从这点来说,HashMap里面的内容也是内存泄漏。 HashMap里的内容你仍然可以自由的存取的,这不叫泄漏,你觉得内存不够用了,你可以去删除掉一些。这完全可以自己控制的,这叫什么泄漏??那按你这个说法,只要向容器里放对象就是泄漏了?? 我们现在再看这个Stack类,我把这个Stack类打成一个jar包,然后我提供给你用,你用上面这个Stack作为你的容器,你push一万次,再pop一万次,你的Stack的size已经是0了,但是这一万个对象仍然无法放掉(前提当然是Stack本身要被keep住)。你会有一些内存你已经永远无法使用了,而且你已经没有任何能力去放掉它了(不包括回收到Stack本身)。 看得懂区别了吗?? 是你没看懂我的意思。我指的是“封装了HashMap"的Cache。 你如果能拿到Stack中Object[]的引用,你一样可以对数组进行操作。 如果你拿不到HashMap的引用,你一样无法对数组进行操作。 所以问题并不是hashMap本身。 其次,就算你能拿到HashMap本身,我也认为这是内存泄漏。请注意,"内存泄漏是指存在无法释放的无用引用"。 Java最大特色在于内存的自动释放。 Object a = new Object(); 。。。 a = null; 显然,a是释放了的,至少程序员的本意是要释放a的,但是由于集合中保存了另一个a的引用(这个总是很隐蔽的),导致a的内存并没有释放,这不是溢出,这是泄漏。 |
|
返回顶楼 | |
发表时间:2010-11-17
象string和stringbuffer这些应该是养成一个编程习惯,单纯的String str = "a"+"b"+"c"换成stringbuffer意义也不大,但是如果通过一个循环来拼一个string,那stringbuffer还有点作用(有两年多没用java了,新的java1.6有没有优化就不清楚了)。其实性能问题更多的是由设计引起的,比如要获取一个列表的记录总数怎样实现(select count(0) from tablename吗?)、怎样实现翻页这些都会存在性能问题。 如果从纯技术角度,那优化DB的回报是最高的,比如对查询语句建索引(建索引提升一两个数量级的速度是很正常的)。一般的性能问题通常发生在DB服务器,应用服务器只要不内存泄漏的话,一般不会有什么太大问题的。
|
|
返回顶楼 | |
发表时间:2010-11-17
dsjt 写道 ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 String str ="aaa" + "bbb" +"ccc" + "ddd"; StringBuilder sb = new StringBuilder(); sb.append("aaa"); sb.append("bbb"); sb.append("ccc"); sb.append("ddd"); String str = sb.toString(); 哪种效率高? 答案是第一种. 对于新手来说想优化很容易适得其反. 反编译看一下就知道为什么了. 我们项目经理不让用第一种 如果你们的JDK版本在1.4或以下的话还说得过去. 如果是1.5或以上. 你完全可以和他提出来.你写一段测试代码给他看.执行效率有很明显的对比 反编译Class给他看.JDK已经做好优化了.自己的优化不仅多余,反而降低了执行效率 |
|
返回顶楼 | |
发表时间:2010-11-17
指尖帝 写道 bitray 写道 赞成2楼和三楼的观点。虽然可能平时大家注意的并不是真正的性能瓶颈。但是如果不重视自己代码的书写规范和简洁,那么写出来的代码就是隐藏的瓶颈,是你最后很难优化出来的东西。有习惯的程序员用stringbuffer和stringbuilder,但是如果是不重视,就会有人用+连接,在多处,一定数据量的情况下,都可能产生隐含问题等
jdk6的字符串拼接内部是用Stringbuilder实现的,现在在sb上纠缠是不明智的。大多情况下+的性能比StringBuilder高 +1 尤其是字符串常量拼接+的性能要大大好于StringBuilder |
|
返回顶楼 | |
发表时间:2010-11-17
指尖帝 写道 bitray 写道 赞成2楼和三楼的观点。虽然可能平时大家注意的并不是真正的性能瓶颈。但是如果不重视自己代码的书写规范和简洁,那么写出来的代码就是隐藏的瓶颈,是你最后很难优化出来的东西。有习惯的程序员用stringbuffer和stringbuilder,但是如果是不重视,就会有人用+连接,在多处,一定数据量的情况下,都可能产生隐含问题等
jdk6的字符串拼接内部是用Stringbuilder实现的,现在在sb上纠缠是不明智的。大多情况下+的性能比StringBuilder高 变量拼接还是很有问题的。JDK 1.6下。 testString cost =453 mils testStringBuilder cost =0 mils public static void main(String[] args) { long t1 = System.currentTimeMillis(); String str1 = ""; for (int i = 0; i < 20000; i++) { str1 = str1 + "a"; } long t2 = System.currentTimeMillis(); System.out.println("testString cost =" + (t2 - t1) + " mils"); StringBuilder sb = new StringBuilder(""); long t3 = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { sb.append("a"); } long t4 = System.currentTimeMillis(); System.out.println("testStringBuilder cost =" + (t4 - t3) + " mils"); } |
|
返回顶楼 | |