Предварительная загрузка всех сборок (JIT) - PullRequest
4 голосов
/ 03 марта 2011

Мы принимаем удар в первый раз, когда загружаются некоторые тяжелые экраны пользовательского интерфейса.Наш проект разделен на один основной исполняемый файл и несколько файлов DLL.Файлы DLL также могут содержать экраны пользовательского интерфейса, которые замедляются при первой загрузке.

Есть ли способ (в коде), которым мы можем предварительно загрузить все ссылочные сборки, чтобы избежать попадания JIT-компиляции?

Я знаю, что есть инструмент под названием NGen .Можно ли использовать NGen в среде разработки, чтобы мы могли сразу увидеть ее эффекты?Тем не менее, в идеале мы хотели бы предварительно загрузить ссылочные сборки из кода.

Используя C # .NET 3.5 вместе с DevExpress для наших компонентов пользовательского интерфейса.

Ответы [ 5 ]

7 голосов
/ 18 марта 2012

Лично я обнаружил, что включение предварительного джиттера в «Программу» помогло в определенном приложении, но это вопрос для конкретной ситуации.

Что более важно, код в ответе wal произойдет сбой при обнаружении абстрактного метода, поэтому для пропуска абстрактных методов были добавлены две строки кода.

static Program()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            if ((method.Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract|| method.ContainsGenericParameters)
            {
                continue;
            }
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
    Console.WriteLine("jitted!");
}
7 голосов
/ 18 апреля 2011

Вы пробовали / смотрели на это ?

То есть выполните следующие действия для каждой сборки, которую вы хотите предварительно JIT.

static void PreJIT()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
}
6 голосов
/ 03 марта 2011

Взгляните на NGen .Другой вариант - использовать ILMerge для объединения всех ваших сборок в одну.Всякий раз, когда я использую ILMerge, я добавляю команду post build, чтобы это происходило автоматически.Другая альтернатива (не проверенная) заключается в том, что, если вы не возражаете против более длительного времени запуска, вы можете вручную вызвать Assembly.Load () в начале для каждой сборки.

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

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

0 голосов
/ 03 марта 2011

Вы можете использовать NGen на любой машине - в CLR нет понятия «среда разработки» ... При использовании убедитесь, что изображения, созданные NGen, действительно используются (см. Native Image Generator (Ngen.exe) для получения инструкций и поиска примечания FusLogVw в документе).

Вы также можете предварительно JIT, вызывая весь код, который вы ожидаете запустить (как предложил Давита), но вам нужно будет вызывать каждый метод всех классов, что не совсем практично.

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

...