为了账号安全,请及时绑定邮箱和手机立即绑定

外部排序在 readInt() 调用中给出 OutOfMemory

外部排序在 readInt() 调用中给出 OutOfMemory

扬帆大鱼 2021-11-03 15:06:04
我正在使用带有合并的外部排序来对整数文件进行排序。通常对此的解决方案是使用 -Xmx 增加 JVM 的堆大小,但我想知道是否有一种方法可以在不增加堆大小的情况下改进我的代码。抛出错误的方法是合并方法。public static void merge(RandomAccessFile a1, RandomAccessFile a2, RandomAccessFile b1,DataOutputStream output, int start, int end) throws FileNotFoundException, IOException {    //a1: file being read from    //b1: file being written to    if((int)a1.length() == 0) {        return;    }    DataInputStream input_a1 = new DataInputStream(            new BufferedInputStream(new FileInputStream(a1.getFD())));    DataInputStream input_a2 = new DataInputStream(            new BufferedInputStream(new FileInputStream(a2.getFD())));    b1.seek(start); //set output pointer to start    int mid = (start + end) /2;    int file_length = (int)a1.length();    //basically if second block is empty so just copy    if (end > file_length) {        end = file_length;        if (end <= mid) {            //copy from start to EOF            int no_of_ints_left = (file_length - start)/4;            for(int i = 1; i <= no_of_ints_left; i++) {                output.writeInt(input_a1.readInt());            }            output.flush();            return;        }    }    int first_counter = start;    int second_counter = mid;    int x;    int y;    while(first_counter < mid && second_counter < end) {        input_a1.mark(first_counter);        input_a2.mark(second_counter);        x = input_a1.readInt();        y = input_a2.readInt();        if(x < y) {            output.writeInt(x);            input_a2.reset();            first_counter += 4;        }        else {            output.writeInt(y);            input_a1.reset();            second_counter += 4;        }    }导致 OutOfMemory 错误的行是 x = input_a1.readInt() 行,但我怀疑这是错误的原因。我尝试在每次调用 merge() 后调用 System.gc(),但这并没有解决问题。我还有哪些其他方法可以优化该方法以减少内存使用量?
查看完整描述

1 回答

?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

mark用于缓冲流的代码。这将需要整个标记部分都在内存中,这可能是您的问题。

RandomAccessFile可能是获得相同功能但将数据保留在磁盘上的最简单方法。内存映射java.nio是一种更复杂的技术 - 在 32 位机器上仍然会遇到问题。但是,我猜您仍然可能会遇到大文件的严重性能问题。

(堆栈跟踪对于准确查看分配失败的内容很有用。可能重新分配缓冲区。尽管分析堆会告诉您实际占用内存的内容。)


查看完整回答
反对 回复 2021-11-03
  • 1 回答
  • 0 关注
  • 138 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信