Сэкономлю много времени. Можно открыть для себя MediatR и уже посоревноваться в специальной Олимпиаде по теме его обоснованного использования. Совершенно то же самое, только пользоваться проще. Там тебе и OpenClose из коробки. Дальше CQRS, EventSourcing etc...
В библиотеках, latency critical систем, например сериализации, маршрутизации и иной инфраструктуры -да. В остальном нет. В коде прикладного уровня, который писали мои команды,мы такого не допускали. Но задачи собеседования на то и задачи, чтобы тестировать экспертизу, понимание платформы и прочее. Все мы желаем работать с ребятами, которые понимают, что происходит в их коде.
Автор либо не работал со сложными проектами, либо хочет хайпануть. Выглядит как подвид борьбы с MediatR, типа сложно найти бизнес-логику, не понятно, что аффектят изменения и т. д. Зато доступны пайплайны, декораторы и аспектное программирование в целом за счёт понятного контракта по точкам подключения. Могу посоветовать автору только не называть антипаттерном то, что он не использует. От себя могу сказать, что приложения с IOC и MediatR гораздо легче приспосабливаются к изменениям, типа замены интеграций, встраивания трассировки и метрик, публикации событий и т. д. За счёт возросшей сложности, да. Ошибки рантайма - дёшево ловятся на автотестах. Проблема из ничего.
Вообще, в базовом раннере Cake Tool таски описаны в более простом DSL, но это на любителя. Мне нравится именно стиль Frosting. Да и подход без тулов вообще тоже на данный момент представляется удобным. По остальным вопросам не сравнивал, не буду утверждать, что Cake в чем -то превосходит nuke.
Кстати, да. Я этого не знал. На stackoverflow указано, что только для массива, длина которого известна на этапе компиляции, но это, по всей видимости, не так. Для динамический формируемых массивов — тоже.
1. Это не новость. Я уже не помню, почему было сделано иначе, но такой вариант тоже был.
1а. Не правда, этим N бенчмарк и управляет. Такой шаблон прямо предложен Акиньшиным в одной из статей по бенчмарку. Этот N позволяет явно задать количество повторяемых операций.
2б. Не нужно, это эмуляция реального кода. В реальном коде были бы именно асинхронные обращения к хранилищу. Со всеми его лагами и мусором.
2. В обоих случаях используется примитивный итератор без условий досрочного выхода. Какие оптимизации? Вы считаете, что IEnumerator, который вернет массив, даст прирост или что? Или потеряет на боксинге в интерфейс? Но насчет того, что надо было использовать один алгоритм — я согласен, Dictionary — артефакт. Смысла в конкурентных коллекциях в текущей реализации нет.
3. Мне кажется, это уже все обсуждалось выше. Во всяком случае, я признаю, что мог многое упустить. Все же более недели назад все было проделано уже.
Так цели абстрактно сравнить производительность конкретно двух подходов к рефлексии и не было, это же сделано до меня в статье, на которую я сослался в одном из первых абзацев.
В общем, я не знаю, о чем наш разговор — то, что Вы пишете — это прописные истины, это факт. Незыблемый факт. Я не буду с этим спорить. Согласен со всем на 100%.
Смотрите: EF не транслирует .Equals() в SQL, поэтому у вас нет никакого выбора. Если Вам надо делать сопоставление строк в памяти — это Equals, если в SQL — это == с приведением к верхнему регистру.
В остальном используйте .Equals всегда — он короче и понятней.
В остальном магии нет, разницы не может быть, так как сравнение с игнором кейса — это сравнение к приведением к какому-то кейсу. Если Вы не вызываете ToUpper() напрямую, это не значит, что он не вызывается под капотом.
Как Вы сравните строки с игнором регистра без приведения к одному регистру? Магии никакой выполняться не будет: кодам символов надо сопоставить другие коды символов в символьной таблице. Потом сравнить. Все.
Вот результат бенча, в котором берется коллекция примерно из 60 итемов и фильтруется через Equals и == по одному свойству. Потом приводится к массиву. ToLower показывает странно большую скорость на .netCore. но не ясно почему. Рекомендации еще с Рихтера были сравнивать всегда в верхнем кейсе. Надо разбираться.
Что мы видим? Мусора при == .ToUpper() больше, но скорость +- одинаковая. ToLower выглядит идеально, но это странно. Возможно, изменилась логика работы BCL с момента, когда я этим интересовался. Но сказанного в первых абзацев это все равно не отменяет.
Тест
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------- |---------:|----------:|----------:|-------:|------:|------:|----------:|
| ProcessWithToUpper | 3.466 us | 0.0337 us | 0.0281 us | 1.6937 | — | — | 5320 B |
| ProcessWithToLower | 1.649 us | 0.0291 us | 0.0273 us | 0.0877 | — | — | 280 B |
| ProcessWithEquls | 3.325 us | 0.0198 us | 0.0165 us | 0.0877 | — | — | 280 B |
Да, если можно пользоваться инструментом. Например на финальное кодревью надо присылать код в котором не падают тесты и так далее.
Тесты не падали. Вы пересмотрели свое отношение к ревью?
По второй цитате — Я не буду спорить с самим собой, потому, что я понимаю и помню контекст, в которых были написаны обе фразы. Они друг другу не противоречат. Если Вы воспринимаете их в другом ключе, перестройте аргумент линейно и закрыто — чтобы я ответил да или нет, и я озвучу свою позицию. Или уточню.
С моей точки зрения это минус — тратить время человека, если можно пользоваться инструментом.
Код ревью — тоже потеря времени? Или вы за все идеальное против всего реалистичного? Bugs happens.
Не увидели ли бы вы сразу узкое место, если воспользовались профайлером? Может сложность из-за этого?
Нет, сложностей нет. Есть ошибка и недоработка. К сожалению, совпало много фактов, которые не сильно усложняют работу по отдельности, но в сумме скрыли источник бага.
Его не нужно вычищать весь. Достаточного только узкие места. Я бы скорее отнес ваш код к инфраструктур не ому уровню чем к бизнес логике.
Тут Ваше мнение против моего, и мне не принципиально доказывать свое. Инфраструктурный это уровень или нет — вопрос философский. Я в таких спорах не участвую. Мой уровень отраслевой культуры мне этого не позволяет. Он низковат для онтологических обсуждений.
Не относится ли это рассуждение к любой оптимизации, в том числе и к замене рефлексии тоже?
Согласен, результатом этой мысли стало название статьи. Я не считаю, что добился изначальных целей, публикуя её.
Тут какая-то описка. Если это то о чем я думаю, то зачем вообще нужна статья, что в ней нового сказано?
Вам не нужна. Для Вас это банальность. А кому-то лишнее напоминание. По моим меркам интерес большой, я ожидал гораздо более прохладной реакции. )
По сути, в момент вызова свойства там же идет не вызов геттера, а некий перехват, который надо обработать.
Не может такой доступ к члена быть быстрей или хотя бы таким же по скорости как просто вызов экземплярного метода.
Так что в лучшем случае мы тут ускоряемся на гидрации экземпляра и теряем при каждом чтении свойств.
Типобезопасность, да и в принципе сложность исполнения я бы сказал тут в паритете… Так что не является ли использование DynamicObject «кашей из топора»?
Профайлер не был использован, потому что там профилировать нечего. Ошибка была найдена достаточно быстро благодаря комментариям.
Посыл и мораль статьи в том, что в реальной жизни заметить разницу между хорошим подходом и плохим достаточно сложно, и эффект от этого может разочаровывать.
А LINQ — это неизбежное зло в бизнес-логике, его просто так не вычистишь. Есть проекты в которых за спринт меняются требования и переписывается код по нескольку раз. Писать логику без LINQ — самоубийство. Оптимизировать логику в таких местах можно только после того, как продукт стабилизируется.
Таким образом я не задаюсь глобальным вопросом оптимизации, в данной статье рассматривался конкретно один кейс с конкретно одним результатом, который подтвердить из-за ошибки удалось не сразу. Если что-то осталось за рамками статьи, это не значит, что у меня это вызывает какие-то вопросы или требует заполнения пробелов. Это значит лишь то, что я не ставил своей целью писать еще одну книгу о перформансе.
С основной мыслью Вы согласны? Результат генерации рефлекшеном поведения необходимо компилировать в делегаты для ускорения и сокращения выброса мусора. Если согласны, то нам не о чем спорить.
1. По производительности в том числе они почти эквивалентны.
2. Мы сейчас идем в добри. Если мы храним данные в ДБ в верхнем регистре, мы избегаем одной из операций — приведения в верхний регистр строки в предикате. Экономим на вызове UPPER() в оракле или её эквивалента в других СУБД. Но мы должны быть уверены, что все данные туда добавят в верхнем регистре. Однажды кто-то нарушит эту схему, и будет баг. Если это бутылочное горлышко по перформансу, имеет смысл так сделать, если нет — можно заигнорировать. Хранить в нижнем регистре не надо, сравнение в верхнем всегда идет быстрей.
3. Есть вероятность того. Это зависит от многих факторов. Если таблицы большие, а предикаты будут примитивные, надо будет возвращать LINQ и через EF фильтровать. Если таблицы будут небольшие, надо будет смотреть, как это триггерит ГЦ. В общем случае лучше не строить предикат, если можно безболезненно вытащить всю таблицу в память.
Нет, дотнет от скуки всё на структуры переводит.
Сэкономлю много времени. Можно открыть для себя MediatR и уже посоревноваться в специальной Олимпиаде по теме его обоснованного использования. Совершенно то же самое, только пользоваться проще. Там тебе и OpenClose из коробки. Дальше CQRS, EventSourcing etc...
Никакой новизны в материале нет, сочувствую.
В библиотеках, latency critical систем, например сериализации, маршрутизации и иной инфраструктуры -да. В остальном нет. В коде прикладного уровня, который писали мои команды,мы такого не допускали. Но задачи собеседования на то и задачи, чтобы тестировать экспертизу, понимание платформы и прочее. Все мы желаем работать с ребятами, которые понимают, что происходит в их коде.
У меня такие задачи люди на скрининге перед собесом решают. Придётся менять задачу, становится слишком легко найти ответ :/
Автор либо не работал со сложными проектами, либо хочет хайпануть. Выглядит как подвид борьбы с MediatR, типа сложно найти бизнес-логику, не понятно, что аффектят изменения и т. д. Зато доступны пайплайны, декораторы и аспектное программирование в целом за счёт понятного контракта по точкам подключения. Могу посоветовать автору только не называть антипаттерном то, что он не использует. От себя могу сказать, что приложения с IOC и MediatR гораздо легче приспосабливаются к изменениям, типа замены интеграций, встраивания трассировки и метрик, публикации событий и т. д. За счёт возросшей сложности, да. Ошибки рантайма - дёшево ловятся на автотестах. Проблема из ничего.
1а. Не правда, этим N бенчмарк и управляет. Такой шаблон прямо предложен Акиньшиным в одной из статей по бенчмарку. Этот N позволяет явно задать количество повторяемых операций.
2б. Не нужно, это эмуляция реального кода. В реальном коде были бы именно асинхронные обращения к хранилищу. Со всеми его лагами и мусором.
2. В обоих случаях используется примитивный итератор без условий досрочного выхода. Какие оптимизации? Вы считаете, что IEnumerator, который вернет массив, даст прирост или что? Или потеряет на боксинге в интерфейс? Но насчет того, что надо было использовать один алгоритм — я согласен, Dictionary — артефакт. Смысла в конкурентных коллекциях в текущей реализации нет.
3. Мне кажется, это уже все обсуждалось выше. Во всяком случае, я признаю, что мог многое упустить. Все же более недели назад все было проделано уже.
В общем, я не знаю, о чем наш разговор — то, что Вы пишете — это прописные истины, это факт. Незыблемый факт. Я не буду с этим спорить. Согласен со всем на 100%.
Я могу сослаться только на недопонимание.
В остальном используйте .Equals всегда — он короче и понятней.
В остальном магии нет, разницы не может быть, так как сравнение с игнором кейса — это сравнение к приведением к какому-то кейсу. Если Вы не вызываете ToUpper() напрямую, это не значит, что он не вызывается под капотом.
Как Вы сравните строки с игнором регистра без приведения к одному регистру? Магии никакой выполняться не будет: кодам символов надо сопоставить другие коды символов в символьной таблице. Потом сравнить. Все.
Вот результат бенча, в котором берется коллекция примерно из 60 итемов и фильтруется через Equals и == по одному свойству. Потом приводится к массиву. ToLower показывает странно большую скорость на .netCore. но не ясно почему. Рекомендации еще с Рихтера были сравнивать всегда в верхнем кейсе. Надо разбираться.
Что мы видим? Мусора при == .ToUpper() больше, но скорость +- одинаковая. ToLower выглядит идеально, но это странно. Возможно, изменилась логика работы BCL с момента, когда я этим интересовался. Но сказанного в первых абзацев это все равно не отменяет.
|------------------- |---------:|----------:|----------:|-------:|------:|------:|----------:|
| ProcessWithToUpper | 3.466 us | 0.0337 us | 0.0281 us | 1.6937 | — | — | 5320 B |
| ProcessWithToLower | 1.649 us | 0.0291 us | 0.0273 us | 0.0877 | — | — | 280 B |
| ProcessWithEquls | 3.325 us | 0.0198 us | 0.0165 us | 0.0877 | — | — | 280 B |
Тесты не падали. Вы пересмотрели свое отношение к ревью?
По второй цитате — Я не буду спорить с самим собой, потому, что я понимаю и помню контекст, в которых были написаны обе фразы. Они друг другу не противоречат. Если Вы воспринимаете их в другом ключе, перестройте аргумент линейно и закрыто — чтобы я ответил да или нет, и я озвучу свою позицию. Или уточню.
Код ревью — тоже потеря времени? Или вы за все идеальное против всего реалистичного? Bugs happens.
Нет, сложностей нет. Есть ошибка и недоработка. К сожалению, совпало много фактов, которые не сильно усложняют работу по отдельности, но в сумме скрыли источник бага.
Тут Ваше мнение против моего, и мне не принципиально доказывать свое. Инфраструктурный это уровень или нет — вопрос философский. Я в таких спорах не участвую. Мой уровень отраслевой культуры мне этого не позволяет. Он низковат для онтологических обсуждений.
Согласен, результатом этой мысли стало название статьи. Я не считаю, что добился изначальных целей, публикуя её.
Вам не нужна. Для Вас это банальность. А кому-то лишнее напоминание. По моим меркам интерес большой, я ожидал гораздо более прохладной реакции. )
По сути, в момент вызова свойства там же идет не вызов геттера, а некий перехват, который надо обработать.
Не может такой доступ к члена быть быстрей или хотя бы таким же по скорости как просто вызов экземплярного метода.
Так что в лучшем случае мы тут ускоряемся на гидрации экземпляра и теряем при каждом чтении свойств.
Типобезопасность, да и в принципе сложность исполнения я бы сказал тут в паритете… Так что не является ли использование DynamicObject «кашей из топора»?
Посыл и мораль статьи в том, что в реальной жизни заметить разницу между хорошим подходом и плохим достаточно сложно, и эффект от этого может разочаровывать.
А LINQ — это неизбежное зло в бизнес-логике, его просто так не вычистишь. Есть проекты в которых за спринт меняются требования и переписывается код по нескольку раз. Писать логику без LINQ — самоубийство. Оптимизировать логику в таких местах можно только после того, как продукт стабилизируется.
Таким образом я не задаюсь глобальным вопросом оптимизации, в данной статье рассматривался конкретно один кейс с конкретно одним результатом, который подтвердить из-за ошибки удалось не сразу. Если что-то осталось за рамками статьи, это не значит, что у меня это вызывает какие-то вопросы или требует заполнения пробелов. Это значит лишь то, что я не ставил своей целью писать еще одну книгу о перформансе.
С основной мыслью Вы согласны? Результат генерации рефлекшеном поведения необходимо компилировать в делегаты для ускорения и сокращения выброса мусора. Если согласны, то нам не о чем спорить.
2. Мы сейчас идем в добри. Если мы храним данные в ДБ в верхнем регистре, мы избегаем одной из операций — приведения в верхний регистр строки в предикате. Экономим на вызове UPPER() в оракле или её эквивалента в других СУБД. Но мы должны быть уверены, что все данные туда добавят в верхнем регистре. Однажды кто-то нарушит эту схему, и будет баг. Если это бутылочное горлышко по перформансу, имеет смысл так сделать, если нет — можно заигнорировать. Хранить в нижнем регистре не надо, сравнение в верхнем всегда идет быстрей.
3. Есть вероятность того. Это зависит от многих факторов. Если таблицы большие, а предикаты будут примитивные, надо будет возвращать LINQ и через EF фильтровать. Если таблицы будут небольшие, надо будет смотреть, как это триггерит ГЦ. В общем случае лучше не строить предикат, если можно безболезненно вытащить всю таблицу в память.