Dado su comentario más reciente, que el valor es una cadena de longitud variable, debería ser fácil calcular el tamaño de cada elemento en el diccionario. Consideraría ahorrar tiempo y esfuerzo creando su propio objeto de almacenamiento en caché (posiblemente solo envolviendo un diccionario) y haciendo un seguimiento del tamaño total a medida que se agregan y eliminan los elementos del caché. De esta forma, en cualquier punto del tiempo puede decir el tamaño total de los valores en la memoria caché mirando el valor que ha estado siguiendo todo el tiempo.
Si necesita que su caché para exponer la funcionalidad completa IDictionary
, se podría implementar la interfaz, delegando hasta el diccionario "real" y modificar el valor del tamaño acumulado de las operaciones y Add
Remove
. Si no necesita su caché para exponer la funcionalidad completa de IDictionary
, simplemente defina una interfaz simplificada (con quizás solo Add
, Contains
y Remove
y una propiedad CumulativeSize
). O bien, podría decidir implementar un objeto de caché sin una interfaz . Si se tratara de mí, yo tampoco utilizo IDictionary
o definir una interfaz, como ICache
Así, la memoria caché podría ser algo como esto (sin compilar y no probado):.
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; }
}
esto es bastante duro. Obviamente, podría ser más eficiente y más robusto. No estoy haciendo cualquier verificación en Add
y Remove
para ver si ya existe una clave, etc., pero creo que probablemente entiendas la idea. Además, es posible que las cadenas que se almacenan como valores en el diccionario se puedan modificar externamente (tal vez no en su programa, pero teóricamente), por lo que la longitud de una cadena cuando se resta del CumulativeSize
cuando se elimina un valor de la memoria caché puede no ser la misma que la longitud de esa cadena cuando se agregó originalmente. Si esto es una preocupación, podría considerar almacenar copias de los valores en el diccionario interno. No sé lo suficiente sobre su aplicación para decir si esta es una buena idea o no.
Para completar ...Aquí hay una implementación aproximada que simplemente envuelve un diccionario, expone la interfaz IDictionary y realiza un seguimiento del tamaño total de los elementos en la memoria caché. Tiene un código un poco más defensivo, principalmente para proteger el acumulador de tamaño. La única parte que podría considerar engañosa es el conjunto de índices ... Mi implementación comprueba si el índice que se está configurando ya existe. Si es así, el valor acumulado se disminuye de forma adecuada y luego se incrementa en función del tamaño del valor de entrada. De lo contrario, creo que es bastante sencillo.
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
}
¡Buena suerte!
Quizás ya haya visto esto, pero por las dudas, puede hacer la aproximación de serrialización http://stackoverflow.com/questions/605621/how-to-get-object-size-in-memory – oleksii
Es necesario contar los bytes ? ¿Podría simplemente contar el número de claves o valores únicos ser lo suficientemente bueno? –
@oleksii Esta podría ser la única solución. Todavía estoy tratando de encontrar la manera de evitar el golpe de rendimiento sustancial que recibes cuando serializas cosas (es un gran éxito). – kmarks2