Будет ли это эффективным способом улучшить задержки холодного запуска в .NET?
Следующий код (Виталий Липчинский) проходит через все типы сборки и вызывает метод PrepareMethod для всех методов. Будет ли это улучшать задержки холодного запуска?
Thread jitter = new Thread(() =>
{
foreach (var type in Assembly.Load("MyHavyAssembly, Version=1.8.2008.8," +
" Culture=neutral, PublicKeyToken=8744b20f8da049e3").GetTypes())
{
foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static))
{
if (method.IsAbstract || method.ContainsGenericParameters)
continue;
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
}
}
});
jitter.Priority = ThreadPriority.Lowest;
jitter.Start();
Ответы
Ответ 1
Он не сделает запуск более быстрым - в конце концов, он делает работу раньше, чем обычно, а не позже. На самом деле это может немного замедлить запуск, так как у вас будет другой поток, выполняющий работу, пока ваше приложение пытается запустить.
Это означает, что к тому времени, когда поток завершится, вы не должны видеть обычную (крошечную) задержку JIT, когда вы вызываете метод в первый раз. (Конечно, есть и конструкторы, но вы можете включить их, если хотите.)
Кроме того, вероятно, это означает, что раньше будет использоваться больше памяти, и в JIT может быть некоторая блокировка, работающая над методами, что означает, что ваш "основной" поток, возможно, придется иногда ждать.
Лично я бы не использовал его "по-настоящему", если бы у меня не было очень хороших доказательств, чтобы предлагать его на самом деле помогать. Во что бы то ни стало проверить это и попытаться получить такие доказательства. Если вы не возражаете против времени запуска, но вам нужно быстрое время отклика, когда вы приходите на работу с приложением, это может помочь.
Ответ 2
Как обсуждалось в комментариях, может быть достаточно просто предварительно загрузить сборки:
static void PreloadAssemblies()
{
int count = -1;
Debug.WriteLine("Loading assemblies...");
List<string> done = new List<string>(); // important...
Queue<AssemblyName> queue = new Queue<AssemblyName>();
queue.Enqueue(Assembly.GetEntryAssembly().GetName());
while (queue.Count > 0)
{
AssemblyName an = queue.Dequeue();
if (done.Contains(an.FullName)) continue;
done.Add(an.FullName);
try
{
Assembly loaded = Assembly.Load(an);
count++;
foreach (AssemblyName next in loaded.GetReferencedAssemblies())
{
queue.Enqueue(next);
}
}
catch { } // not a problem
}
Debug.WriteLine("Assemblies loaded: " + count);
}