0

对于学校作业,我需要为内存访问创建一个模拟。首先,我需要阅读 1 个或多个跟踪文件。每个都包含每次访问的内存地址。例子:

0 F001CBAD
2 EEECA89F
0 EBC17910
...

其中第一个整数表示读/写等,然后是十六进制内存地址。有了这些数据,我应该运行一个模拟。所以我的想法是将这些数据解析成一个ArrayList<Trace>(现在我正在使用 Java),其中 trace 是一个简单的类,包含内存地址和访问类型(只是一个字符串和一个整数)。之后我计划遍历这些数组列表来处理它们。

问题甚至在解析时,堆空间用完了。每个跟踪文件约为 200MB。我最多有 8 个。这意味着我要“缓存”的数据至少为 ~1.6 GB?令我困惑的是,我只解析 1 个文件,而根据我的任务管理器,java 正在使用 2GB ...

有什么更好的方法来做到这一点?

可以在Code Review中找到代码片段

4

3 回答 3

1

我在 codereview 上给出的答案与您应该在这里使用的答案相同.....

但是,因为重复似乎没问题,所以我将在这里复制答案。


几乎可以肯定,问题在于您的Trace班级结构,以及内存效率。您应该确保instrTypehexAddress存储为内存高效结构。instrType 似乎是 an int,这很好,但只需确保它int在 Trace 类中声明为 an 。

更可能的问题是 hexAddress 字符串的大小。您可能没有意识到,但字符串因“泄漏”内存而臭名昭著。在这种情况下,您有 aline并且您认为您只是从中获取 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,计数为 7 .

由于字符串子字符串和其他构造的工作方式,它们可以为短字符串消耗大量内存......(理论上内存与其他字符串共享)。结果,您实际上是将整个文件存储在内存中!!!!

至少,您应该将代码更改为:

hexAddr = new String(tokenizer.nextToken().toCharArray());

但更好的是:

long hexAddr = parseHexAddress(tokenizer.nextToken());
于 2013-11-07T12:44:03.090 回答
1

像 rolfl 我在代码审查中回答了你的问题。对我来说,最大的问题是先将所有内容读入内存,然后再进行处理。你需要阅读一个固定的数量,处理它,然后重复直到完成。

于 2013-11-07T13:07:48.800 回答
0

尝试使用 classjava.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)
    }

}
于 2013-11-07T13:00:03.867 回答