C# 记录对象的内存使用情况
大概有5到6篇文章与此相关,但没有一篇真正回答这个问题 我有一个Dictionary对象,我使用它作为缓存来存储值。问题是,我不知道它有多大——随着时间的推移,它可能会变大,也可能不会变大,但我无法判断,因此我无法衡量它的有效性,也无法对用户如何使用该软件做出结论。因为这是一个将投入生产并在很长一段时间内监视某些内容的部件,所以附加内存分析器或类似调试的东西是没有意义的 理想情况下,我只需在计时器中打一个电话,这样做:C# 记录对象的内存使用情况,c#,.net,memory,C#,.net,Memory,大概有5到6篇文章与此相关,但没有一篇真正回答这个问题 我有一个Dictionary对象,我使用它作为缓存来存储值。问题是,我不知道它有多大——随着时间的推移,它可能会变大,也可能不会变大,但我无法判断,因此我无法衡量它的有效性,也无法对用户如何使用该软件做出结论。因为这是一个将投入生产并在很长一段时间内监视某些内容的部件,所以附加内存分析器或类似调试的东西是没有意义的 理想情况下,我只需在计时器中打一个电话,这样做: private void someTimer_Tick(object sen
private void someTimer_Tick(object sender, EventArgs e)
{
...
float mbMem = cacheMap.GetMemorySize();
RecordInLog(DateTime.Now.ToString() + ": mbMem is using " + mbMem.ToString() + "MB of memory");
...
}
这可以在不附加调试工具的情况下完成,以便在部署场景中使用吗?框架中没有方法告诉您对象正在使用多少内存,因为对任何类型的对象执行此操作都非常复杂
如果您知道您的字典很容易分析,即它不包含对同一项的重复引用,并且每个项的内存使用量可以很容易地进行近似计算,那么您只需在字典中循环并汇总每个对象的近似大小。根据您最近的评论,如果该值是一个可变长度的字符串,那么计算字典中每个项目的大小应该很容易。我会考虑通过创建自己的缓存对象(可能只是包装一个字典)来节省时间和精力,并且随着项目被添加到缓存中并从缓存中移除,可以跟踪总大小。这样,在任何时间点,您都可以通过查看一直跟踪的值来判断缓存中值的总大小 如果需要缓存来公开完整的
IDictionary
功能,可以实现该接口,将其委托给“真实”词典,并在Add
和Remove
操作中修改累积大小值。如果不需要缓存来公开完整的IDictionary
功能,只需定义一个精简接口即可(可能只使用Add
,包含和删除方法和CumulativeSize
属性。或者,您可能决定实现一个没有接口的缓存对象。如果是我,我会使用IDictionary
或定义一个接口,如ICache
)
因此,您的缓存可能看起来像这样(未编译且未测试):
祝你好运!也许你已经看到了这一点,但以防万一-你可以做串行化近似计算字节数是必要的吗?简单地计算键数或唯一值就足够了吗?@oleksii这可能是唯一的解决方案。我仍在试图找到一种方法来解决当你进行串行化时对性能造成的严重影响将事物化(这是一个巨大的冲击)。如果它在生产中使用,我会考虑使用性能计数器来跟踪大小(或者至少是项目的数量)。。听起来像是过早的优化。是的,密钥是唯一的。这是我的退路,只是估计k/v对的大小,并将该值缩放为集合的大小。我的主要问题是,对中的值是可变长度字符串,一旦我打破100万条记录,值中+/-50%的摆动空间可能会很大。对于strings内存使用通常很简单,长度为*2加上一些开销(12/20字节取决于32/64位平台)。但是,请注意,如果使用StringBuilder
创建字符串,字符串结尾可能会包含额外的未使用空间。这是一个想法……我会尝试一下,看看有100-200万个条目这一事实是否会破坏性能交易。我只是在将其标记为解决方案之前看完了您的第一段。然而,解决方案实施后,需要保持一个滚动的总数才能执行。这是如此清晰和简单的正确答案,我自己都没有想到。再次感谢。
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; }
}
public class MySpecialDictionary : IDictionary<string, string>
{
private IDictionary<string, string> dict = new Dictionary<string, string>();
public int TotalSize { get; private set; }
#region IDictionary<string,string> Members
public void Add(string key, string value)
{
dict.Add(key, value);
TotalSize += string.IsNullOrEmpty(value) ? 0 : value.Length;
}
public bool ContainsKey(string key)
{
return dict.ContainsKey(key);
}
public ICollection<string> Keys
{
get { return dict.Keys; }
}
public bool Remove(string key)
{
string value;
if (dict.TryGetValue(key, out value))
{
TotalSize -= string.IsNullOrEmpty(value) ? 0 : value.Length;
}
return dict.Remove(key);
}
public bool TryGetValue(string key, out string value)
{
return dict.TryGetValue(key, out value);
}
public ICollection<string> Values
{
get { return dict.Values; }
}
public string this[string key]
{
get
{
return dict[key];
}
set
{
string v;
if (dict.TryGetValue(key, out v))
{
TotalSize -= string.IsNullOrEmpty(v) ? 0 : v.Length;
}
dict[key] = value;
TotalSize += string.IsNullOrEmpty(value) ? 0 : value.Length;
}
}
#endregion
#region ICollection<KeyValuePair<string,string>> Members
public void Add(KeyValuePair<string, string> item)
{
dict.Add(item);
TotalSize += string.IsNullOrEmpty(item.Value) ? 0 : item.Value.Length;
}
public void Clear()
{
dict.Clear();
TotalSize = 0;
}
public bool Contains(KeyValuePair<string, string> item)
{
return dict.Contains(item);
}
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
{
dict.CopyTo(array, arrayIndex);
}
public int Count
{
get { return dict.Count; }
}
public bool IsReadOnly
{
get { return dict.IsReadOnly; }
}
public bool Remove(KeyValuePair<string, string> item)
{
string v;
if (dict.TryGetValue(item.Key, out v))
{
TotalSize -= string.IsNullOrEmpty(v) ? 0 : v.Length;
}
return dict.Remove(item);
}
#endregion
#region IEnumerable<KeyValuePair<string,string>> Members
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return dict.GetEnumerator();
}
#endregion
}