Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】

        谈起java,给人的第一映像是什么?除了简单方便易上手,跨平台可移植,各种函数库支持类应有尽有不用重复造轮子这些特性之外,恐怕就是速度慢,占用内存高了吧。不可否认,java运行速度和内存占用方便确实无法比肩C/C++。随手举一个很直观的栗子,在ACM等其他算法竞赛中,普通给java的代码运行的时间往往都是C和C++  2~~3倍,由此可见一斑。不过我们今天要说的就是,算法效率一样的情况下,如何去优化java的速度,让他在提供编码方便的同时,速度和内存上比肩一般的C和C++。

     (/**博客记录了小菜寻找优化解法的过程 === 嫌拖拉的同学可以直接拉到最末看总结出的模板 */)

        为了方便直观对运行时间和占用内存有直观的感受,我们拿 hdu 2602这个题目举栗子。因为在OJ上能直接给出程序的运行时间和占用内存。 

        hdu 2602 是一个没有任何变化的经典01背包问题,对于01背包问题,一维的dp做法在算法上已经到极致不能再优化了(参考dd巨巨的背包九讲)。在大家算法效率都是一样的情况下,我们看看速度和内存占用有多大差别。(提交语言都是java的情况下)

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第1张图片

        最开始我连续提交了好几次,虽然AC了,但是代码运行内存开销始终在1万3千多k,我继续往后翻了一下java的提交记录

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第2张图片

        大都是在1万多k 以上,虽然这数字看着有点大,但是既然那么多人都是这么大的内存占用,那就应该是java本身的问题了。  ========我继续往后翻=========可是当我继续往后翻的时候,就感觉不对了,同样是java,同样的算法,怎么还能有这么不可思议,整整少了一个数量级的内存占用,整整快了一倍的速度

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第3张图片

        快个几十毫秒,内存多个几十几百k 还能理解,但是这不是一个几十几百k了,这是上万的差别了,同样是用java同样的算法(应该是),居然出现了上万的差别。这就让人不能忍受了。

        下面是我自己第一次提交的代码,用的是直观二维的做法。耗时468ms,占用内存24948k

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第4张图片

        在发现自己内存占用比人家高了那么多之后,我又换成一维的解法。 耗时546ms,占用内存 13908k。

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第5张图片

        速度还是不尽人意,我试着直接写在main 函数里面,省去函数调用看会不会快一点。这次是546ms, 13940k,并没有多大的变化。甚至还多了一点,我想应该是随机的吧。

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第6张图片

        后来丧心病狂的我又尝试把 i,j 还有数组的定义都放在循环外,然而时间还是微乎其微的变化,尝试着像以前一样固定数组,然和时间也还是没有变化。于是意识到这不是普通小优化能解决的了。

        ========================纠结纠结尝试中====================

        由于在hdu 上不能发邮件问别人代码怎么写的也看不到别人代码,只能靠自己一步步的摸索了。百度了好久也没找到可行的解决方案,最后还是上codeforces看的别人的模板才发现的。

来看一下效果吧,参看cf上排名第二的peter的java代码之后,Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第7张图片        运行时间降到了234ms,内存降到了 9588k

Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第8张图片

        可是9k多k 还是比人家2k多有很大的差距,继续在 cf上找代码尝试 ======>

        这次看的是排名第一的tourist巨巨的代码Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第9张图片,运行时间降到了 249ms,内存占用降到了7504k,与之前相比整整降低了一倍,下面给出代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

public class Main {

    static InputReader in;
    static PrintWriter out;

    public static void main(String[] args) throws IOException {
        in = new InputReader(System.in);
        out = new PrintWriter(System.out);
            
        int Case;
        Case = in.nextInt();
        //int i,j;
//        int []v = new int[1010];
//        int []w = new int[1010];            
//        int []m = new int[1010];
        while(Case-- > 0){
            int n,c;
            n = in.nextInt();
            c = in.nextInt();    
            int []v = new int[n];
            int []w = new int[n];            
            int []m = new int[c+1];
            for(int i=0;i=w[i];j--)   
                        m[j]=Math.max(m[j], m[j-w[i]]+v[i]);   
            }
            System.out.println(m[c]);
        }    
        out.close();
    }

    static class InputReader {
        BufferedReader br;

        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
        }

        public int nextInt() throws IOException {
            int c = br.read();
            while (c <= 32) {
                c = br.read();
            }
            boolean negative = false;
            if (c == '-') {
                negative = true;
                c = br.read();
            }
            int x = 0;
            while (c > 32) {
                x = x * 10 + c - '0';
                c = br.read();
            }
            return negative ? -x : x;
        }

        public long nextLong() throws IOException {
            int c = br.read();
            while (c <= 32) {
                c = br.read();
            }
            boolean negative = false;
            if (c == '-') {
                negative = true;
                c = br.read();
            }
            long x = 0;
            while (c > 32) {
                x = x * 10 + c - '0';
                c = br.read();
            }
            return negative ? -x : x;
        }

        public String next() throws IOException {
            int c = br.read();
            while (c <= 32) {
                c = br.read();
            }
            StringBuilder sb = new StringBuilder();
            while (c > 32) {
                sb.append((char) c);
                c = br.read();
            }
            return sb.toString();
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

        200多的速度和7000多的内存和极致的142ms度与2712的内存使用相比还有差距,不死心,还想继续降低下去来着,可是无奈cf上前面两页巨巨的java代码几乎都尝试过了一遍,还是没能降低下来,那就只好先暂时这样吧。更加好奇142ms 的极致速度是怎么出来的,真的堪比C/C++Java IO速度和占用内存的极致优化方法,模板方法【从hdu 2602 说起】_第10张图片

要是哪位亲有代码一定要贴出来学习一下啊.......

        下面给出IO读取加速的普遍模板

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.PrintWriter;  
import java.util.Scanner;  
  
public class Main {  
  
    static InputReader in;  
    static PrintWriter out;  
  
    public static void main(String[] args) throws IOException {  
        in = new InputReader(System.in);  
        out = new PrintWriter(System.out);  
        /*
         * 
         * 这里补充你的实际代码   读取输入采用   in.nextInt();的形式
         * 
         * */
        out.close();  
    }  
  
    static class InputReader {  
        BufferedReader br;  
  
        public InputReader(InputStream stream) {  
            br = new BufferedReader(new InputStreamReader(stream));  
        }  
  
        public int nextInt() throws IOException {  
            int c = br.read();  
            while (c <= 32) {  
                c = br.read();  
            }  
            boolean negative = false;  
            if (c == '-') {  
                negative = true;  
                c = br.read();  
            }  
            int x = 0;  
            while (c > 32) {  
                x = x * 10 + c - '0';  
                c = br.read();  
            }  
            return negative ? -x : x;  
        }  
  
        public long nextLong() throws IOException {  
            int c = br.read();  
            while (c <= 32) {  
                c = br.read();  
            }  
            boolean negative = false;  
            if (c == '-') {  
                negative = true;  
                c = br.read();  
            }  
            long x = 0;  
            while (c > 32) {  
                x = x * 10 + c - '0';  
                c = br.read();  
            }  
            return negative ? -x : x;  
        }  
  
        public String next() throws IOException {  
            int c = br.read();  
            while (c <= 32) {  
                c = br.read();  
            }  
            StringBuilder sb = new StringBuilder();  
            while (c > 32) {  
                sb.append((char) c);  
                c = br.read();  
            }  
            return sb.toString();  
        }  
  
        public double nextDouble() throws IOException {  
            return Double.parseDouble(next());  
        }  
    }  
}  



你可能感兴趣的:(java)