Большой набор данных в памяти - .NET Framework и C # - PullRequest
2 голосов
/ 28 марта 2011

У меня есть проект DLL, который создает единый список всех отображаемых строк, используемых в моем приложении. Проблема в том, что мне нужна ссылка на эту DLL во многих независимо работающих приложениях.

Я понимаю, что если я буду ссылаться на проект DLL во всех независимо работающих приложениях, они все загрузят DLL в память и создадут отдельные синглтоны, к которым они могут обращаться, но я хочу избежать этой избыточности.

Есть ли способ сохранить один экземпляр этого синглтона в памяти и ссылаться на него из всех независимых проектов?

Я понимаю, что я звучу глупо и что эта загрузка может вообще не происходить, но я искал около часа сейчас:)

Я использую .NET Framework с C # в качестве целевого языка.

Ответы [ 4 ]

5 голосов
/ 28 марта 2011

Как правило, разные процессы имеют разные адресные пространства. Поскольку DLL-файл обычно загружается в адресное пространство процесса, необходимо написать специальный код для реализации обмена данными между процессами. Обычно это делается с помощью Windows API , например, с помощью отображенных в память файлов. Вы можете узнать больше об этом на:

Совместное использование памяти между двумя процессами (C, Windows)

Использование Windows API неплохо, но это как-то противоречит философии .NET Framework. Я думаю, что лучше создать клиент-серверную архитектуру, когда один сервер может работать с разными клиентами и передавать им необходимые данные. Это можно сделать, используя, например, Remoting или WCF .

2 голосов
/ 28 марта 2011

Я бы не стал беспокоиться о потреблении памяти, пока это действительно не станет проблемой.Мы можем сделать несколько простых математических вычислений: 2 ^ 13 (8192) строк в 2 ^ 3 (8) приложениях - это 2 ^ 16 строк, и если одна строка имеет средний размер 2 ^ 8 (256) символов, общее количество байтов для всехприложения 2 * 2^24 (32 МиБ).Это не должно создавать никаких проблем, даже если количество строк будет умножено на 10.

Объем работы, требуемый другими решениями, сделает их неосуществимыми на текущем этапе.Также не будет преимуществ общего сервиса строк, если большинство общих строк используются всеми приложениями.Это дает преимущества только в том случае, если небольшая часть строк действительно используется всеми ими.

При удаленном взаимодействии вам нужно будет убедиться, что экземпляр singleton инициализируется только в одном месте, и вам нужно получить к нему доступ через интерфейсы.,Скорее всего, вы хотите создать локальный экземпляр Singleton, который запрашивает строки из удаленного экземпляра.Это решение также может быть реализовано впоследствии, если вы продолжите использовать старую реализацию Singleton, пока не понадобятся другие решения.

Если вы используете TaskManager для отслеживания использования памяти, у вас должна быть очень большая строка в классе singleton.*

public static Strings {
    private readonly string MemoryUsageTest;

    static Strings() {
#if DEBUG
        int size = 104000000;
        var text = "abcdefghijklmnopqrstuvwxyz";
        var sb = new StringBuilder(size);

        for (int i = 0; i < size / text.Length; ++i) {
            sb.Append(text);
        }

        MemoryUsageTest = sb.ToString();
#endif
    }
}

Я не уверен, что удаленное взаимодействие будет хорошей альтернативой в любой момент.В любом случае, если мы предположим, что это будет хорошей альтернативой, я бы предложил, чтобы текущая реализация использовала одноэлементный класс, который реализует интерфейс.Это значительно упростит использование удаленного экземпляра.

public interface IStrings {
    string HelloWorld { get; }
}

public sealed class LocalStringService : IStrings {
    internal LocalStringService() { }

    string IStrings.HelloWorld {
        get { return "Hello World!"; }
    }
}

public static class StringService {
    private static readonly IStrings SingletonInstance = new LocalStringService();

    // If empty static constructor does not make any sense, read this:
    // http://csharpindepth.com/Articles/General/Beforefieldinit.aspx
    static StringService() { }

    public static IStrings Instance {
        get { return SingletonInstance; }
    }
}

Теперь, если вы хотите сделать этот удаленный экземпляр, вам нужно будет только переименовать LocalStringService в RemoteStringService, чтобы он наследовал MarshalByRefObjи измените StringService, чтобы создать его удаленный экземпляр.Кроме того, RemoteStringService должен находиться в другой сборке, чтобы он не загружался в память вместе с другими классами.

Тем не менее я сомневаюсь, что это даст вам какие-либо преимущества в этом случае.

1 голос
/ 28 марта 2011

Создайте оболочку службы для этого файла DLL и вместо этого вызовите службу из других приложений.

1 голос
/ 28 марта 2011

Используемые строковые константы, скорее всего, интернированы. Вызовите статическую функцию string.IsInterned, чтобы увидеть конкретную строку. В этом случае они не занимают лишнюю память, поскольку каждая строка находится в пуле CLR.

IsInterned

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...