Перформансе у .НЕТ Цоре

Здраво свима! Овај чланак је збирка најбољих пракси које моје колеге и ја користимо већ дуже време када радимо на различитим пројектима.
Информације о машини на којој су извршени прорачуни:БенчмаркДотНет=в0.11.5, ОС=Windows 10.0.18362
Интел Цоре и5-8250У ЦПУ 1.60 ГХз (Каби Лаке Р), 1 ЦПУ, 8 логичких и 4 физичка језгра
.НЕТ Цоре СДК=3.0.100
[Хост]: .НЕТ Цоре 2.2.7 (ЦореЦЛР 4.6.28008.02, ЦореФКС 4.6.28008.03), 64-битни РиуЈИТ
Језгро: .НЕТ Цоре 2.2.7 (ЦореЦЛР 4.6.28008.02, ЦореФКС 4.6.28008.03), 64-битни РиуЈИТ
[Хост]: .НЕТ Цоре 3.0.0 (ЦореЦЛР 4.700.19.46205, ЦореФКС 4.700.19.46214), 64-битни РиуЈИТ
Језгро: .НЕТ Цоре 3.0.0 (ЦореЦЛР 4.700.19.46205, ЦореФКС 4.700.19.46214), 64-битни РиуЈИТ
Јоб=Цоре Рунтиме=Цоре
ТоЛист вс ТоАрраи и Цицлес
Планирао сам да припремим ове информације са издавањем .НЕТ Цоре 3.0, али су ме победили, не желим да крадем туђу славу и копирам туђе информације, па ћу само истаћи .
У своје име само желим да вам представим своја мерења и резултате.
Код:
public class Bench
{
private List<int> _list;
private int[] _array;
[Params(100000, 10000000)] public int N;
[GlobalSetup]
public void Setup()
{
const int MIN = 1;
const int MAX = 10;
Random random = new Random();
_list = Enumerable.Repeat(0, N).Select(i => random.Next(MIN, MAX)).ToList();
_array = _list.ToArray();
}
[Benchmark]
public int ForList()
{
int total = 0;
for (int i = 0; i < _list.Count; i++)
{
total += _list[i];
}
return total;
}
[Benchmark]
public int ForListFromEnd()
{
int total = 0;t
for (int i = _list.Count-1; i > 0; i--)
{
total += _list[i];
}
return total;
}
[Benchmark]
public int ForeachList()
{
int total = 0;
foreach (int i in _list)
{
total += i;
}
return total;
}
[Benchmark]
public int ForeachArray()
{
int total = 0;
foreach (int i in _array)
{
total += i;
}
return total;
}
[Benchmark]
public int ForArray()
{
int total = 0;
for (int i = 0; i < _array.Length; i++)
{
total += _array[i];
}
return total;
}
[Benchmark]
public int ForArrayFromEnd()
{
int total = 0;
for (int i = _array.Length-1; i > 0; i--)
{
total += _array[i];
}
return total;
}
}
Брзине перформанси у .НЕТ Цоре 2.2 и 3.0 су скоро идентичне. Ево шта сам успео да добијем у .НЕТ Цоре 3.0:


Можемо закључити да је итеративна обрада колекције Арраи бржа због њених интерних оптимизација и експлицитне алокације величине колекције. Такође је вредно запамтити да колекција Листа има своје предности и да треба да користите праву колекцију у зависности од потребних прорачуна. Чак и ако пишете логику за рад са петљама, не заборавите да је ово обична петља и да је такође подложна могућој оптимизацији петље. На хабру је давно објављен чланак: . И даље је релевантна и препоручена за читање.
Бацити
Пре годину дана радио сам у једној компанији на застарелом пројекту, у том пројекту је било нормално да се валидација на терену обрађује кроз конструкцију покушај-хватај-баци. Већ тада сам схватио да је то нездрава пословна логика за пројекат, па сам кад год је било могуће настојао да не користим такав дизајн. Али хајде да схватимо зашто је приступ руковању грешкама са таквом конструкцијом лош. Написао сам мали код да упоредим два приступа и направио референтне вредности за сваку опцију.
Код:
public bool ContainsHash()
{
bool result = false;
foreach (var file in _files)
{
var extension = Path.GetExtension(file);
if (_hash.Contains(extension))
result = true;
}
return result;
}
public bool ContainsHashTryCatch()
{
bool result = false;
try
{
foreach (var file in _files)
{
var extension = Path.GetExtension(file);
if (_hash.Contains(extension))
result = true;
}
if(!result)
throw new Exception("false");
}
catch (Exception e)
{
result = false;
}
return result;
}Резултати у .НЕТ Цоре 3.0 и Цоре 2.2 имају сличан резултат (.НЕТ Цоре 3.0):


Три цатцх чини код тежим за разумевање и повећава време извршавања вашег програма. Али ако вам је потребна ова конструкција, не би требало да убацујете оне линије кода за које се не очекује да ће обрађивати грешке – то ће олакшати разумевање кода. У ствари, није толико руковање изузецима оно што учитава систем, већ бацање самих грешака кроз конструкцију избацивања новог изузетка.
Бацање изузетака је спорије од неке класе која ће прикупити грешку у потребном формату. Ако обрађујете образац или неке податке и јасно знате која би грешка требало да буде, зашто је не обрадити?
Не би требало да пишете тхров нев Екцептион() конструкцију ако ова ситуација није изузетна. Руковање и бацање изузетка је веома скупо!!!
ТоЛовер, ТоЛоверИнвариант, ТоУппер, ТоУпперИнвариант
Током мог 5 година искуства рада на .НЕТ платформи, наишао сам на многе пројекте који су користили подударање стрингова. Такође сам видео следећу слику: постојало је једно Ентерприсе решење са много пројеката, од којих је сваки обављао различита поређења низова. Али шта треба користити и како то ујединити? У књизи ЦЛР преко Ц# од Рихтера, прочитао сам информацију да је метод ТоУпперИнвариант() бржи од ТоЛоверИнвариант().
Одломак из књиге:

Наравно, нисам веровао и одлучио сам да извршим неке тестове тада на .НЕТ Фрамеворк-у и резултат ме је шокирао - више од 15% повећања перформанси. Затим, по доласку на посао следећег јутра, показао сам ова мерења својим надређенима и дао им приступ изворном коду. Након тога, 2 од 14 пројеката су промењена да би се прилагодила новим мерењима, а с обзиром да су ова два пројекта постојала за обраду огромних Екцел табела, резултат је био више него значајан за производ.
Представљам вам и мере за различите верзије .НЕТ Цоре-а, тако да свако од вас може да изабере најоптималније решење. И само желим да додам да у компанији у којој радим користимо ТоУппер() за упоређивање стрингова.
Код:
public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3";
[Benchmark]
public bool ToLower()
{
return defaultString.ToLower() == defaultString.ToLower();
}
[Benchmark]
public bool ToLowerInvariant()
{
return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant();
}
[Benchmark]
public bool ToUpper()
{
return defaultString.ToUpper() == defaultString.ToUpper();
}
[Benchmark]
public bool ToUpperInvariant()
{
return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant();
}


У .НЕТ Цоре 3.0, повећање за сваку од ових метода је ~к2 и балансира имплементације међу собом.


Тиер Цомпилатион
У свом последњем чланку сам укратко описао ову функционалност, желео бих да исправим и допуним своје речи. Компилација на више нивоа убрзава време покретања вашег решења, али ви жртвујете то што ће делови вашег кода бити преведени у оптимизовану верзију у позадини, што може довести до малих трошкова. Са појавом НЕТ Цоре 3.0, време израде пројеката са омогућеном компилацијом нивоа се смањило и исправљене су грешке повезане са овом технологијом. Раније је ова технологија довела до грешака у првим захтевима у АСП.НЕТ Цоре-у и замрзнула се током прве градње у режиму компилације на више нивоа. Тренутно је подразумевано омогућен у .НЕТ Цоре 3.0, али можете да га онемогућите ако желите. Ако сте на позицији вође тима, старијег, средњег или сте шеф одељења, онда морате схватити да брз развој пројекта повећава вредност тима и ова технологија ће вам омогућити да уштедите време за оба програмера и време самог пројекта.
.НЕТ ниво горе
Надоградите своју .НЕТ Фрамеворк / .НЕТ Цоре верзију. Често, свака нова верзија пружа додатно побољшање перформанси и додаје нове функције.
Али које су тачно предности? Погледајмо неке од њих:
- .НЕТ Цоре 3.0 је представио Р2Р слике које ће смањити време покретања .НЕТ Цоре апликација.
- Са верзијом 2.2 појавила се Тиер Цомпилатион, захваљујући којој ће програмери трошити мање времена на покретање пројекта.
- Подршка за нове .НЕТ стандарде.
- Подршка за нову верзију програмског језика.
- Оптимизација, са сваком новом верзијом побољшава се оптимизација основних библиотека Цоллецтион/Струцт/Стреам/Стринг/Регек и још много тога. Ако прелазите са .НЕТ Фрамеворк-а на .НЕТ Цоре, одмах ћете добити велико повећање перформанси. Као пример, прилажем везу до неких оптимизација које су додате у .НЕТ Цоре 3.0:

Закључак
Када пишете код, вреди обратити пажњу на различите аспекте вашег пројекта и користити карактеристике вашег програмског језика и платформе да бисте постигли најбољи резултат. Било би ми драго да поделите своје знање о оптимизацији у .НЕТ-у.
Извор: ввв.хабр.цом
