锁定老帖子 主题:关于性能优化
精华帖 (2) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2010-11-17
ironsabre 写道 哎。你这个没过期,也有用。你可以通过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); } } effective java中的这段代码,也不一定就有内存泄露。比如push elements[3]=e1,然后pop elements[3],e1已经被栈弹出,不过还是被引用着,等下次push elements[3]=e2的时候,e1就没有被引用了,可以被回收。 不管是程序不能访问,还是你自己认为是过期了,这部分数据归根结底都是垃圾数据,占着茅坑不拉屎,不删除了还留着干吗?难道等内存占了4g、8g的,老板问了,怎么这么大,你难道还解释说,这些数据还可以被访问的。。。 |
|
返回顶楼 | |
发表时间:2010-11-17
应该是常量直接相加,在编译期得到了优化处理,属于语法糖,所以看来性能很好。
但是对于变量相加,就编译期无能为力,现了原型了。性能差到不行。 |
|
返回顶楼 | |
发表时间:2010-11-17
最后修改:2010-11-17
蔡华江 写道 这个测试用例是错误的,因为String a = "a"+"a"就是String a = "aa"; 但是String a = b + c 就不一样了。 ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 我说明了是字符串常量拼接.请看清楚再回答 aladdin181 写道 千万别用 "AAAA"+"BBBB"这样的东西来验证它的性能,那是最不能看出结果的。
恰恰是项目中有很多诸如此类的字符串常量拼接代码. StringBuilder sql = new StringBuilder(); sql.append(" select a.col1,a.col2,a.col3 "); sql.append(" from tablea a ,tableb b "); sql.append(" where a.col1 = b.col1 "); 字符串常量拼接正确的做法是 String sql = " select a.col1,a.col2,a.col3 " + " from tablea a ,tableb b " + " where a.col1 = b.col1 "; |
|
返回顶楼 | |
发表时间:2010-11-17
最后修改:2010-11-17
ironsabre 写道 现在设我是被Cache住的一个小对象,我就是这个对象,那么我的身份怎么定义?
A) 我是一个Cache住的有用的对象,我能提高访问效率。 B) 我是一个被泄漏掉的垃圾,我是垃圾。 我是A还是B,谁说了算,按什么标准执行? 因为程序是你自己写的,你当然知道哪些数据是垃圾数据。比如用户session放在cache里边,用户再一次登录,以前这个session就完全没有用了。如果不去清除,很明显的结果是内存会被占光。 |
|
返回顶楼 | |
发表时间:2010-11-17
effective java中的这段代码,也不一定就有内存泄露。比如push elements[3]=e1,然后pop elements[3],e1已经被栈弹出,不过还是被引用着,等下次push elements[3]=e2的时候,e1就没有被引用了,可以被回收。
不管是程序不能访问,还是你自己认为是过期了,这部分数据归根结底都是垃圾数据,占着茅坑不拉屎,不删除了还留着干吗?难道等内存占了4g、8g的,老板问了,怎么这么大,你难道还解释说,这些数据还可以被访问的。。。 ----------------------------------------------- 需要分清我能删除还是我已经无法删除。 如果JDK里给你的Stack就是effective java里的这段,那么你在用的时候,你对很多已经垃圾了的对象是无能为力的,你很无助,你什么都做不了。我认为这种才算泄漏了。 而如果你用的是一个功能正常的HashMap,你是可以去删除你不想要的东西的。 这两种完全不一样。一种你能,一种你不能。 我希望你回答这个问题: 现在设我是被Cache住的一个小对象,我就是这个对象,那么我的身份怎么定义? A) 我是一个Cache住的有用的对象,我能提高访问效率。 B) 我是一个被泄漏掉的垃圾,我是垃圾。 我是A还是B,谁说了算,按什么标准执行? |
|
返回顶楼 | |
发表时间:2010-11-17
ouchxp 写道 蔡华江 写道 这个测试用例是错误的,因为String a = "a"+"a"就是String a = "aa"; 但是String a = b + c 就不一样了。 ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 我说明了是字符串常量拼接.请看清楚再回答 aladdin181 写道 千万别用 "AAAA"+"BBBB"这样的东西来验证它的性能,那是最不能看出结果的。
恰恰是项目中有很多诸如此类的字符串常量拼接代码. StringBuilder sql = new StringBuilder(); sql.append(" select a.col1,a.col2,a.col3 "); sql.append(" from tablea a ,tableb b "); sql.append(" where a.col1 = b.col1 "); 字符串常量拼接正确的做法是 String sql = " select a.col1,a.col2,a.col3 " + " from tablea a ,tableb b " + " where a.col1 = b.col1 "; 请不要用appand进行拼接有限行数据. 不易读. sql这东西占不了多少内存. 不需要节约. |
|
返回顶楼 | |
发表时间:2010-11-17
不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
|
|
返回顶楼 | |
发表时间:2010-11-17
抛出异常的爱 写道 ouchxp 写道 蔡华江 写道 这个测试用例是错误的,因为String a = "a"+"a"就是String a = "aa"; 但是String a = b + c 就不一样了。 ouchxp 写道 JDK自己已经有优化了. 不合理的优化反而会降低效率 比如字符串常量拼接 我说明了是字符串常量拼接.请看清楚再回答 aladdin181 写道 千万别用 "AAAA"+"BBBB"这样的东西来验证它的性能,那是最不能看出结果的。
恰恰是项目中有很多诸如此类的字符串常量拼接代码. StringBuilder sql = new StringBuilder(); sql.append(" select a.col1,a.col2,a.col3 "); sql.append(" from tablea a ,tableb b "); sql.append(" where a.col1 = b.col1 "); 字符串常量拼接正确的做法是 String sql = " select a.col1,a.col2,a.col3 " + " from tablea a ,tableb b " + " where a.col1 = b.col1 "; 请不要用appand进行拼接有限行数据. 不易读. sql这东西占不了多少内存. 不需要节约. 额...我只是拿SQL举个例子. 项目中见到这样的代码太多了..... |
|
返回顶楼 | |
发表时间:2010-11-17
ironsabre 写道 不能用内存占了4g、8g的来认定里边的对象是不是垃圾,我如果一个超级缓存系统,我可能需要Cache住100g的对象,那又怎么样,我们是垃圾吗?我们不是,我们是有用的。
抛出异常的爱 写道 ouchxp 写道 kyh23_y 写道 既然那些对象我一直在用,那为什么会被叫做是泄露?难道我用那100个对象也有错? 应该是当我没用那所有对象,或者是某些对象的时候,又没有在Map里面remove掉那些对象,导致了map一直持有引用,根据gc的原理,这样的对象是不会被回收的,这样才造成了泄露吧.这是我的理解 存在对象不代表正在使用. 已经不需要再使用的对象,但没有清除掉引用.仍然是内存泄露. 在Java中内存泄露的概念与C++不同.因为Java有自动的垃圾回收. 所以很少会有C++中的已无引用但是内存未释放的问题. Java中的内存泄露一般指未清除的引用导致的不能释放. 所以C++的内存泄露(狭义)和Java的内存泄露(广义),这个概念是不同的. j2ee会把一所有的垃圾数据放到 大胃王 数据库中 所以不必保持大多数数据. 有些数据需要保持的比如自写的cache 删除条件很简单, 比如内存不够用了.... 但你什么时间进行扫描是否够用 怎么样扫描内存总量 怎么样在多线程下锁 怎么样决定哪个元素是可以被 清掉的. 哪个元素是过期的 最重要的是以上操作怎么样让这一个周期时间缩短到下一个周期启动之前完成. 以上过程有有非常大的可能会出现内存泄露.. |
|
返回顶楼 | |
发表时间:2010-11-17
考量性能 拿字符串常量拼接本身是没有意义的,大家通常做法常量直接是+的,所以拿常量来说是一点意义都没有。
|
|
返回顶楼 | |