我正在考虑减少像集合对象这样的表的内存消耗。
给出类似
的类结构Class Cell
{
public property int Data;
public property string Format;
}
Class Table
{
public property Dictionary<Position, Cell> Cells;
}
当存在大量单元格时,Cell类的Data属性可以是可变的,但Format属性可以重复多次,例如,标题单元格可以具有标题的空格式字符串,数据单元格可以都是“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="" /
&GT;
<item romFrom=2 rowTo=1000 format="0.00" /
&GT;
答案 0 :(得分:5)
对于弦乐,你或许可以看看实习生;或者使用内置的interner,或者(最好)自定义interner - 基本上是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
进一步。
请注意,不需要更改设计 - 只需更改填充对象的代码即可使用内部/缓存。
答案 1 :(得分:4)
您是否确实确定这是否确实存在问题? CLR代表你做了很多string interning因此有可能(取决于CLR版本以及编译代码的方式)你没有使用你认为的那么多的内存。
我强烈建议您在更改设计之前验证对内存利用率的怀疑。
答案 2 :(得分:0)
正如其他人所说,在改变你的设计之前,你首先要看看这是否是一个问题。如果这是一个问题和/或你处理大量的稀疏数据,那么稀疏的数据结构可能更适用于问题。我稍后会发布一个非常简单的天真实现(因为我现在还不能)但是二维稀疏矩阵可以做你想要的。
概念是将为给定的单元格范围存储单个格式(字符串或类),例如1-1000。要从中受益,您必须进行一些设计更改...需要从单元类中删除format属性。相反,格式应该在表类中注册,或者最好在另一个类中注册。例如
public class CellFormats
{ ....
public void Register(int start, int finish, string format);
}
单元格格式类将包含稀疏矩阵,该矩阵将包含范围的格式。
Table类将使用CellFormats类。它没有一个名为GetCellFormat的方法,而是有一个带有以下签名的方法
void ApplyCellFormat(Position cellPosition)
这将从CellFormats类(稀疏矩阵)中检索单元格格式并将其应用于单元格。
如果数据很常见并应用于大范围,此技术可以大大减少内存使用量。但正如我已经说过的那样,在通过添加这样的代码使设计更复杂之前,你需要确保这是问题的原因。