Почему .NET использует так много процессора, это проблема? - PullRequest
5 голосов
/ 15 сентября 2009

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

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

Обновление 1 Ответ Skeet

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

Обновление 2

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

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

(int)datarow["Index"]

и

ConvertTo.Int32(datarow["Index"])

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

Ответы [ 5 ]

17 голосов
/ 15 сентября 2009

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

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

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

И память, и производительность процессора должны быть исследованы с использованием хорошего профилировщика. Я могу порекомендовать JetBrains DotTrace Profiler , но есть множество других.

6 голосов
/ 16 сентября 2009

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, поскольку он устраняет дополнительное кэширование, необходимое для произвольного доступа.

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

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

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

1 голос
/ 15 сентября 2009

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

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

0 голосов
/ 15 сентября 2009

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

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

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

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

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

0 голосов
/ 15 сентября 2009

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

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

...