1

假设我们有一个结构体,它有一个名为 idx 的 int 字段。我有这个结构的列表,我需要生成一个不在这个列表中的索引。最直接的保留是:gen idx keep { it not in mylist.idx; };

问题是如果 mylist 很长,那么 mylist.idx 我们会返回一个大列表。我宁愿这样做: gen idx keep { not mylist.has(it.idx == it); };

有没有其他方法可以做到这一点,具有更好的内存性能?

4

1 回答 1

3

实际上,当 list.field 返回一个新列表时,并且重复执行此操作时,可以分配大量内存。

减轻痛苦的一种方法是使用辅助列表来避免使用“mylist.idx”和分配新列表。

这样,如果您的原始代码是

<'  
struct A {
  idx:int;  
};
extend sys  {
    run() is also  {
        var mylist: list of A;
        var idx:int;
        for i from 0 to 10000 {
            gen idx keeping {it not in mylist.idx};
            mylist.add(new A with {.idx = idx;});
        };
    };
};
'>

峰值进程大小:969MB

您可以添加一个辅助列表:

<'
struct A {
  idx:int;  
};
extend sys  {
    run() is also  {
        var mylist: list of A;
        var l : list of int;
        var idx:int;
        for i from 0 to 10000 {
            gen idx keeping {it not in l};
            mylist.add(new A with {.idx = idx;});
            l.add(idx);
        };
    };
};
'>

峰值进程大小:736MB

但是,从 Specman 12.2 开始,您可以将“set”类型与辅助变量一起使用,这在生成时更有效。

<'
struct A {
  idx:int;  
};
extend sys  {
    run() is also  {
        var mylist: list of A;
        var S:set;
        var idx:int;
        for i from 0 to 10000 {
            gen idx keeping {it not in value(S)};
            mylist.add(new A with {.idx = idx;});
            S = S.union([idx]);
        };
    };
};
'>

峰值进程大小:135MB

于 2014-05-20T09:20:23.697 回答