对于学校作业,我需要创建一个内存访问模拟。首先,我需要读取一个或多个跟踪文件。每个包含每次访问的内存地址。示例:
0 F001CBAD
2 EEECA89F
0 EBC17910
...
第一个整数表示读/写等,然后是十六进制存储器地址。有了这些数据,我应该进行模拟。所以我的想法是将这些数据解析为ArrayList<Trace>
(现在我正在使用Java),trace是一个包含内存地址和访问类型的简单类(只是一个字符串和一个整数)。之后我计划遍历这些数组列表来处理它们。
问题甚至在解析时,它耗尽了堆空间。每个跟踪文件大约200MB。我最多8个。意思是最小的~1.6 GB的数据我试图&#34;缓存&#34;?令我感到困惑的是,根据我的任务经理,我只解析了1个文件而java正在使用2GB ......
这样做的更好方法是什么?
可以在Code Review
找到代码段答案 0 :(得分:1)
The answer I gave on codereview is the same你应该在这里使用.....
但是,因为重复似乎没问题,我会在这里复制答案。
问题几乎可以肯定是Trace
类的结构,而且是内存效率。您应确保将instrType
和hexAddress
存储为内存有效结构。 instrType似乎是int
,这很好,但只要确保它在Trace类中声明为int
。
更可能的问题是hexAddress String的大小。你可能没有意识到这一点,但是Strings因“泄漏”记忆而臭名昭着。在这种情况下,你有一个line
并且你认为你只是从中获取hexString ......但实际上,hexString包含整行......是的,真的。例如,请查看以下代码:
public class SToken {
public static void main(String[] args) {
StringTokenizer tokenizer = new StringTokenizer("99 bottles of beer");
int instrType = Integer.parseInt(tokenizer.nextToken());
String hexAddr = tokenizer.nextToken();
System.out.println(instrType + hexAddr);
}
}
现在,设置一个断点(我使用eclipse)你的IDE,然后运行它,你会看到hexAddr包含整个行的char []数组,它的偏移量为3和a数为7。
由于String子串和其他构造的工作方式,它们可以为短字符串消耗大量内存......(理论上,内存与其他字符串共享)。因此,您实际上是将整个文件存储在内存中!!!!
至少应将代码更改为:
hexAddr = new String(tokenizer.nextToken().toCharArray());
但更好的是:
long hexAddr = parseHexAddress(tokenizer.nextToken());
答案 1 :(得分:1)
就像rolfl一样,我在code review回答了你的问题。对我来说,最大的问题是先将所有内容读入内存然后再处理。您需要读取固定金额,处理,然后重复直到完成。
答案 2 :(得分:0)
尝试使用课程java.nio.ByteBuffer
代替java.util.ArrayList<Trace>
。它还应该减少内存使用量。
class TraceList {
private ByteBuffer buffer;
public TraceList(){
//allocate byte buffer
}
public void put(byte operationType, int addres) {
//put data to byte buffer
}
public Trace get(int index) {
//get data from byte buffer by index
byte type = ...//read type
int addres = ...//read addres
return new Trace(type, addres)
}
}