准备1千万个随机数字,保存到文件并顺序读取

来源:互联网 发布:ecshop大京东2.5源码 编辑:程序博客网 时间:2024/05/01 20:50
 今天花了些时间,想准备1千万条数据用于测试不同算法的排序性能。 刚开始的思路是:使用Apache的IOUtils操作文件,Apache的Common-lang中的StringUtils.join(int[], ",")将int[] 转换为string保存到文件。 读出数据,通过String.split(","),再转换为int[]。 想想就觉得别扭,转来转去的,特别是数据量大了,1千万条,极其耗CPU,速度不理想。 调优前: 1百万:保存需要260ms多,读取需要1s多。 1千万:保存需要6s多,读取需要14s多。 调优后: 1百万:保存需要50ms,读取需要50ms。 1千万:保存需要400ms多,读取需要4.2s多。 (读取慢,主要原因是初始堆内存太小-100m,几次垃圾回收就用掉了3s多) 调整jvm参数:-Xms4096m -Xmx4096m -Xmn2048m 1百万:保存需要50ms,读取需要50ms。 1千万:保存需要400ms多,读取需要200ms多。 3千万:保存需要1.5s多,读取需要530ms多。 5千万:保存需要2.6s多,读取需要870ms多。 1亿:保存需要5.3s多,读取时间长,不可接受。(上亿条之后,需要20*1亿,2G多的内存,超过虚拟机设置的新生代内存大小,所以爆慢,可以理解。不知道为什么不报OutOfMemory异常)。 1千万条数据内存占用分析。 数组需要连续的一大块内存,分配1千万条Integer(20),需要2亿byte,及200m连续内存。 在繁忙的系统中,这个是很困难的,可能造成系统瓶颈,甚至崩溃。 一个Integer对象,需要20字节保存,虽然一个int只占4字节 int[] datas占用200m,ByteBuffer.allocate(4*1千万)占40m。 Integer[]data占40m,一个引用4字节,存放了1千万个Integer引用。 所以,系统会使用300m左右的内存。再加上其他的开销,400m左右吧。

代码:

public static void saveHuge(String path, int len) {    File file = new File(path);    if (file.exists()) {        file.delete();    }    long start = System.currentTimeMillis();    try (FileOutputStream fos = new FileOutputStream(path); FileChannel fc = fos.getChannel();) {        ByteBuffer buff = ByteBuffer.allocate(4*len);        Random r = new Random();        for (int i=0; i<len; i++) {            buff.putInt(r.nextInt(MAX));        }        buff.flip();        fc.write(buff);    } catch (IOException e) {        e.printStackTrace();    }    long end = System.currentTimeMillis();    System.out.println("save() time used : " + (end - start) + " ms");}public static Integer[] readHuge(String path, int len) {    long start = System.currentTimeMillis();    Integer datas[] = new Integer[len];    try (FileInputStream fis = new FileInputStream(path);FileChannel fc = fis.getChannel();) {        ByteBuffer buff = ByteBuffer.allocate(4*len);        fc.read(buff);        buff.flip();        int i=0;        while (buff.remaining() > 0 && len-- > 0) {            datas[i] = buff.getInt();            i++;        }        buff.clear();    } catch (IOException e) {        e.printStackTrace();    }    long end = System.currentTimeMillis();    System.out.println("save() time used : " + (end - start) + " ms");    return datas;}
0 0
原创粉丝点击