Платформа .NET

Из предыдущей заметки некоторые могут сделать вывод, что разрабатывать программы на .NET нельзя. Мнение это ошибочно. Разработка на .NET значительно дешевле, нежели разработка на С++. Особенно это касается разработки распределённых приложений, приложений работающих с базами данных, а так же приложений, обладающих функционально насыщенным1  пользовательским интерфейсом. Мифология медленной работы сформирована неправильной разработкой программ.

Дело в том, что спрашивающий не знал, как выделить определенный бинарный флаг из числа...
Вопрос закономерен для начинающего разработчика, но каково было мое удивление, когда я увидел ответы от авторитетнейших программистов, aвторов статей, и обладателя MVP! ...

Что же тут можно сказать? Мне становится не по себе от попытки представить скорость программ, которые пишут эти специалисты, превращая атомарные операции в циклы. Между прочим, второй ответ (от MVP) даже МЕНЕЕ производителен не смотря на кажущуюся простоту, поскольку IndexOf вызывает еще одну функцию, где в цикле ведется поиск необходимого значения.
Производительность .NET, миф или реальность

Квалификация

Основная беда «плохо работающих программ» написанных под .NET заключается в том, что они написаны идиотами. Платформа предоставлет большое количество высокоуровневых средств и глубоких знаний для разработки простых программ не требуется. Написанная на C# программа выглядит очень просто, но что стоит за этой простотой многие разработчики (как показывает практика) попросту не понимают и поэтому при разработке архитектурно сложных программ, программ оперирующих большими данными или работающими круглосуточно, начинаются проблемы, связанные зачастую с небрежностью использования ресурсов вычислительной системы.

Пример из практики

Создание 6 мегабайтной строки методом посимвольной конкатенации, выполняемой с помощью оператора +=. На 8-ми процессорном сервере данный код очень быстро приводит к возникновению исключения OutOfMemory и выгрузке программы.

Пример из практики

//pnlMainBody - это форма (System.Windows.Form)
if (pnlMainBody.Controls.Find("chk" + column.AbbrHeading + Constants.VALUE, true).GetLength(0) > 0)
{
   CheckBox chkColumnValue = pnlMainBody.Controls.Find("chk" + column.AbbrHeading + Constants.VALUE, true).Length > 0 ? 
                   (CheckBox)pnlMainBody.Controls.Find("chk" + column.AbbrHeading + Constants.VALUE, true)[0] : null;

   if (chkColumnValue != null)
   {
     drToAdd[column.AbbrHeading] = chkColumnValue.Checked ? true : false;
   }
}

Идиотизм разработчиков не является недостатком платформы.

Ресурсы

Вторая беда, свойственная всем «управляемым» платформам и .NET и Java — неявное освобожение ресурсов. Вместо утечки ресурсов (memory leak), случается блокирование ресурсов (memory lock).

Пример из практики

Плагины для bCAD 3.x разрабатывались на Java. В начале 2000-х при написании набора инструментов по генерации полигональных сеток столкнулся с проблемой нехватки памяти при генерации выскодетализированных сеток. Плагинами в то время пользовались в Новосибирском филиале КБ Сухого и создаваемые ими сетки авиационных конструкций были достаточно «тяжелыми». Это приводило к тому, что на компьютере со 256 мегабайтами памяти эта самая память быстро заканчивалась. Решение было простым, принудительный вызов сборки мусора в промежутках между построениями. В Microsoft диалекте Java существовало два различных способа вызова сборки мусора. После завершения генерации поверхности вызывался сборщик мусора, что приводило к совобождению порядка 20 Мб памяти, следующий за этим вызов сборки мусора другим способом, приводил к освобождению еще 20 Мб памяти.

Пример из практики

“System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)”

Программы .NET используют неуправляемые ресурсы, например дескрипторы (handles) для кистей, изображений и т.п. При некорректной работе в программе иногда возникает исключение OutOfMemory которое может означать не только отсутствие свободной памяти, но и отсутствие свободных дескрипторов. Количество дескрипторов, выделяемых процессу равно примерно 15000, но оно может быть изменено, например для процессов, запускаемых на виртуальных машинах.

“There is also a default per-process limit of GDI handles. To change this limit, set the following registry value: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota This value can be set to a number between 256 and 65,536.”

 Improving .NET Application Performance and Scalability

1) Термин rich user interface, который «профессиональные» переводчики переводят как богатый интерфейс :-)