Есть ли BigMemory как система для .net - PullRequest
5 голосов
/ 25 августа 2011

Я только что читал о том, как BigMemory позволяет Java-системам расширяться, а не уменьшаться.

О BigMemory :

BigMemory предоставляет приложениям Java мгновенный, легкий доступ к большому объему памяти, без ограничений по сбору мусора.

BigMemory - это чистая Java и обеспечивает внутрипроцессный кэш вне кучи это позволяет хранить большие объемы данных - до терабайта - ближе к вашему приложению.

Это революционное решение улучшает использование памяти и производительность приложений благодаря автономному и распределенному кешированию.

Итак, как мне сделать то же самое с .net, например, in-process,вне кучи .(Обратите внимание, что кэш Asp.net находится в куче мусора)

Ответы [ 2 ]

8 голосов
/ 25 августа 2011

Нет, системы BigMemory для .Net (т. Е. Внутрипроцессного менеджера кучи памяти без GC) нет, однако вы можете свернуть свою собственную.

Вы можете использовать неуправляемую кучу, чтобы получить неиспользуемую кучу в процессе, однако, если вы работаете с объектами, а не с необработанной памятью, вам придется сериализовать и десериализовать их, что медленно .

Вам нужно будет искать информацию о куче, чтобы вы могли извлекать свои объекты, это, очевидно, имеет свои накладные расходы памяти, поэтому не подходит для огромного количества очень маленьких объектов, таких как:

а. Большая часть памяти будет занята объектами управления.
б. ГХ сходит с ума, просматривая объекты управления.

Если объекты достаточно большие и их не слишком много, это может сработать для вас.

Однако вы также можете поместить некоторую информацию об управлении в неуправляемую кучу. Есть много возможностей для оптимизации.

Все это можно обернуть, чтобы он работал как кеш ключ \ значение, таким образом абстрагируя информацию о куче и кучу.

Обновлено

Обновлен пример кода для использования Protobuf , который выполняет двоичную сериализацию значительно быстрее, чем .Net. Этот простой пример может помещать + получать 425 тыс. Объектов в секунду с помощью обертки ключ \ значение. Ваш корм будет варьироваться в зависимости от размера объекта \ сложности.

Размер объекта хранится в неуправляемой куче, чтобы уменьшить потребление памяти в управляемой куче.

...
...
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;
        }
    }
}
1 голос
/ 09 августа 2015

Да, есть 100% управляемый код. ProtoBuf, предложенный в ответе выше, не даст вам 100% прозрачности, так как он не отображает полиморфные ссылки и циклы должным образом + требует специальных атрибутов. NFX Pile не требует ничего, кроме [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

смотреть видео: https://www.youtube.com/watch?v=IUBF2Ncvbbs

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

Apache 2.0

...