我有近1,000,000条记录的数组,每条记录都有一个字段“filename”。
有许多记录具有完全相同的文件名。
我的目标是通过重复数据删除字符串实例(文件名实例,而不是记录)来改善内存占用。
.NET Framework 2.0是一种约束。这里没有LINQ。
我为重复数据删除写了一个通用(和线程安全)类:
public class Deduplication<T>
where T : class
{
private static Deduplication<T> _global = new Deduplication<T>();
public static Deduplication<T> Global
{
get { return _global; }
}
private Dictionary<T, T> _dic;// = new Dictionary<T, T>();
private object _dicLocker = new object();
public T GetInstance(T instance)
{
lock (_dicLocker)
{
if (_dic == null)
{
_dic = new Dictionary<T, T>();
}
T savedInstance;
if (_dic.TryGetValue(instance, out savedInstance))
{
return savedInstance;
}
else
{
_dic.Add(instance, instance);
return instance;
}
}
}
public void Clear()
{
lock (_dicLocker)
{
_dic = null;
}
}
}
这个类的问题在于它增加了更多的内存使用量,它会一直保留到下一个GC。
我正在寻找一种减少内存占用的方法,而无需增加更多的内存使用量,也无需等待下一代GC。此外,我不想使用GC.Collect()
,因为它会冻结GUI几秒钟。
答案 0 :(得分:1)
如果你不想实习你的琴弦。您可以采用类似的方法来处理Java 8的字符串重复数据删除(由堆上的GC完成)。
如果您有很多重复项,这会减少您的内存占用,但是实际上可能会执行得更好,因为它是在堆上的较低级别完成的。
答案 1 :(得分:0)
您可以将所有字符串粘贴在前缀树中。根据您的路径名称的不同,这应该自动重复删除常见的子串。谷歌的快速搜索产生于this C# implementation。
答案 2 :(得分:-1)
我建议您仔细检查您的内存占用情况是否已经过优化。 .NET会自动在堆上实现重复的字符串,这意味着您可以将多个相同的String
对象指向相同的内存地址。只需致电String.Intern(targetString)
即可。这就是为什么String
是不可变的,StringBuilder
存在。
更快的是,如果您在堆上的剩余字符串遇到问题,您可以在完成后立即启动垃圾收集(甚至在运行期间定期启动):
GC.Collect();