Re[10]: Несколько соображений по дизайну C#
От: Sinix  
Дата: 16.07.16 08:04
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Проект не забросили, просто основное что планировали уже добавили.


Ну у меня идей полно, могу подкинуть
Re[14]: Несколько соображений по дизайну C#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.07.16 08:17
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Это уже лирика, естественно правильный выбор алгоритма решает. При этом поиск минимального элемента — вполне практичный алгоритм, и имеет вполне реальные применения.


Linq писался под SQL, а там Min Max немного другой
https://msdn.microsoft.com/ru-ru/library/bb548726(v=vs.110).aspx

Одна из реализаций

public static Nullable<double> Max<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, Nullable<double>> selector
)


То есть обычная схема это получение максимального элемента.
var МаксимальноеЗначение=Список.Where(значение =>значение!=null).Max(значение =>значение.СравниваемоеПоле);
//var МаксимальноеЗначение=Список.DefaultIfEmpty().Max(p => p == null ? 0 : p.X)

if (МаксимальноеЗначение!=null)
   Result=Список.Where(значение =>значение .СравниваемоеПоле==МаксимальноеЗначение).First();


Так все и поступают.
Но если ты хочешь сократить вычисления, или сделать вычисления аналогичными C++ min_element то никто не мешает тебе сделать расширения.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 16.07.2016 8:56 Serginio1 . Предыдущая версия .
Re[14]: Несколько соображений по дизайну C#
От: Sinix  
Дата: 16.07.16 08:57
Оценка: 44 (2)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Там кстати ещё и в других местах подобная генерация.


Ну так все только советуют, как делать — так ой. И я в том числе


S>>Разница в 20% не окупает 5 килострок лишнего кода.

IT>>Генерируемый код вообще не требует никакой поддержки. Поддержки требует код генератора. В данном случае код генератора прост как угол дома. Вообще-то, precompile time генерация кода самый простой и на сегодняшний день доступный вид метапрограммирования. Так что твои жалобы на сложность поддержки такого решения я не разделяю.


Ну вот тебе точка зрения хардкорного этерпрайз-разработчика: любая новая строчка кода содержит возможный баг.

Если у нас есть риск пропустить баг, надо этот риск снижать, простейший способ — юнит-тесты + интеграционные тесты + code coverage (не как самоцель, не дай бог) как индикатор мест, которые используются очень редко и могут выстрелить в самый неприятный момент.
Т.е. сгенерен код, не сгенерен — один фиг поддерждивать. Только баг в сгенеренном куда проще пропустить, поэтому и покрывать тестами надо тщательнее


S>>Тем более, что когда перфоманс _действительно_ важен, узкие места просто переписываются врукопашную с сменой алгоритма. Как вариант, достаточно один раз отсортировать список и загонять дальше данные бинарным поиском.

EP>Это уже лирика, естественно правильный выбор алгоритма решает. При этом поиск минимального элемента — вполне практичный алгоритм, и имеет вполне реальные применения.
Неа. Это яд мозга от явы — любовь к сбору простейших алгоритмов из отдельных кирпичиков где надо и не надо. Вот тебе результаты:
структуры
          Method |      Median |     StdDev | Scaled |         Min | Lnml(min) | Lnml(max) |         Max |
---------------- |------------ |----------- |------- |------------ |---------- |---------- |------------ |
      MinCodeJam |   7.8484 us |  0.7074 us |   1.00 |   7.5465 us |      1.00 |      1.00 |  15.3949 us |
        MinNaive | 146.5534 us | 16.9635 us |  18.67 | 138.2523 us |     18.63 |     18.63 | 416.2661 us |
         MyMinBy |   9.3577 us |  1.4898 us |   1.19 |   9.0558 us |      1.22 |      1.22 |  20.8284 us |
 MyMinByComparer |  10.8670 us |  0.5786 us |   1.38 |  10.5651 us |      1.36 |      1.36 |  20.2247 us |
    MinDoneRight |   0.9056 us |  0.8442 us |   0.12 |   0.9056 us |      0.13 |      0.13 |  15.3949 us |


строки
          Method |        Median |     StdDev | Scaled |           Min | Lnml(min) | Lnml(max) |           Max |
---------------- |-------------- |----------- |------- |-------------- |---------- |---------- |-------------- |
      MinCodeJam |   143.9876 us |  6.2432 us |   1.00 |   136.1392 us |      1.00 |      1.00 |   192.2853 us |
        MinNaive | 1,998.1677 us | 47.3561 us |  13.88 | 1,892.6674 us |     13.87 |     13.87 | 2,263.6543 us |
         MyMinBy |    15.0930 us |  0.9107 us |   0.10 |    14.7912 us |      0.10 |      0.10 |    27.7712 us |
 MyMinByComparer |   136.7430 us | 14.7119 us |   0.95 |   135.2337 us |      0.97 |      0.97 |   283.1455 us |
    MinDoneRight |   123.4611 us |  1.0342 us |   0.86 |   122.5555 us |      0.86 |      0.86 |   133.4225 us |


код.

Это полностью корректный код, см CheckCorrectness. Ну, как корректный, в реализации CodeJam баг: если свойства null, то возвращается последний элемент, а не первый. Для не-null наоборот, first wins. Пришлось повторять. Это к вопросу про подход в лоб vs "думать, затем делать".

Так вот, для общего случая правильно написанный универсальный метод чуть быстрее. В лучшем — в 10 раз быстрее за счёт правильного выбора алгоритма, см на MyMinBy. В самом худшем — на 20-25% медленнее. Один подвох: рукопашный вариант в этом самом худшем случае в 8 раз быстрее. Отсюда — правильный подход: время, затраченное на кодогенерацию перекинуть на поиск и починку узких мест (а это так и так делать приходится).

Ну и разумеется в реальном коде эти 8 раз выигрыша превращаются в 3-5% разницы, остальной код тоже делом занят
Т.е. до тех пор, пока оптимизация не даёт выигрыш в разы, смысла в лишних килостроках нет.



EP>Вот обычно со стороны евангелистов C# в КСВ темах звучат тезисы мол ну и что что медленно, зато мы вас переархитектурим/переалгоритмим и т.п. Да пока вы будете "с памятью возится" мы получим 2000% ускорения и т.п. Да и вообще всё в базу упирается.

Ты меньше евангелистов курильщика слушай. Для ситуации "максимум перфоманса любой ценой" евангелист здорового человека
1. Меняет алгоритмы.
2. Использует оптимизированные библиотеки и пофиг на чём они написаны.

Для всяких числомолотилок / кодеков / etc шарп на сегодня имеет смысл только для поиграться — ни библиотек, ни быстрой арифметики, векторизация в зачаточном состоянии и тыды и тыпы. Задел для поменять ситуацию есть, .net native позволяет сравнять перфоманс с плюсами. Но это дело лет на 5-6 в лучшем случае, а мы про здесь и сейчас говорим.

Так вот. Для всего остального кроме числомолотилок перфоманс сам по себе не так важен. Люди начинают смотреть на стоимость написания / поддержки кода. И тут шарп вырывается вперёд даже в инди-играх на юнити с далеко не самым лучшим рантаймом mono (про AAA-тайтлы не будем, там всё понятно).

Ну а в энтерпрайзе / десктопе / вебе / мобилках плюсы потихоньку сдают позиции буквально всему. Ибо дорого.


EP>Конечно можно генерировать и напрямую, но фишка в том что из одного исходника (.org файла) есть экспорт помимо RSDN ещё и в форматы типа PDF, HTML, LaTeX, ODT, etc — и везде свои таблицы.

На самом деле тут правильный подход — markdown. Rsdn, пожалуй, последний серьёзный ресурс для дотнет-разработчиков, где он всё ещё не используется.
Re[15]: Markdown
От: Qbit86 Кипр
Дата: 16.07.16 09:07
Оценка: :)
Здравствуйте, Sinix, Вы писали:

S>На самом деле тут правильный подход — markdown. Rsdn, пожалуй, последний серьёзный ресурс для дотнет-разработчиков, где он всё ещё не используется.


+1729. Две кружки квасу этому господину.
Глаза у меня добрые, но рубашка — смирительная!
Re[14]: Несколько соображений по дизайну C#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.07.16 15:14
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Ради интереса, я что смешного в https://rsdn.ru/forum/dotnet/6506570.1
Автор: Serginio1
Дата: 16.07.16

То есть я тебе разъясняю, как работает мин макс, а у тебя это вызывает смех?
Я волнуюсь за тебя. Скоро тебе книгу по C# покажешь ты и умрешь со смеху
и солнце б утром не вставало, когда бы не было меня
Отредактировано 16.07.2016 16:39 Serginio1 . Предыдущая версия . Еще …
Отредактировано 16.07.2016 15:18 Serginio1 . Предыдущая версия .
Re[15]: Несколько соображений по дизайну C#
От: Evgeny.Panasyuk Россия  
Дата: 16.07.16 16:16
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Вот тебе результаты:


Интересно, а почему в этот раз всё примерно вдвое быстрей? По идеи должно же быть наоборот, из-за branch misprediction. Или это другая машина?
И что там за числа у CompetitionBenchmark?

S>код.


public static T MyMinByComparer<T, TValue>(
            this IEnumerable<T> source,
            Func<T, TValue> selector,
            IComparer<TValue> comparer = null)
{
    comparer = comparer ?? Comparer<TValue>.Default;

Это специально так сделано? Чтобы компилятору было проще понять что там по умолчанию?

S>Так вот, для общего случая правильно написанный универсальный метод чуть быстрее.


Так то с чем ты сравниваешь в CodeJam тоже универсально жеж.

S> В лучшем — в 10 раз быстрее за счёт правильного выбора алгоритма, см на MyMinBy.


Структура алгоритма (MyMinBy vs MyMinByComparer) одинаковая, отличие только в использовании костыля Operators, и в том что он жёстко зашит в коде, а не приходит извне.

S>В самом худшем — на 20-25% медленнее. Один подвох: рукопашный вариант в этом самом худшем случае в 8 раз быстрее.


В котором даже нет селектора, не говоря уже об IEnumerable.

S>Отсюда — правильный подход: время, затраченное на кодогенерацию перекинуть на поиск и починку узких мест (а это так и так делать приходится).


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

S>Ну и разумеется в реальном коде эти 8 раз выигрыша превращаются в 3-5% разницы, остальной код тоже делом занят


Остальной код пишется теми же средствами, в нём те же самые "разы проигрыша"

EP>>Конечно можно генерировать и напрямую, но фишка в том что из одного исходника (.org файла) есть экспорт помимо RSDN ещё и в форматы типа PDF, HTML, LaTeX, ODT, etc — и везде свои таблицы.

S>На самом деле тут правильный подход — markdown.

Экспорт из Org-Mode в Markdown тоже имеется. Но речь же не столько про разметку, сколько про автоматизацию создания документов с "живыми" фрагментами кода на разных языках порождающие разноформатный результат (таблицы, графики, формулы и т.п.). Как альтернатива например Jupyter. То есть я про то что называется Reproducible Research.
https://www.youtube.com/watch?v=1-dUkyn_fZA
Re[16]: Несколько соображений по дизайну C#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.07.16 16:46
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>
EP>public static T MyMinByComparer<T, TValue>(
EP>            this IEnumerable<T> source,
EP>            Func<T, TValue> selector,
EP>            IComparer<TValue> comparer = null)
EP>{
EP>    comparer = comparer ?? Comparer<TValue>.Default;
EP>

EP>Это специально так сделано? Чтобы компилятору было проще понять что там по умолчанию?

Это конструкция заменяет
 if (comparer==null) comparer = Comparer<TValue>.Default;


Боюсь за тебя, ты же сейчас на смех изойдешь
и солнце б утром не вставало, когда бы не было меня
Re[11]: Несколько соображений по дизайну C#
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 16.07.16 18:03
Оценка:
Здравствуйте, Sinix, Вы писали:

AVK>>Проект не забросили, просто основное что планировали уже добавили.

S>Ну у меня идей полно, могу подкинуть

Подкидывай конечно.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[17]: Несколько соображений по дизайну C#
От: Evgeny.Panasyuk Россия  
Дата: 16.07.16 18:21
Оценка: :))
Здравствуйте, Serginio1, Вы писали:

EP>>Это специально так сделано? Чтобы компилятору было проще понять что там по умолчанию?

S>Это конструкция заменяет ...
S> Боюсь за тебя, ты же сейчас на смех изойдешь

Ты в очередной раз не понял о чём речь "Буквы не читай, сообщения пиши"
Вопрос не про значение конструкции. А про мотивацию использования именно её, вместо той которая была в CodeJam — это например вполне может влиять на оптимизатор
Re[18]: Несколько соображений по дизайну C#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.07.16 18:58
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Serginio1, Вы писали:


EP>>>Это специально так сделано? Чтобы компилятору было проще понять что там по умолчанию?

S>>Это конструкция заменяет ...
S>> Боюсь за тебя, ты же сейчас на смех изойдешь

EP>Ты в очередной раз не понял о чём речь "Буквы не читай, сообщения пиши"

EP>Вопрос не про значение конструкции. А про мотивацию использования именно её, вместо той которая была в CodeJam — это например вполне может влиять на оптимизатор

В CodeJam сделано через перегрузку методов в итоге 2 метода,

Sinix сделал один метод с дефолтным параметром

public static T MyMinByComparer<T, TValue>(
            this IEnumerable<T> source,
            Func<T, TValue> selector,
            IComparer<TValue> comparer = null)
{
    comparer = comparer ?? Comparer<TValue>.Default;


Зачем писать кучу перегрузок, если можно использовать 1 метод с дефолтными параметрами?
Кстати мне как нужно в своей компоненте использования классов .Net в нативе как раз использовать дефолтные параметры.
Это я сам с собой. Не обращай внимания. Но можешь еще посмеяться. Я только рад.
и солнце б утром не вставало, когда бы не было меня
Re[19]: Default values
От: Qbit86 Кипр
Дата: 16.07.16 19:07
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S> Зачем писать кучу перегрузок, если можно использовать 1 метод с дефолтными параметрами?


Насколько я помню, то ли Code Analysis aka FxCop, то ли ReSharper рекомендуют избегать умолчальных значений в пользу перегрузок. Аргументация вроде заключалась в том, что не все языки поддерживают значения по умолчанию.
Глаза у меня добрые, но рубашка — смирительная!
Re[20]: Default values
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.07.16 19:22
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Serginio1, Вы писали:


S>> Зачем писать кучу перегрузок, если можно использовать 1 метод с дефолтными параметрами?


Q>Насколько я помню, то ли Code Analysis aka FxCop, то ли ReSharper рекомендуют избегать умолчальных значений в пользу перегрузок. Аргументация вроде заключалась в том, что не все языки поддерживают значения по умолчанию.

Так на самом деле он вызывается как полный. Просто в других языках нужно использовать все аргументы.
Дефолтные параметры как раз и были сделаны из-за критики перегрузок.
Зачем плодить кучу методов если их заменяет один с дефолтными параметрами?

Кстати некоторые языки не поддерживают перегрузки. И лучше иметь различные по имени методы.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 16.07.2016 20:47 Serginio1 . Предыдущая версия .
Re[20]: Default values
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.07.16 20:01
Оценка:
Здравствуйте, Qbit86, Вы писали:

S>> Зачем писать кучу перегрузок, если можно использовать 1 метод с дефолтными параметрами?


Q>Насколько я помню, то ли Code Analysis aka FxCop, то ли ReSharper рекомендуют избегать умолчальных значений в пользу перегрузок. Аргументация вроде заключалась в том, что не все языки поддерживают значения по умолчанию.


Это говорится в FDG.
The God is real, unless declared integer.
Re[21]: FDG
От: Qbit86 Кипр
Дата: 16.07.16 20:03
Оценка:
Здравствуйте, netch80, Вы писали:

Q>>Насколько я помню, то ли Code Analysis aka FxCop, то ли ReSharper рекомендуют избегать умолчальных значений в пользу перегрузок...

N>Это говорится в FDG.

...Значит, в Code Analysis aka FxCop.
Глаза у меня добрые, но рубашка — смирительная!
Re[20]: Default values
От: Sinix  
Дата: 17.07.16 08:57
Оценка: +1
Здравствуйте, Qbit86, Вы писали:


Q>Насколько я помню, то ли Code Analysis aka FxCop, то ли ReSharper рекомендуют избегать умолчальных значений в пользу перегрузок. Аргументация вроде заключалась в том, что не все языки поддерживают значения по умолчанию.


Ну да. Тут я целиком и полностью согласен с FDG: в общем случае default parameter values обходятся достаточно дорого в плане поддержки, читаем вот эту простыню. В простыне кстати забыты грабли при использовании default values в virtual-методах, тоже удовольствие то ещё.


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

В перфтестах поддерживается интеграция с ms text, nunit, xunit (для начала), запуск из консоли плюс отдельный раннер для тестирования перфтестов. Каждый из классов расположен в своём проекте и выглядит примерно так.

Параметр config в каждом методе optional.

Можно добавить перегрузки без этого параметра, но при необходимости поправить комментарий придётся просматривать уже 30, а не 15 методов.
Можно признать поражение и подрубить кодогенерацию, но остаются раннеры для консоли и self-testing, которые немного отличаются от остальных.

Разумеется, это частный случай и приводить его как оправдание для всех остальных вариантов точно не стоит
Re[12]: Несколько соображений по дизайну C#
От: Sinix  
Дата: 17.07.16 09:27
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Подкидывай конечно.

done
Автор: Lexey
Дата: 13.05.16
Re[16]: Несколько соображений по дизайну C#
От: Sinix  
Дата: 17.07.16 09:49
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Интересно, а почему в этот раз всё примерно вдвое быстрей? По идеи должно же быть наоборот, из-за branch misprediction. Или это другая машина?


Опс, другая машина. Первые тесты на ноутбуке запускал, вторые — на полноценной дев-машине. Некритично, т.к. сравнивать в любом случае надо относительное время (столбцы scaled или lognormal scaled (lnml)). Абсолютное время легко может меняться на ±5% из-за intel speed step даже на взрослых машинах, на ноутбуках и планшетках в этом плане полный кошмар.


EP>И что там за числа у CompetitionBenchmark?

Эт которые
    [CompetitionBaseline] 
    public Data MinCodeJam() => _data.MinBy(x => x.StructField); 

    [CompetitionBenchmark(18.45, 19.60)] // <=
    public Data MinNaive() => _data.OrderBy(x => x.StructField).FirstOrDefault(); 

    [CompetitionBenchmark(1.18, 1.33)]   // <=
    public Data MyMinBy() => _data.MyMinBy(x => x.StructField);

?
Лучшее и худшее время относительно baseline за всю историю запусков, заполняется автоматически в том числе и по результатам с билдсервера.
Для микробенчмарков время берётся как среднегеометрическое от всех семплов (оно же — mean для lognormal distribution) (по умолчанию при каждом запуске каждый метод замеряется 300 раз емнип), как найдётся вариант лучше, можно будет поменять.

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

EP>Это специально так сделано? Чтобы компилятору было проще понять что там по умолчанию?

Неа, jit-компилятор никак не учитывает default values


S>>Так вот, для общего случая _правильно написанный_ универсальный метод чуть быстрее.

EP>Так то с чем ты сравниваешь в CodeJam тоже универсально жеж.
Выделил


S>> В лучшем — в 10 раз быстрее за счёт правильного выбора алгоритма, см на MyMinBy.

EP>Структура алгоритма (MyMinBy vs MyMinByComparer) одинаковая, отличие только в использовании костыля Operators, и в том что он жёстко зашит в коде, а не приходит извне.
Ну да. Operators используют ordinal-сравнение для строк, без учёта культуры, что примерно на порядок быстрее. В 99% случаев требуется именно это, когда явно нужна культура, никто не запрещает передать другой comparer.


S>>В самом худшем — на 20-25% медленнее. Один подвох: рукопашный вариант в этом самом худшем случае в 8 раз быстрее.

EP>В котором даже нет селектора, не говоря уже об IEnumerable.
А смысл оставлять всю эту радость, если для нас действительно важна производительность?


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

Угу. Одна проблема, для дотнета это дело лет 5-6 в лучшем случае, а обсуждаем то, что есть здесь и сейчас


S>>Ну и разумеется в реальном коде эти 8 раз выигрыша превращаются в 3-5% разницы, остальной код тоже делом занят

EP>Остальной код пишется теми же средствами, в нём те же самые "разы проигрыша"
Ну это от команды зависит. Где-то разы проигрыша, где-то код регулярно профилируется и одной локальной правкой код заметно не ускоришь, т.к. всё и так уже близко к идеалу.
Re: Несколько соображений по дизайну C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.16 20:42
Оценка: :)
Здравствуйте, Gattaka, Вы писали:

G>Что думаете? Есть ли основания у подобных претензий?


Думаю, что тебе нужно учить Хаскель. Там почти все как ты хочешь.

И комьюнити там из таких же извращенцев
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Несколько соображений по дизайну C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.16 20:59
Оценка: :)
Здравствуйте, AlexRK, Вы писали:

ARK>Кстати, я это считаю убогим решением. Слишком похоже на вызов. Лучше было бы обязать писать "delegate" или что-то подобное.


Делегат слишком коротко! Кроме того это и не делегат вовсе. Надо заставлять писать:
give me delegate of Action<Int> foo.Bar

и сразу все понятно будет!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Несколько соображений по дизайну C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.07.16 21:00
Оценка:
Здравствуйте, Kolesiki, Вы писали:

K>Претензии на пустом месте — от непонимания того, что код не только пишут, но и читают. В том числе и компиляторы.


Компилятор то все сможет прочесть. Были бы четкие правила. Вопрос только в человеке.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.