免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: send_linux
打印 上一主题 下一主题

Java程序性能优化 ,您从何入手?(获奖名单已公布-2012-11-22) [复制链接]

论坛徽章:
0
31 [报告]
发表于 2012-10-28 10:51 |只看该作者
pitonas 发表于 2012-10-28 08:26
Java的性能不如人意


所以这不是需要优化吗?和C相比,可能是会稍微差点,但是这个也是要看情况的。Hadoop 也不是用java的嘛!这种云的东西都用java,所以也不会太离谱啦~

论坛徽章:
0
32 [报告]
发表于 2012-10-28 15:50 |只看该作者
内存溢出的问题,可以对tomcat进行监控:
一、gclog,这种方式用于观察内存回收情况,显示的内容如下所示:
211847: [GC 211847: [DefNew: 57509K->1728K(57664K), 0.0321256 secs] 281236K->225664K(523712K), 0.0322686 secs]
212394: [GC 212394: [DefNew: 57663K->1308K(57664K), 0.0330551 secs] 281600K->225730K(523712K), 0.0332203 secs]
212951: [GC 212951: [DefNew: 57244K->1469K(57664K), 0.0277455 secs] 281666K->225899K(523712K), 0.0278909 secs]
如何配置gc log,下面是几个常用的gclog的配置:
1、打开gclog,这个步骤是必须的:
JAVA_OPTS="$JAVA_OPTS -verbose:gc"
2、显示gclog中的时间戳,可选:
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCTimeStamps"
3、打印gclog的详细信息,可选:
JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails"
4、配置gclog的日志文件路径(路径为自定义),必选:
JAVA_OPTS="$JAVA_OPTS -Xloggc:/traindvb/dvbtrain/tomcat/gclogs/gc.log"
5、重启tomcat。
如何观察:
以下面这段为例:
212951: [GC 212951: [DefNew: 57244K->1469K(57664K), 0.0277455 secs] 281666K->225899K(523712K), 0.0278909 secs]
主要以两个箭头为参考(->)
第一个箭头:57244K->1469K,箭头指向的是新生段的内存占用情况;
第二个箭头:281666K->225899K,箭头指向的是回收后的内存占用情况。
圆括号中通常指的是当前申请的内存大小。
二、heap dump监测方法。这种方式用于抓取当时tomcat的运行的各模块的内存占用情况,显示的内容通常如下:
16400   [char   8192    "..............................................................."
24      .util.HashMap$Entry
56      java.net.URL
56      java.net.URL
32      sun.misc.URLClassPath$JarLoader
24      java.lang.String
24      java.lang.String
24      java.lang.String
24      java.lang.String
80      [java.util.HashMap$Entry
前面的数字表示占用的字节数。
如何配置:
1、将动态库libheapprofile.so,放到/usr/lib/目录下;
2、在catalina.sh文件中加入如下配置:
   JAVA_OPTS="$JAVA_OPTS -Xrunheapprofile"
3、重启tomcat即可。
如何观察:
当通过观察gclog,发现内存已经溢出或,内存占用已经超过正常值很多时(
以现网环境为例:日常占用在600-700M,较高时会在1500M左右,通常页面上只要能够正常使用,内存还是正常的,
但是如果内存达到1800M-2000M,则视为已经溢出),执行kill -3 [java pid]。
此时(有可能要等1-2分钟),会在$TOMCAT_HOME/bin下生成一个heap.dump文件,这个文件通常要过10分钟左右
才能完全生成(判断是否已经生成的办法是,观察这个文件的大小是否还在改变,如果大小停止变化了,则说明已经生
成好了)。
文件生成后,用 cut -f 2 <heap.dump | sort -n | uniq -c | sort -n 对该文件进行分析,统计内存中各个类的数量。

论坛徽章:
27
CU大牛徽章
日期:2013-03-13 15:15:08CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大牛徽章
日期:2013-09-18 15:24:25CU大牛徽章
日期:2013-09-18 15:24:31CU大牛徽章
日期:2013-09-18 15:24:36CU大牛徽章
日期:2013-09-18 15:24:41CU大牛徽章
日期:2013-09-18 15:24:48CU大牛徽章
日期:2013-09-18 15:24:52处女座
日期:2013-09-27 17:45:43
33 [报告]
发表于 2012-10-28 23:30 |只看该作者
1.Java中字符串分割的性能讨论
答:若是分隔的逻辑很简单并且数据量很大的话,我会采用stringbuffer+加charAt进行分割,分割后产生一个记录位置的数组,这样既减少占用内存又节省时间;
     若是一般性的话使用split进行分隔
     可以考虑使用java调用c程序进行分割



2. 如果程序性能不如人意,如何找到代码中的性能瓶颈
答:1)查找字符串比较次数比较多的地方,若是比较次数超过1000次,建议使用hashMap来替换
  1. /**
  2.          * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害,在switch最好把出现次数最多的判断放在最前面
  3.          * @author yifangyou
  4.          * @since 2011-08-16 09:35:00
  5.          */
  6.         public static void test5() {
  7.                 HashMap<String, Integer> types = new HashMap<String, Integer>() {
  8.                         {
  9.                                 int i = 0;
  10.                                 this.put("a", i++);
  11.                                 this.put("b", i++);
  12.                                 this.put("c", i++);
  13.                                 this.put("d", i++);
  14.                                 this.put("e", i++);
  15.                         }
  16.                 };
  17.                 String a = "e";
  18.                 int b = 0;
  19.                 long startTime;
  20.                 startTime = new Date().getTime();
  21.                 for (int i = 0; i < 10000000; i++) {
  22.                         if ("a".equals(a)) {
  23.                                 b = 0;
  24.                         } else if ("b".equals(a)) {
  25.                                 b = 1;
  26.                         } else if ("c".equals(a)) {
  27.                                 b = 2;
  28.                         } else if ("d".equals(a)) {
  29.                                 b = 3;
  30.                         } else if ("e".equals(a)) {
  31.                                 b = 4;
  32.                         }
  33.                 }
  34.                 System.out.println(new Date().getTime() - startTime);

  35.                 startTime = new Date().getTime();
  36.                 for (int i = 0; i < 10000000; i++) {
  37.                         b = types.get(a);
  38.                 }
  39.                 System.out.println(new Date().getTime() - startTime);
  40.                 int c = 14;//改为0的话则最快
  41.                 startTime = new Date().getTime();
  42.                 for (int i = 0; i < 10000000; i++) {
  43.                         switch (c) {
  44.                         case 0:
  45.                                 break;
  46.                         case 1:
  47.                                 break;
  48.                         case 2:
  49.                                 break;
  50.                         case 3:
  51.                                 break;
  52.                         case 4:
  53.                                 break;
  54.                         case 5:
  55.                                 break;
  56.                         case 6:
  57.                                 break;
  58.                         case 7:
  59.                                 break;
  60.                         case 8:
  61.                                 break;
  62.                         case 9:
  63.                                 break;
  64.                         case 10:
  65.                                 break;
  66.                         case 11:
  67.                                 break;
  68.                         case 12:
  69.                                 break;
  70.                         case 13:
  71.                                 break;
  72.                         case 14:
  73.                                 break;
  74.                         default:
  75.                                 break;
  76.                         }
  77.                 }

  78.                 System.out.println(new Date().getTime() - startTime);
  79.         }
复制代码
2)输入和输出(I/O),避免多次读写同一个文件,读时最好尽量一次读取完需要的数据,
                   写时,先把要写的内容全部放到变量里,一次写入文件
     3)对于数据库或者网络通信最好重用连接,不要每次查询都连接一次,可以采用连接池

3. 如果系统频繁发生Out of Memory异常,该如何分析和解决问题
1)查看一下java虚拟机申请的内存是不是太少
2)检查代码中循环次数最多的地方,最好使用stringbuffer代替string对字符串进行操作
3)  检查数据库查询的地方是否释放结果集,可以把大量的插入操作改为一次次操作,减少占用内存
4)  不要把大量数据存放在静态变量里


4、您在Java程序开发和调优中用到的一些有用的技巧
下面的代码是我做的性能测试代码,大家可以参考一下,有什么不对的请指教

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.Comparator;
  4. import java.util.Date;
  5. import java.util.HashMap;
  6. import java.util.Iterator;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import java.util.StringTokenizer;

  10. public class Test {

  11.         public static void main(String argv[]) {
  12.                
  13.                 /*
  14.                  * 避免在循环条件中使用复杂表达式
  15.                  * @author yifangyou
  16.              * @since 2011-08-16 09:35:00
  17.                  *
  18.                  */
  19. //                test0();
  20.                 /*
  21.                  * 如果只是查找单个字符的话,用charAt()代替startsWith()
  22.                  * @author yifangyou
  23.          * @since 2011-08-16 09:35:00
  24.                  */
  25. //                test1();


  26.                 /*
  27.                  * 能够使用移位的乘除,最好用移位
  28.                  * @author yifangyou
  29.          * @since 2011-08-16 09:35:00
  30.                  */
  31. //                 test2();

  32.                 /*
  33.                  * 只有一个字符的字符串拼接,用''代替""
  34.                  * @author yifangyou
  35.          * @since 2011-08-16 09:35:00
  36.                  */
  37. //                 test3();

  38.                 /**
  39.                  * try catch最好不要放在循环里
  40.                  * @author yifangyou
  41.          * @since 2011-08-16 09:35:00
  42.                  */
  43. //                 test4();

  44.                 /**
  45.                  * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害
  46.                  * @author yifangyou
  47.          * @since 2011-08-16 09:35:00
  48.                  */
  49. //                test5();

  50.                 /*
  51.                  * 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省时间
  52.                  * @author yifangyou
  53.          * @since 2011-08-16 09:35:00
  54.                  */
  55. //                test6();
  56.                 /*
  57.                  * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
  58.                  * 字符串的分析在很多应用中都是常见的。使用indexOf
  59.                  * ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
  60.                  * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
  61.                  * @author yifangyou
  62.          * @since 2011-08-16 09:35:00
  63.                  */
  64. //                 test7();

  65.                 /*
  66.                  * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
  67.                  * @author yifangyou
  68.          * @since 2011-08-16 09:35:00
  69.                  */
  70. //                 test8();
  71.                 /*
  72.                  * 确定 StringBuffer的容量
  73.                  * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小
  74.                  * ,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
  75.                  * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
  76.                  * @author yifangyou
  77.          * @since 2011-08-16 09:35:00
  78.                  */
  79. //                 test9();
  80.                 /*
  81.                  * 尽可能的使用栈变量
  82.                  *
  83.                  * 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
  84.                  * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
  85.                  * @author yifangyou
  86.          * @since 2011-08-16 09:35:00
  87.                  */
  88. //                test10();
  89.                 /**
  90.                  * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
  91.                  * @author yifangyou
  92.          * @since 2011-08-16 09:35:00
  93.                  */
  94.                
  95. //                copyArray();
  96.                 /*
  97.                  * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
  98.                  * @author yifangyou
  99.          * @since 2011-08-16 09:35:00
  100.                  */
  101. //                copyArrayList();
  102.                 /*
  103.                  * 复制Map最好用逐个复制最快,putAll最简单
  104.                  * @author yifangyou
  105.          * @since 2011-08-16 09:35:00
  106.                  */
  107.                 copyMap();

  108.        
  109.         }

  110.         int localN = 0;
  111.         static int staticN = 0;

  112.         /*
  113.          * 避免在循环条件中使用复杂表达式
  114.          * @author yifangyou
  115.          * @since 2011-08-16 09:35:00
  116.          */
  117.         public static void test0() {
  118.                 ArrayList<Integer> a = new ArrayList<Integer>();

  119.                 for (int i = 0; i < 10000000; i++) {
  120.                         a.add(i);
  121.                 }

  122.                 long startTime;
  123.                 // 循环条件中使用复杂表达式
  124.                 startTime = new Date().getTime();
  125.                 for (int i = 0; i < a.size(); i++) {
  126.                         int j = a.get(i);
  127.                 }
  128.                 System.out.println(new Date().getTime() - startTime);

  129.                 // 循环条件中不使用复杂表达式
  130.                 startTime = new Date().getTime();
  131.                 for (int i = 0, maxlen = a.size(); i < maxlen; i++) {
  132.                         int j = a.get(i);
  133.                 }
  134.                 System.out.println(new Date().getTime() - startTime);
  135.         }

  136.         /*
  137.          * 如果只是查找单个字符的话,用charAt()代替startsWith()
  138.          * @author yifangyou
  139.          * @since 2011-08-16 09:35:00
  140.          */
  141.         public static void test1() {
  142.                 String s = "sdfsdfsdfsdfdssssssssssssssssssssssssssssdfffffffffffffffa";
  143.                 long startTime;
  144.                 // startsWith
  145.                 startTime = new Date().getTime();
  146.                 for (int i = 0; i < 10000000; i++) {
  147.                         if (s.startsWith("a")) {

  148.                         }
  149.                 }
  150.                 System.out.println(new Date().getTime() - startTime);
  151.                 // charAt
  152.                 startTime = new Date().getTime();
  153.                 for (int i = 0; i < 10000000; i++) {
  154.                         if (s.charAt(0) == 'a') {

  155.                         }
  156.                 }
  157.                 System.out.println(new Date().getTime() - startTime);
  158.                
  159.                 // charAt
  160.                 startTime = new Date().getTime();
  161.                 for (int i = 0; i < 10000000; i++) {
  162.                         if ("ab".equals("abcdssdds".substring(0, 2))) {

  163.                         }
  164.                 }
  165.                 System.out.println(new Date().getTime() - startTime);

  166.         }

  167.         /*
  168.          * 能够使用移位的乘除,最好用移位
  169.          * @author yifangyou
  170.          * @since 2011-08-16 09:35:00
  171.          */
  172.         public static void test2() {
  173.                 long startTime;
  174.                 int a;
  175.                 //
  176.                 startTime = new Date().getTime();

  177.                 for (int i = 0; i < 10000000; i++) {
  178.                         a = 333333333 / 8;
  179.                 }
  180.                 System.out.println(new Date().getTime() - startTime);
  181.                 // charAt
  182.                 startTime = new Date().getTime();
  183.                 for (int i = 0; i < 10000000; i++) {
  184.                         a = 333333333 >> 3;
  185.                 }
  186.                 System.out.println(new Date().getTime() - startTime);
  187.         }

  188.         /*
  189.          * 只有一个字符的字符串拼接,用''代替""
  190.          * @author yifangyou
  191.          * @since 2011-08-16 09:35:00
  192.          */
  193.         public static void test3() {
  194.                 long startTime;

  195.                 startTime = new Date().getTime();
  196.                 String s = "123";
  197.                 for (int i = 0; i < 10000000; i++) {
  198.                         String a = s + "d";
  199.                 }
  200.                 System.out.println(new Date().getTime() - startTime);
  201.                 // charAt
  202.                 startTime = new Date().getTime();
  203.                 for (int i = 0; i < 10000000; i++) {
  204.                         String a = s + 'd';
  205.                 }
  206.                 System.out.println(new Date().getTime() - startTime);
  207.         }

  208.         /**
  209.          * try catch最好不要放在循环里
  210.          * @author yifangyou
  211.          * @since 2011-08-16 09:35:00
  212.          */
  213.         public static void test4() {
  214.                 long startTime;
  215.                 startTime = new Date().getTime();
  216.                 for (int i = 0; i < 10000000; i++) {
  217.                         try {
  218.                                 int a = Integer.parseInt("1");
  219.                         } catch (Exception e) {

  220.                         }
  221.                 }
  222.                 System.out.println(new Date().getTime() - startTime);

  223.                 startTime = new Date().getTime();
  224.                 try {
  225.                         for (int i = 0; i < 10000000; i++) {
  226.                                 int a = Integer.parseInt("1");
  227.                         }
  228.                 } catch (Exception e) {

  229.                 }

  230.                 System.out.println(new Date().getTime() - startTime);
  231.                 int a=1;
  232.                 startTime = new Date().getTime();
  233.                 for (int i = 0; i < 10000000; i++) {
  234.                         if("sdffffffffffffffffffffffffffffffff".contains("a")){
  235.                                 a = 0;
  236.                         }else{
  237.                                 a = 1;
  238.                         }
  239.                 }
  240.                 System.out.println(new Date().getTime() - startTime);

  241.                 startTime = new Date().getTime();

  242.                
  243.                 if("sdffffffffffffffffffffffffffffffff".contains("a")){
  244.                         for (int i = 0; i < 10000000; i++) {
  245.                                 a = 0;
  246.                         }
  247.                 }else{
  248.                         for (int i = 0; i < 10000000; i++) {
  249.                                 a = 1;
  250.                         }
  251.                 }
  252.                 System.out.println(new Date().getTime() - startTime);
  253.                
  254.         }

  255.         /**
  256.          * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害,在switch最好把出现次数最多的判断放在最前面
  257.          * @author yifangyou
  258.          * @since 2011-08-16 09:35:00
  259.          */
  260.         public static void test5() {
  261.                 HashMap<String, Integer> types = new HashMap<String, Integer>() {
  262.                         {
  263.                                 int i = 0;
  264.                                 this.put("a", i++);
  265.                                 this.put("b", i++);
  266.                                 this.put("c", i++);
  267.                                 this.put("d", i++);
  268.                                 this.put("e", i++);
  269.                         }
  270.                 };
  271.                 String a = "e";
  272.                 int b = 0;
  273.                 long startTime;
  274.                 startTime = new Date().getTime();
  275.                 for (int i = 0; i < 10000000; i++) {
  276.                         if ("a".equals(a)) {
  277.                                 b = 0;
  278.                         } else if ("b".equals(a)) {
  279.                                 b = 1;
  280.                         } else if ("c".equals(a)) {
  281.                                 b = 2;
  282.                         } else if ("d".equals(a)) {
  283.                                 b = 3;
  284.                         } else if ("e".equals(a)) {
  285.                                 b = 4;
  286.                         }
  287.                 }
  288.                 System.out.println(new Date().getTime() - startTime);

  289.                 startTime = new Date().getTime();
  290.                 for (int i = 0; i < 10000000; i++) {
  291.                         b = types.get(a);
  292.                 }
  293.                 System.out.println(new Date().getTime() - startTime);
  294.                 int c = 14;//改为0的话则最快
  295.                 startTime = new Date().getTime();
  296.                 for (int i = 0; i < 10000000; i++) {
  297.                         switch (c) {
  298.                         case 0:
  299.                                 break;
  300.                         case 1:
  301.                                 break;
  302.                         case 2:
  303.                                 break;
  304.                         case 3:
  305.                                 break;
  306.                         case 4:
  307.                                 break;
  308.                         case 5:
  309.                                 break;
  310.                         case 6:
  311.                                 break;
  312.                         case 7:
  313.                                 break;
  314.                         case 8:
  315.                                 break;
  316.                         case 9:
  317.                                 break;
  318.                         case 10:
  319.                                 break;
  320.                         case 11:
  321.                                 break;
  322.                         case 12:
  323.                                 break;
  324.                         case 13:
  325.                                 break;
  326.                         case 14:
  327.                                 break;
  328.                         default:
  329.                                 break;
  330.                         }
  331.                 }

  332.                 System.out.println(new Date().getTime() - startTime);
  333.         }

  334.         /*
  335.          * 对于常量字符串,用'StringBuffer' 代替 'String' ,节省空间,节省一半时间
  336.          * @author yifangyou
  337.          * @since 2011-08-16 09:35:00
  338.          */
  339.         public static void test6() {
  340.                 StringBuffer s = new StringBuffer("Hello");
  341.                 int maxlen=1000000;
  342.                 long startTime;
  343.                 startTime = new Date().getTime();
  344.                 for (int i = 0; i < maxlen; i++) {
  345.                         String t =new String("Hello ") + "World!";
  346.                 }
  347.                 System.out.println(new Date().getTime() - startTime);
  348.                
  349.                 startTime = new Date().getTime();
  350.                 for (int i = 0; i < maxlen; i++) {
  351.                         StringBuffer t =new StringBuffer("Hello ").append("World!");
  352.                 }
  353.                 System.out.println(new Date().getTime() - startTime);
  354.         }

  355.         /*
  356.          * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
  357.          * 字符串的分析在很多应用中都是常见的。使用indexOf
  358.          * ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
  359.          * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
  360.          * @author yifangyou
  361.          * @since 2011-08-16 09:35:00
  362.          */
  363.         public static void test7() {
  364.                 String domain = "www.a.com.";
  365.                 long startTime;
  366.                 startTime = new Date().getTime();

  367.                 for (int i = 0; i < 100000; i++) {
  368.                         int index = 0;
  369.                         while ((index = domain.indexOf(".", index + 1)) != -1) {
  370.                                 domain.substring(index + 1, domain.length());
  371.                                 // System.out.println(domain.substring(index+1,
  372.                                 // domain.length()));
  373.                         }
  374.                 }
  375.                 System.out.println(new Date().getTime() - startTime);
  376.                 startTime = new Date().getTime();
  377.                 for (int i = 0; i < 100000; i++) {
  378.                         StringTokenizer st = new StringTokenizer(domain, ".");
  379.                         while (st.hasMoreTokens()) {
  380.                                 st.nextToken();
  381.                                 // System.out.println(st.nextToken());
  382.                         }
  383.                 }
  384.                 System.out.println(new Date().getTime() - startTime);
  385.         }

  386.         /*
  387.          * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
  388.          * @author yifangyou
  389.          * @since 2011-08-16 09:35:00
  390.          */
  391.         public static void test8() {
  392.                 ArrayList<Integer> a = new ArrayList<Integer>();
  393.                 int maxlen = 10000000;
  394.                 for (int i = 0; i < maxlen; i++) {
  395.                         a.add(i);
  396.                 }
  397.                 long startTime;
  398.                 startTime = new Date().getTime();
  399.                 for (int i = 0; i < maxlen; i++) {
  400.                         Object o = new Object();
  401.                         o = a.get(i);
  402.                 }
  403.                 System.out.println(new Date().getTime() - startTime);
  404.                 Object o = new Object();
  405.                 startTime = new Date().getTime();
  406.                 for (int i = 0; i < maxlen; i++) {
  407.                         o = a.get(i);
  408.                 }
  409.                 System.out.println(new Date().getTime() - startTime);
  410.         }

  411.         /*
  412.          * 确定 StringBuffer的容量
  413.          * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存
  414.          * ,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
  415.          * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
  416.          * @author yifangyou
  417.          * @since 2011-08-16 09:35:00
  418.          */
  419.         public static void test9() {
  420.                 int maxlen = 1000000;
  421.                 long startTime;
  422.                 startTime = new Date().getTime();
  423.                 for (int i = 0; i < maxlen; i++) {
  424.                         StringBuffer buffer = new StringBuffer(); // violation
  425.                         buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  426.                 }
  427.                 System.out.println(new Date().getTime() - startTime);
  428.                 startTime = new Date().getTime();
  429.                 for (int i = 0; i < maxlen; i++) {
  430.                         StringBuffer buffer = new StringBuffer(128); // violation
  431.                         buffer.append("hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  432.                 }
  433.                 System.out.println(new Date().getTime() - startTime);
  434.         }

  435.         /*
  436.          * 尽可能的使用栈变量 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
  437.          * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
  438.          * @author yifangyou
  439.          * @since 2011-08-16 09:35:00
  440.          */
  441.         public static void test10() {
  442.                 int maxlen = 100000000;
  443.                 long startTime;
  444.                 int n = 0;
  445.                 Test test = new Test();
  446.                 // 局部变量
  447.                 startTime = new Date().getTime();
  448.                 for (int i = 0; i < maxlen; i++) {
  449.                         n = i;
  450.                 }
  451.                 System.out.println(new Date().getTime() - startTime);
  452.                 // 类变量
  453.                 startTime = new Date().getTime();
  454.                 for (int i = 0; i < maxlen; i++) {
  455.                         test.localN = i;
  456.                 }
  457.                 System.out.println(new Date().getTime() - startTime);

  458.                 // 静态变量
  459.                 startTime = new Date().getTime();
  460.                 for (int i = 0; i < maxlen; i++) {
  461.                         Test.staticN = i;
  462.                 }
  463.                 System.out.println(new Date().getTime() - startTime);
  464.         }
  465. //       
  466. //        /*1.尽量使用final修饰符。
  467. //带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
  468. //         */
  469. //        public static void test11() {
  470. //                int maxlen = 10000000;
  471. //                long startTime;
  472. //                int n = 0;
  473. //               
  474. //                // 普通类
  475. //                startTime = new Date().getTime();
  476. //                A a = new A();
  477. //                for (int i = 0; i < maxlen; i++) {
  478. //                        a.inc();
  479. //                }
  480. //                System.out.println(new Date().getTime() - startTime);
  481. //               
  482. //                // final类
  483. //                startTime = new Date().getTime();
  484. //                FinalA finalA = new FinalA();
  485. //                for (int i = 0; i < maxlen; i++) {
  486. //                        finalA.inc();
  487. //                }
  488. //                System.out.println(new Date().getTime() - startTime);
  489. //        }

  490.         /**
  491.          * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
  492.          * @author yifangyou
  493.          * @since 2011-08-16 09:35:00
  494.          */
  495.         static void copyArray() {
  496.                 int[] array1 = new int[10000000];
  497.                 int[] array2 = new int[10000000];
  498.                 for (int i = 0, maxlen = array1.length; i < maxlen; i++) {
  499.                         array1[i] = i;
  500.                 }

  501.                 long startTime;
  502.                 // 逐个复制,最慢
  503.                 startTime = new Date().getTime();

  504.                 for (int i = 0, maxlen = array2.length; i < maxlen; i++) {
  505.                         array2[i] = array1[i]; // Violation
  506.                 }
  507.                 System.out.println(new Date().getTime() - startTime);

  508.                 // 批量复制,最快
  509.                 startTime = new Date().getTime();
  510.                 System.arraycopy(array1, 0, array2, 0, 10000);
  511.                 System.out.println(new Date().getTime() - startTime);

  512.         }

  513.         /*
  514.          * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
  515.          * @author yifangyou
  516.          * @since 2011-08-16 09:35:00
  517.          */
  518.         static void copyArrayList() {
  519.                 int maxlen = 1000000;
  520.                 ArrayList<Integer> array1 = new ArrayList<Integer>();
  521.                 ArrayList<Integer> array2 = new ArrayList<Integer>();
  522.                 ArrayList<Integer> array3 = new ArrayList<Integer>();
  523.                 ArrayList<Integer> array4;
  524.                 for (int i = 0; i < maxlen; i++) {
  525.                         array1.add(i);
  526.                 }

  527.                 long startTime;
  528.                 // 逐个复制,最慢
  529.                 startTime = new Date().getTime();

  530.                 for (int i = 0; i < maxlen; i++) {
  531.                         array2.add(array1.get(i)); // Violation
  532.                 }
  533.                 System.out.println(new Date().getTime() - startTime);

  534.                 // 批量复制,最快
  535.                 startTime = new Date().getTime();
  536.                 array3.addAll(array1);
  537.                 System.out.println(new Date().getTime() - startTime);

  538.                 // 克隆,次快
  539.                 startTime = new Date().getTime();
  540.                 array4 = (ArrayList<Integer>) array1.clone();
  541.                 System.out.println(new Date().getTime() - startTime);
  542.                 array4.set(0, 4);
  543.                 System.out.println("array1[0]=" + array1.get(0));
  544.                 System.out.println("array4[0]=" + array4.get(0));

  545.         }

  546.         /*
  547.          * 复制Map最好用逐个复制最快,putAll最简单
  548.          * @author yifangyou
  549.          * @since 2011-08-16 09:35:00
  550.          */
  551.         static void copyMap() {
  552.                 int maxlen = 1000000;
  553.                 Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
  554.                 Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
  555.                 Map<Integer, Integer> map3 = new HashMap<Integer, Integer>();
  556.                 Map<Integer, Integer> map4 = new HashMap<Integer, Integer>();
  557.                 for (int i = 0; i < maxlen; i++) {
  558.                         map1.put(i, i);
  559.                 }
  560.                 long startTime;
  561.                 // 逐个复制,最快
  562.                 startTime = new Date().getTime();
  563.                 Set<Integer> key = map1.keySet();
  564.                 for (Iterator it = key.iterator(); it.hasNext();) {
  565.                         Integer k = (Integer) it.next();
  566.                         map2.put(k, map1.get(k));
  567.                 }
  568.                 System.out.println(new Date().getTime() - startTime);

  569.                 // 批量复制,最慢
  570.                 startTime = new Date().getTime();
  571.                 map3.putAll(map1);
  572.                 System.out.println(new Date().getTime() - startTime);
  573.                 System.out.println("map2[9999]=" + map2.get(9999));
  574.                 System.out.println("map3[9999]=" + map3.get(9999));

  575.                 // 逐个复制,次快
  576.                 startTime = new Date().getTime();
  577.                 Set<Map.Entry<Integer, Integer>> set = map1.entrySet();
  578.                 for (Iterator<Map.Entry<Integer, Integer>> it = set.iterator(); it
  579.                                 .hasNext();) {
  580.                         Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>) it
  581.                                         .next();
  582.                         map4.put(entry.getKey(), entry.getValue());
  583.                 }
  584.                 System.out.println(new Date().getTime() - startTime);

  585.         }

  586. }
复制代码

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
34 [报告]
发表于 2012-10-28 23:42 |只看该作者
yifangyou 发表于 2012-10-28 23:30
1.Java中字符串分割的性能讨论
答:若是分隔的逻辑很简单并且数据量很大的话,我会采用stringbuffer+加cha ...


这么晚还在啊,感谢分享咯

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:56:11
35 [报告]
发表于 2012-10-29 09:37 |只看该作者
Java优化感觉要靠 jvm

论坛徽章:
27
CU大牛徽章
日期:2013-03-13 15:15:08CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大牛徽章
日期:2013-09-18 15:24:25CU大牛徽章
日期:2013-09-18 15:24:31CU大牛徽章
日期:2013-09-18 15:24:36CU大牛徽章
日期:2013-09-18 15:24:41CU大牛徽章
日期:2013-09-18 15:24:48CU大牛徽章
日期:2013-09-18 15:24:52处女座
日期:2013-09-27 17:45:43
36 [报告]
发表于 2012-10-29 09:37 |只看该作者
回复 34# send_linux
最近这个月加班都挺晚的{:3_196:} ,每天上CU都是晚上十点以后了

   

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
37 [报告]
发表于 2012-10-29 10:19 |只看该作者
yifangyou 发表于 2012-10-29 09:37
回复 34# send_linux
最近这个月加班都挺晚的 ,每天上CU都是晚上十点以后了


身体重要啊,呵呵,看你的微博,去参加了云技术架构峰会,现场如何?干货多不?

论坛徽章:
6
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:582015年辞旧岁徽章
日期:2015-03-03 16:54:15
38 [报告]
发表于 2012-10-29 15:27 |只看该作者
我觉得jvm优化只是治标而已, 还是用profiler找出代码缺陷比较靠谱点

论坛徽章:
0
39 [报告]
发表于 2012-10-29 16:58 |只看该作者
不错!不错!不错!

论坛徽章:
0
40 [报告]
发表于 2012-10-29 19:37 |只看该作者
回复 32# sinxadmin


    恩恩。学习了。这些JVM参数,在书里都有说明。不明白的可以看看~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP