减少类似对象的记忆

Chr*_*ing 4 c# performance design-patterns

我正在考虑减少像收集对象这样的表的内存消耗.

给定类结构

Class Cell
{
    public property int Data;
    public property string Format;
}

Class Table
{
    public property Dictionary<Position, Cell> Cells;
}
Run Code Online (Sandbox Code Playgroud)

当有大量的细胞的细胞类的数据属性可以是可变的,但格式属性可被重复多次,例如,报头单元可以具有一个空的格式字符串为标题和数据单元可以全部是"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);
}
Run Code Online (Sandbox Code Playgroud)

这将节省字符串上的内存,但FormatId整数值仍将重复多次.

有没有比这更好的实施?我看过flyweight模式,但我不确定它是否与此匹配.

更为复杂的执行我正在考虑是完全移除从Cell类格式属性和而不是存储在该组中的相邻细胞一起字典的格式
例如可以有2项这样
<item rowFrom=1 rowTo=1 format="" />
<item romFrom=2 rowTo=1000 format="0.00" />

Mar*_*ell 5

对于琴弦,你或许可以看看实习生; 无论是内置的内部,还是(最好)定制的内部 - 基本上是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
    }
}
Run Code Online (Sandbox Code Playgroud)

WeakReference如果需要,你可以进一步采取这一点.

请注意,您不需要更改设计 - 只需更改填充对象的代码即可使用内部/缓存.