我正在编程一个神经网络,在该网络中,我将权重数据保存在一个长的txt
文件中,因此为了检索数据,我使用"|"来分隔数字,然后在返回之前将其添加到数组中。
使用这种方法,我的内存使用量会达到1500
MB,直到整个程序结束才会消失,但如果没有它,我的ram使用量会到达700
。
我试着关闭所有的东西,也许以为我的一个对象是一个线程,但这也不起作用。我的代码中有什么东西可能导致这种内存使用吗
这是代码:
public static int[] findDoub(String fileName) {
ArrayList<Integer> innt = new ArrayList<Integer>();
try {
File file = new File(fileName);
FileInputStream strem = new FileInputStream(file);
BufferedInputStream buff = new BufferedInputStream(strem);
int index = buff.read();
StringBuilder doubus = new StringBuilder("");
for (int i = 0; index != -1; i++) {
char a = (char) index;
if (i > 0) {
if (a != '|') {
doubus.append(a);
} else {
innt.add(Integer.valueOf(doubus.toString()));
doubus = new StringBuilder("");
}
}
index = buff.read();
}
buff.close();
strem.close();
buff = null;
strem = null;
} catch (IOException e) {
e.printStackTrace();
}
Runtime.getRuntime().gc();
int[] innnt = new int[innt.size()];
for (int i = 0; i < innnt.length; i++) {
innnt[i] = innt.get(i);
}
return innnt;
}
有几个地方使用了过多的内存,但除了返回的int[]
之外,方法中的所有内容都是可垃圾收集的,因此您不应该有任何顾虑。
然而,如果你正在读取许多值,比如100000或更多,那么下面的建议将减少所需的内存占用。
在使用前预先设置ArrayList
的大小可避免在其增长时重新分配:
int initialSize = 100000;
ArrayList<Integer> innt = new ArrayList<>(initialSize);
避免每个解析的Integer
使用StringBuffer。由于int
具有最大长度,您可以用final char[] doubus
:替换
final char[] doubus = new char[Integer.toString(Integer.MAX_VALUE).length() + 2];
int dIndex = 0;
// ... Then append with:
if (a != '|') {
doubus[dIndex++] = a;
} else {
innt.add(Integer.valueOf(new String(doubus, 0, dIndex)));
dIndex=0;
}
将Integer.valueOf
与ArrayList<Integer>
一起使用意味着将许多int
值自动装箱为Integer,但最后提取为int
。将ArrayList
换成int[]
并使用Integer.parseInt
,因此结果始终是基元类型int
意味着避免了许多内存转换:
int [] innt = new int[initialSize];
int iIndex = 0;
// Replace add with:
innt[iIndex++] = Integer.parseInt(new String(doubus, 0, dIndex));
把这些放在一起,你应该有相同的输出,希望更少的内存流失:
public static int[] findDoub(File file) throws IOException {
int initialSize = 100000; // Use suitable value
int [] innt = new int[initialSize];
int iIndex = 0;
try (BufferedInputStream buff = new BufferedInputStream(new FileInputStream(file))) {
int index = buff.read();
final char[] doubus = new char[Integer.toString(Integer.MAX_VALUE).length() + 2];
int dIndex = 0;
for (int i = 0; index != -1; i++) {
char a = (char) index;
if (i > 0) {
if (a != '|') {
doubus[dIndex++] = a;
} else {
// Grow int[] if needed:
if (iIndex == innt.length) {
innt = Arrays.copyOf(innt, innt.length + initialSize);
}
innt[iIndex++] = Integer.parseInt(new String(doubus, 0, dIndex));
dIndex=0;
}
}
index = buff.read();
}
}
// Return exact size int[] of current length:
return Arrays.copyOf(innt, iIndex);
}
您读取所有要innt的文件,直到函数结束。然后你把它复制到innnt。
两者都会导致ram的使用。
ram的使用也取决于文件大小。
您不需要复制innt,只需返回arraylist,它将提高ram的使用率。
你可以尝试拆分文件。