减少类似对象的内存
我正在寻找减少类似集合对象的表的内存消耗。减少类似对象的内存
给定一个类结构类似
Class Cell
{
public property int Data;
public property string Format;
}
Class Table
{
public property Dictionary<Position, Cell> Cells;
}
当有大量的细胞的细胞类的数据属性可以是可变的,但格式属性可被重复多次,例如标题单元可能具有用于标题的空格式字符串,并且数据单元可能都是“0.00”。
一个想法是像下面
Class Cell
{
public property int Data;
public property int FormatId;
}
Class Table
{
public property Dictionary<Position, Cell> Cells;
private property Dictionary<Position, string> Formats;
public string GetCellFormat(Position);
}
这对字符串但是FormatId整数值仍然会被重复多次将节省内存。
有没有比这更好的实现?我已经看过flyweight模式,但我不确定它是否与此匹配。
我正在考虑的一个更复杂的实现是从Cell类中删除Format属性,而将格式存储在将相邻单元格分组在一起的字典
可能有2项这样<item rowFrom=1 rowTo=1 format="" /
><item romFrom=2 rowTo=1000 format="0.00" /
>
对于字符串,你也许可以看看实习;无论是内置的内部人员还是(最好是)定制的内部人员 - 基本上都是Dictionary<string,string>
。这意味着每个相同的字符串使用相同的参考 - 并且可以收集重复项。
不要对int进行任何操作;那已经是最佳了。
例如:
using System;
using System.Collections.Generic;
class StringInterner {
private readonly Dictionary<string, string> lookup
= new Dictionary<string, string>();
public string this[string value] {
get {
if(value == null) return null;
if(value == "") return string.Empty;
string result;
lock (lookup) { // remove if not needed to be thread-safe
if (!lookup.TryGetValue(value, out result)) {
lookup.Add(value, value);
result = value;
}
}
return result;
}
}
public void Clear() {
lock (lookup) { lookup.Clear(); }
}
}
static class Program {
static void Main() {
// this line is to defeat the inbuilt compiler interner
char[] test = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' };
string a = new string(test), b = new string(test);
Console.WriteLine(ReferenceEquals(a, b)); // false
StringInterner cache = new StringInterner();
string c = cache[a], d = cache[b];
Console.WriteLine(ReferenceEquals(c, d)); // true
}
}
如果需要,您可以借此进一步与WeakReference
。
请注意,您的不需要更改您的设计 - 您只需更改填充对象以使用interner/cache的代码。
你真的确定这是否实际上是一个问题? CLR为你做了很多string interning,所以它可能(取决于CLR版本以及你的代码是如何编译的)你没有使用尽可能多的内存。
我强烈建议您在更改设计之前验证您对内存使用情况的怀疑。
谢谢,我不知道。开始的例子是对已经存在的设计进行简化,这种设计占用了大量的内存,我假设了许多字符串要贡献。很难准确地确定内存的位置...... – 2009-11-13 06:53:29
正如其他人所说的,你首先要在改变你的设计之前看看这是否是一个问题。如果这是一个问题和/或你处理大量稀疏数据,那么稀疏数据结构可能更适用于问题。稍后我会发布一个非常简单的朴素实现(因为我目前无法做到),但是二维稀疏矩阵可以满足您的要求。
这个概念是为给定单元格范围存储单个格式(字符串或类),例如, 1-1000。为了从中受益,您必须进行一些设计更改......格式属性将需要从单元类中删除。相反,格式应该在表格类中注册,或者最好与其他类一起注册。例如,
public class CellFormats
{ ....
public void Register(int start, int finish, string format);
}
单元格格式类将包含稀疏矩阵,它将包含范围的格式。
Table类将使用CellFormats类。相反,有一个名为GetCellFormat方法,它必须具有以下签名
void ApplyCellFormat(Position cellPosition)
这将检索来自CellFormats类(稀疏矩阵)单元格格式的方法,并将其应用到单元。
如果数据很常见并应用于大范围,此技术可以显着减少内存使用量。但正如我已经说过的,您需要确保这是问题的原因,然后才能通过添加这样的代码来使设计更复杂。
+1尼斯例:) – 2009-11-13 06:42:30
谢谢。我想我需要确定CLR是否已经为我做了这个。 – 2009-11-13 06:57:07
该文档指定分配给CLR实例字符串的内存在CLR本身终止之前不可能被释放。这就是为什么你更喜欢定制的内部人员? – 2009-11-13 07:05:33