TG Telegram Group & Channel
.NET Разработчик | United States America (US)
Create: Update:

День 2317. #ЗаметкиНаПолях
Почему Перебор List Быстрее, чем IList?

Если у нас есть List<T> и IList<T>, перебор List<T> быстрее, чем IList<T>. Почему?

Запустим бенчмарк

[MemoryDiagnoser]
public class Benchmark
{
private List<int> list
= [.. Enumerable.Range(0, 10_000)];
private IList<int> ilist
= [.. Enumerable.Range(0, 10_000)];

[Benchmark(Baseline = true)]
public int GetSumOfList()
{
var sum = 0;
foreach (var n in list) { sum += n; }
return sum;
}

[Benchmark]
public int GetSumOfIList()
{
var sum = 0;
foreach (var n in ilist) { sum += n; }
return sum;
}
}

Результаты будут примерно такие:
|Method       |Mean     |…|Allocated|
|-------------|--------:|…|--------:|
|GetSumOfList | 4.214 us|…| -|
|GetSumOfIList|19.508 us|…| 40 B|


40 байт

Откуда взялись эти 40 байт? Когда вы вызываете List<T>.GetEnumerator() (что будет в каждом цикле foreach), вы получаете структуру с именем Enumerator. Когда вы вызываете IList<T>.GetEnumerator(), вы получаете переменную типа IEnumerator, которая содержит упакованную версию указанного перечислителя. Это объясняет 40 байт выделения в куче и некоторую разницу в производительности.

Вызовы виртуальных методов
Но есть и второе измерение. Когда вы вызываете IList<T>.GetEnumerator(), он должен вызвать виртуальный метод, что медленнее, чем вызов невиртуального метода. По сути, кто-то должен проверить, какой конкретный тип действительно используется, а затем вызвать правильный метод. Это не относится к List<T>, который уже является конкретным типом.

Источник: https://steven-giesel.com/blogPost/c624c170-c16c-4414-8506-2ae25ba54df7/why-is-enumerating-over-list-faster-than-ilist

День 2317. #ЗаметкиНаПолях
Почему Перебор List Быстрее, чем IList?

Если у нас есть List<T> и IList<T>, перебор List<T> быстрее, чем IList<T>. Почему?

Запустим бенчмарк
[MemoryDiagnoser]
public class Benchmark
{
private List<int> list
= [.. Enumerable.Range(0, 10_000)];
private IList<int> ilist
= [.. Enumerable.Range(0, 10_000)];

[Benchmark(Baseline = true)]
public int GetSumOfList()
{
var sum = 0;
foreach (var n in list) { sum += n; }
return sum;
}

[Benchmark]
public int GetSumOfIList()
{
var sum = 0;
foreach (var n in ilist) { sum += n; }
return sum;
}
}

Результаты будут примерно такие:
|Method       |Mean     |…|Allocated|
|-------------|--------:|…|--------:|
|GetSumOfList | 4.214 us|…| -|
|GetSumOfIList|19.508 us|…| 40 B|


40 байт

Откуда взялись эти 40 байт? Когда вы вызываете List<T>.GetEnumerator() (что будет в каждом цикле foreach), вы получаете структуру с именем Enumerator. Когда вы вызываете IList<T>.GetEnumerator(), вы получаете переменную типа IEnumerator, которая содержит упакованную версию указанного перечислителя. Это объясняет 40 байт выделения в куче и некоторую разницу в производительности.

Вызовы виртуальных методов
Но есть и второе измерение. Когда вы вызываете IList<T>.GetEnumerator(), он должен вызвать виртуальный метод, что медленнее, чем вызов невиртуального метода. По сути, кто-то должен проверить, какой конкретный тип действительно используется, а затем вызвать правильный метод. Это не относится к List<T>, который уже является конкретным типом.

Источник: https://steven-giesel.com/blogPost/c624c170-c16c-4414-8506-2ae25ba54df7/why-is-enumerating-over-list-faster-than-ilist


>>Click here to continue<<

.NET Разработчик




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)