Почему .NET использует так много процессора, является ли это проблемой?

StackOverflow https://stackoverflow.com/questions/1429162

Вопрос

(Это должен был быть общий гипотетический вопрос, я жаловался, что .NET — свинья, и умолял объяснить причины.На самом деле это не был вопрос о моем конкретном приложении.)

В настоящее время я переписываю старый код C++ на C#.Мы переносим все устаревшие приложения.У меня есть приложения на C++, которые занимают МАКСИМАЛЬНО 3% ЦП.В основном они ничего не используют.Затем я беру код, копирую и вставляю, затем переформатирую его в синтаксис C# и библиотеки .NET, и БАМ!50% процессор.В чем причина этого?Сначала я подумал, что это JIT, но даже после того, как каждый путь кода был проверен и все это было JIT-редактировано, та же проблема.

Я также заметил огромный прирост памяти.Приложения, которые при полной загрузке занимали 9 МБ, теперь начинаются с 10 МБ и работают с 50 МБ.Я понимаю, что оборудование дешевое, но я хочу понять, что является причиной этого.Является ли это поводом для беспокойства или .NET — такая уж свинья?

Обновить 1 ответ на Скит

Я знаком с C#.Я меняю что-то на Linq и так далее.Я обычно беру код и уменьшаю количество строк и так далее.Не могли бы вы привести еще несколько примеров того, что человек, работающий на C++, делает неправильно в .NET?

Обновление 2

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

У него есть поток, который использует драйвер ODBC для получения данных из парадоксальной базы данных.Затем он использует Linq, чтобы преобразовать это в базу данных SQL и опубликовать ее.Я пропустил его через профилировщик ANTS, и кажется, что заполнение набора данных занимает больше всего времени.Далее следует сообщение Linq.Я знаю, что некоторые из моих областей связаны с использованием отражений, но я не понимаю, как без этого сделать то, что мне нужно.Я планирую сменить свою струну на строители струн.Есть ли разница между этими двумя?

(int)datarow["Index"]

и

ConvertTo.Int32(datarow["Index"])

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

Это было полезно?

Решение

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

Мы не можем точно сказать, что снижает производительность, не зная больше о приложении, хотя я не удивлюсь, узнав, что виновата конкатенация строк.Сколько процессоров у вас в коробке?Если это 2, то приложение в основном использует все, что может, для одного потока...

.NET обычно требует больше памяти, чем приложение C++, но оно должно быть как минимум сопоставимый с точки зрения скорости для большинства задач.Взятие 50 МБ вместо 9 МБ кажется большим, чем я ожидал, но я бы не стал сразу слишком волновался.

Производительность памяти и процессора следует исследовать с помощью хорошего профилировщика.Я могу порекомендовать Профилировщик JetBrains dotTrace, но есть много других.

Другие советы

AFAIK, есть небольшая разница между (int)datarow["Index"] и ConvertTo.Int32(datarow["Index"]).Однако есть большая разница, если вы используете считыватели данных в потоковом режиме:

int orderIndex = <order of Index column in projection list>;
using (OdbcDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
  int Index = rdr.GetInt32(orderIndex);
}

А SeqentialAccess Поведение команд — это самый быстрый способ обработки результатов SQL, поскольку оно устраняет необходимость дополнительного кэширования, необходимого для произвольного доступа.

Второе замечание: похоже, вы используете наборы данных.Наборы данных просты в использовании, но они очень далеки от того, что можно назвать «быстрым».С наборами данных вы в основном используете механизм хранения в памяти (я думаю, он основан на Рашмор).Если вы хотите выжать каждый цикл процессора и все единицы из каждого бита оперативной памяти, вам придется использовать более компактные компоненты (например.необработанные массивы структур вместо наборов данных и таблиц данных).

Когда вы сравниваете яблоки с яблоками, CLR может устоять перед нативным кодом.IL-код может быть адаптирован во время развертывания с помощью НГЕН.Типичные накладные расходы CLR, такие как проверок границ можно избежать .«Пауза» вытеснения GC происходит только в том случае, если вы небрежно относитесь к распределению (тот факт, что у вас есть GC, не означает, что вы должны выделять влево и вправо).И у CLR действительно есть козыри в рукаве, когда дело доходит до структуры памяти, поскольку она может переупорядочивать объекты в памяти в соответствии с шаблонами доступа и улучшать локальность TLB и L2.

Кстати, если вы думаете, что дебаты о том, что C++ может кружить вокруг C#, — это что-то новое, я помню время, когда C мог кружить вокруг C++ («виртуальные вызовы невероятно медленны», — говорили они), и я слышал, что была временная сборка бегал кругами вокруг С.

Вы должны увидеть некоторое увеличение использования процессора.От 3% до 50% звучит слишком много, что это за код?

Объем памяти — это всего лишь неизбежные затраты.Любая вещь размером от 30 до 50 МБ для приложения .NET является нормальной.Как правило, фактическое использование памяти вашим .NET-приложением очень мало, но существуют значительные накладные расходы во время выполнения, которых вы не можете избежать (это единовременные затраты, но они есть), и это очень заметно, если вы ссылаетесь на тонны сборок. .

Я бы сказал, что использование памяти, вероятно, соответствует, но использование ЦП — нет.

Похоже, у вас есть нить, которая не поддается.

Могу предположить несколько предположений:

1) Память. В C++ нет управляемой памяти.Таким образом, он освобождает память постепенно и в оптимальное время (если оно правильно запрограммировано).

При использовании управляемой памяти программа, по сути, будет «упускать» память до тех пор, пока не решит выполнить сборку мусора.Время, вероятно, зависит от того, сколько памяти было выделено процессу.Вероятно, есть способ изменить поведение по умолчанию, но меньший размер памяти означает, что сбор мусора происходит быстрее и чаще, что влияет на время обработки.Если выделено достаточно памяти, то вызов gc может не потребоваться.

2) Программа выполняется за то же время или меньше?Если он использует в 5 раз больше мощности процессора, но завершается за 1/5 времени, то используемый процессор в основном эквивалентен.

3) Да, .NET, наверное, свинья.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top