Re[6]: Оптимизация производительности
От: Qbit86 Кипр
Дата: 08.06.20 14:14
Оценка: 19 (2) +1 :)
Здравствуйте, hi_octane, Вы писали:

_>Ну так ты до этого не понял при чём там хипстеры и менеджеры


Так ведь это ж ты не понял, чем отличается монада от хламидомонады : ) С менеджерами невпопад, так как для них наоборот работает: если моноид — что-то сложное из матана, то всё, пора из инженеров в менеджеры.

_>Темы связаны потому что эти штуки друг без друга не ходят.




_>Когда дело доходить до оптимизации производительности или потребления памяти — часто проще всю монадную магию выкинуть и переписать с нуля на чистой императивщине.


Внезапно, код с моноидом в стиле как на видео будет быстрее, чем стандартная лапша с делегатами : )

Рассмотрим моноид из видео (C# пятилетней давности подойдёт, ничего нового из превью 9.0). Осторожно, возможна интоксикация жутким хтоническим матаном в мозг!
public interface IMonoid<T>
{
    T Identity { get; }
    T Combine(T left, T right);
}

internal readonly struct AdditiveInt32Monoid : IMonoid<int>
{
    public int Identity => 0;
    public int Combine(int left, int right) => left + right;
}

internal readonly struct MultiplicativeDecimalMonoid : IMonoid<decimal>
{
    public decimal Identity => 1m;
    public decimal Combine(decimal left, decimal right) => left * right;
}


И напишем свёртку, аналог Linq Aggregate:
internal static T Reduce<T, TMonoid>(this IEnumerable<T> items, TMonoid monoid)
    where TMonoid : IMonoid<T>
{
    if (items is null)
        throw new ArgumentNullException(nameof(items));

    T result = monoid.Identity;
    foreach (T item in items)
        result = monoid.Combine(result, item);

    return result;
}


Вызовы выглядят так:
[Benchmark(Baseline = true)]
public int ReduceIntegers() => s_integers.Reduce(default(AdditiveInt32Monoid));

[Benchmark]
public int AggregateIntegers() => s_integers.Aggregate(0, (left, right) => left + right);

[Benchmark]
public decimal ReduceDecimals() => s_decimals.Reduce(default(MultiplicativeDecimalMonoid));

[Benchmark]
public decimal AggregateDecimals() => s_decimals.Aggregate(1m, (left, right) => left * right);


Бенчмарк можно взять отсюда и убедиться самостоятельно.
Глаза у меня добрые, но рубашка — смирительная!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.