Pregunta ¿Hay un sistema como BigMemory para .net?


Acabo de estar leyendo sobre cómo BigMemory permite que los sistemas Java se amplíen en lugar de expandirse.

Acerca de BigMemory:

BigMemory proporciona a las aplicaciones Java acceso instantáneo y sin esfuerzo a un   Huella de memoria grande, libre de las restricciones de la recolección de basura.

BigMemory es Java puro y proporciona una Caché en el proceso fuera del montón ese   le permite almacenar grandes cantidades de datos, hasta un terabyte, más cerca de su   solicitud.

Esta solución revolucionaria mejora la utilización de la memoria   y el rendimiento de la aplicación con ambos, independiente y distribuido   almacenamiento en caché

Entonces, ¿cómo hago lo mismo con .net, p. Ej. Caché en el proceso fuera del montón. (Tenga en cuenta que el caché de Asp.net está en el montón de basura recolectada)


5
2017-08-25 10:54


origen


Respuestas:


No, no hay un sistema BigMemory para .Net (es decir, un gestor de memoria de montón no en proceso que no sea de GC), sin embargo, puede hacer el suyo.

Puede utilizar un montón no administrado para tener un montón en proceso recolectado sin basura, sin embargo, si está trabajando con objetos en lugar de memoria en bruto, tendrá que serializarlos y deserializarlos. lento.

Tendrá que mantener una búsqueda de infos de pila para poder recuperar sus objetos, esto obviamente tiene su propia sobrecarga de memoria, por lo que no es adecuado para una gran cantidad de objetos muy pequeños como:

a. Una gran cantidad de memoria será ocupada por los objetos de gestión.
segundo. El GC se volverá loco escaneando los objetos de gestión.

Si los objetos son lo suficientemente grandes y no hay también Muchos de ellos, esto podría funcionar para usted.

Sin embargo, también podría insertar parte de la información de administración en el montón no administrado. Hay muchas oportunidades de optimización.

Todo esto puede completarse para que funcione como un valor clave \ value cache, por lo tanto, se resumen las informaciones del montón y el montón.

Actualizado

Código de ejemplo actualizado para usar Protobuf lo que hace la serialización binaria significativamente más rápido que .Net. Esta muestra simple puede poner + obtener 425k de objetos por segundo, con una envoltura de \ key value. Su millage variará dependiendo del tamaño del objeto \ complejidad.

El tamaño del objeto se almacena en un montón no administrado para reducir el consumo de memoria en el montón administrado.

...
...
using ProtoBuf;

[TestFixture]
public class UnmanagedHeap
{
    [Test]
    public void UnmanagedHeapAccess()
    {
        const int Iterations = 425 * 1000;
        const string Key = "woo";

        Bling obj = new Bling { Id = -666 };
        Cache cache = new Cache();
        Stopwatch sw = Stopwatch.StartNew();

        for (int i = 0; i < Iterations; i++)
        {
            cache.Put(Key, obj);

            obj = cache.Get<Bling>(Key);
        }

        cache.Remove(Key);

        Console.WriteLine(sw.Elapsed.TotalMilliseconds);
    }

    [DataContract]
    public class Bling
    {
        [DataMember(Order = 1)]
        public int Id { get; set; }
    }

    public class Cache
    {
        private const int SizeFieldWidth = 4;

        private readonly Dictionary<string, IntPtr> _lookup = new Dictionary<string, IntPtr>();

        public void Put(string key, object obj)
        {
            IntPtr oldPtr = _lookup.TryGetValue(key, out oldPtr) ? oldPtr : IntPtr.Zero;

            IntPtr newPtr = SerializeToHeap(obj, oldPtr);

            _lookup[key] = newPtr;
        }

        public T Get<T>(string key)
        {
            IntPtr ptr = _lookup[key];

            return DeserializeFromHeap<T>(ptr);
        }

        public void Remove(string key)
        {
            IntPtr ptr = _lookup[key];

            Marshal.FreeHGlobal(ptr);

            _lookup.Remove(key);
        }

        private static IntPtr SerializeToHeap(object obj, IntPtr oldPtr)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.Serialize(ms, obj);
                byte[] objBytes = ms.GetBuffer();
                int newSize = (int)ms.Length;
                bool requiresAlloc = true;

                if (oldPtr != IntPtr.Zero)
                {
                    int oldSize = GetObjectSize(oldPtr);

                    requiresAlloc = (oldSize != newSize);
                }

                IntPtr newPtr = requiresAlloc ? Marshal.AllocHGlobal(newSize + SizeFieldWidth) : oldPtr;

                byte[] sizeField = BitConverter.GetBytes(newSize);
                Marshal.Copy(sizeField, 0, newPtr, SizeFieldWidth);
                Marshal.Copy(objBytes, 0, newPtr + SizeFieldWidth, newSize);
                return newPtr;
            }
        }

        private static T DeserializeFromHeap<T>(IntPtr ptr)
        {
            int size = GetObjectSize(ptr);
            byte[] objBytes = new byte[size];
            Marshal.Copy(ptr + SizeFieldWidth, objBytes, 0, size);

            using (MemoryStream ms = new MemoryStream(objBytes))
            {
                return Serializer.Deserialize<T>(ms);
            }
        }

        private static int GetObjectSize(IntPtr ptr)
        {
            byte[] sizeField = new byte[SizeFieldWidth];
            Marshal.Copy(ptr, sizeField, 0, SizeFieldWidth);
            int size = BitConverter.ToInt32(sizeField, 0);
            return size;
        }
    }
}

8
2017-08-25 13:27



Sí, hay un código administrado al 100%. ProtoBuf sugerido en la respuesta anterior no le dará 100% de transparencia como  no correlaciona erecciones polimórficas y ciclos de forma adecuada + requiere atributos especiales. NFX Pile no requiere nada más que [Serializable]

https://github.com/aumcode/nfx https://github.com/aumcode/nfx/blob/master/Source/NFX/ApplicationModel/Pile/IPile.cs

https://github.com/aumcode/nfx/blob/master/Source/NFX/ApplicationModel/Pile/ICache.cs

ver videos: https://www.youtube.com/watch?v=IUBF2Ncvbbs

https://www.youtube.com/watch?v=Dz_7hukyejQ

Apache 2.0


1
2017-08-09 01:33