gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 05:58:34 27 4
gpt4 key购买 nike

我正在使用外部排序和合并来对整数文件进行排序。通常,解决此问题的方法是使用 -Xmx 增加 JVM 的堆大小,但我想知道是否存在一种方法可以在不增加堆大小的情况下改进我的代码。

抛出错误的方法是 merge 方法。

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;
}
}
output.flush();
if(first_counter == mid) {
int no_of_ints_left = (end - second_counter)/4;

while(no_of_ints_left > 0){
x = input_a2.readInt();
output.writeInt(x);
no_of_ints_left--;
}

}
else {
int no_of_ints_left = (mid - first_counter)/4;
while(no_of_ints_left > 0){
x = input_a1.readInt();
output.writeInt(x);
no_of_ints_left--;
}
}
output.flush();
input_a1 = null;
input_a2 = null;
return;

}

导致 OutOfMemory 错误的行是 x = input_a1.readInt() 行,但我怀疑这就是错误的原因。我尝试在每次调用 merge() 后调用 System.gc(),但这并没有解决问题。我还可以通过哪些其他方法来优化该方法以使其使用更少的内存?

最佳答案

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

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

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

关于java - 外部排序在 readInt() 调用中给出 OutOfMemory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52688495/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com