На днях, при отладке профайлера, на приложении выделяющим и инициализирующим массив в 2Gb (максимальный размер объекта в CLR), во время очередного GC, был замечен странный кратковременный всплеск потребления памяти - выделялось дополнительно еще 2Gb (итого пиково было 4Gb). После расследования выяснилось, что на время вызова ICorProfilerCallback::ObjectReferences() CLR выделяет массив для передачи в профайлер всех исходящих рефернсов соответствующего объекта. Если референсы занимают эти самые 2Gb, то будут выделен массив в 2Gb. Проблема возникает только тогда, когда ICorProfilerCallback::ObjectReferences() возвращает всегда S_OK и производится полный обход графа для профайлера.
Собственно приложение (число 9 в коде подобрано для CLR 4.0 x64):
using System; namespace AllocationTest { internal class Program { private static void Main() { var tmp = new object[0x80000000U / (uint) IntPtr.Size - 9]; for (int n = 0; n < tmp.Length; ++n) tmp[n] = tmp; Console.Write("Press any key..."); Console.ReadKey(); Console.WriteLine(); GC.KeepAlive(tmp); } } }P.S. Если убрать в примере запонение массива, то эффект наблюдается не будет. P.P.S.CLR v4.5 x64 может выделять массивы больше чем 2Gb! Смотри gcAllowVeryLargeObjects.
No comments:
Post a Comment