可能有5或6个SO帖子切向触及,但没有一个真正回答这个问题。
我有一个Dictionary对象,我使用它作为缓存来存储值。问题是我不知道它有多大 - 随着时间的推移它可能会变得越来越大,但我无法分辨,所以我无法衡量它的有效性,或者对用户如何使用该软件做出结论。因为这是一部将在很长一段时间内投入生产和监控的东西,所以连接内存分析器或任何类似的调试都没有意义。
理想情况下,我只需在我的计时器中调用一个类似于:
的调用private void someTimer_Tick(object sender, EventArgs e)
{
...
float mbMem = cacheMap.GetMemorySize();
RecordInLog(DateTime.Now.ToString() + ": mbMem is using " + mbMem.ToString() + "MB of memory");
...
}
这可以在不附加某些调试工具的情况下完成,以便可以使用部署方案吗?
答案 0 :(得分:1)
框架中没有方法可以告诉您对象使用了多少内存,因为对任何类型的对象执行此操作都会非常复杂。
如果您知道您的词典很容易分析,即它不包含对同一项目的重复引用,并且每个项目的内存使用量可以很容易地近似,您可以循环浏览字典并求和增加每个物体的大致尺寸。
答案 1 :(得分:1)
鉴于您最近的评论,该值是一个可变长度字符串,它应该很容易计算字典中每个项目的大小。我会考虑通过创建自己的缓存对象(可能只是包装一个字典)来节省时间和精力,并在缓存中添加和删除项目时跟踪总大小。这样,在任何时间点,您都可以通过查看一直跟踪的值来判断缓存中值的总大小。
如果您需要缓存来公开完整的IDictionary
功能,您可以实现界面,委托“真实”字典并修改Add
和{{1}中的累积大小值操作。如果您不需要缓存来公开完整的Remove
功能,只需定义一个精简的界面(可能只有IDictionary
,Add
和Contains
方法和Remove
属性。或者,您可能决定在没有接口的情况下实现缓存对象。如果是我,我会使用CumulativeSize
或定义接口,如IDictionary
。
因此,您的缓存可能看起来像这样(未编译和未经测试):
ICache
这非常粗糙。显然它可以更有效,更强大。我没有在public interface ICacheWithCumulativeSize
{
void Add(string key, string value);
bool Contains(string key);
void Remove(string key);
int CumulativeSize { get; }
}
public class MyCache : ICacheWithCumulativeSize
{
private IDictionary<string, string> dict = new Dictionary<string, string>();
public void Add(string key, string value)
{
CumulativeSize += value.Length;
dict[key] = value;
}
public bool Contains(string key)
{
return dict.ContainsKey(key);
}
public void Remove(string key)
{
string toRemove = dict[key];
CumulativeSize -= value.Length;
dict.Remove(key);
}
int CumulativeSize { public get; private set; }
}
和Add
进行任何检查以查看密钥是否已经存在等等,但我认为您可能已经明白了。此外,可能会在外部修改作为字典中的值存储的字符串(可能不在您的程序中,但在理论上),因此当从Remove
中减去字符串时,字符串的长度可能会被修改。从缓存中删除的值可能与最初添加时该字符串的长度不同。如果这是一个问题,您可以考虑在内部字典中存储值的副本。我对你的申请知之甚少,不知道这是不是一个好主意。
为了完整性...这是一个粗略的实现,它简单地包装字典,公开IDictionary接口,并跟踪缓存中项目的总大小。它有一些防御性代码,主要用于保护大小累加器。我可能认为唯一棘手的部分是索引设置器...我的实现检查以查看所设置的索引是否已存在。如果是,则累积值适当地递减,然后基于输入值的大小递增。否则,我认为这很简单。
CumulativeSize
祝你好运!