Pull to refresh

Comments 60

UFO just landed and posted this here

Заголовок статьи:

(Компилятор C#) & (.Net 6) => $"интерполяция строк работает быстрее".

Статья о том, <i>почему</i> быстрее. Не обязательно знать нюансы, чтобы воспользоваться. Но поможет, если надо оптимизировать критические секции.

UFO just landed and posted this here
Может такие элементарные вещи как "работа со строками" лучше самостоятельно писать в виде функций

Нет, не лучше. Элементарные вещи должны быть в общей библиотеке, чтобы программисты не бегали самостоятельно по граблям.

Просмотрел статью. А что нового и непонятного в этом синтаксисе? В нюансах разбираться не обязательно - это просто оптимизации, без которых код будет работать как раньше. С другой стороны, профессионалы оценят и заиспользуют zero allocation фичи при необходимости.

UFO just landed and posted this here
UFO just landed and posted this here

Ваше предложение — срань, еще и стилевые гайды нарушает.

UFO just landed and posted this here
Оно работает и что самое важное без копания по библиотекам .Net

… а оно работает консистентно с остальными местами, где Debug.Assert написан?

ни ужели кто то мешает написать так:
if (debug) Debug.Assert(validCertificate, $"Certificate: {GetCertificateDetails(cert)}");

Никто не мешает, только результат будет другой.

Ну вообще это лишний if в коде, а если этих ассертов много, то даже такие мелочи могут раздражать.


Кстати, компилятор/JIT может даже выкинуть операцию сравнения как и блок под ней, если debug — это константа.

Весь сахар появляеться потому что уровень разработчиков неуклонно падает, хорошему разработчику не нужен сахар чтобы создавать эффективный код, это у него на подкорке уже.

Сахар, вроде, никогда не нужен был, чтобы создавать эффективный код.

"Сахар" нужен не для того, чтобы создавать эффективный код, а для того, чтобы создавать читаемый код.

UFO just landed and posted this here
Пишу вам ответ и мне смешно — сложили две строки и описали это как проблему вселенского масштаба в статье на 1000 строк.

О какой проблеме вы говорите? Статья о форматировании, а не о конкатенации (хотя конкатенация — тоже штука веселая).


Вы не задавались вопросом: "Может проще NLog поставить из репозитория?"

Проще чем что?


PS


автор статьи ушатал 100 часов времени чтобы написать статью и еще столько же времени продирался сквозь логику классов

Что-то я не думаю, что Стивен Тауб потратил 100 часов на продирание через логику этих классов...

UFO just landed and posted this here

А где вы видите "помойку" в коде?


Debug.Assert(validCertificate, $"Certificate: {GetCertificateDetails(cert)}");

Или?


string FormatVersion(int major, int minor, int build, int revision)
=>  $"{major}.{minor}.{build}.{revision}";
UFO just landed and posted this here
Почитайте статью выше длиной в 100500 строк, о том как сделать быстрое сложение текста и переменных приведенных к типу STRING в одну строку.

Там такого нет. Вы точно читаете ту же статью, что и я?


(или вы не отличаете код, который пишет программист, от кода, который генерит компилятор?)

UFO just landed and posted this here
https://docs.microsoft.com/ru-ru/dotnet/core/compatibility/core-libraries/6.0/stringbuilder-append-evaluation-order

А можно пожалуйста из обсуждаемой статьи пример? Я не понимаю, о чем вы.


По второму вопросу, написал тест Debug.Assert в консольном приложении — все работает при наличии условного оператора проверки истинности, ничего не вызывается

То есть вы проверили, что если выражение под ассертом истинно, то сборка параметров строки ассерта не вызывается?


(я уж молчу про то, что в релизе ваш ассерт не вызовется никогда, и не важно, что у вас там во флаге)


Я Вам уже писал что NLog, так же все решает.

А при чем тут NLog, и что вообще он решает? Я им перестал пользоваться много лет назад, ушел на Serilog, и не жалею.

UFO just landed and posted this here
Изначально статья была видимо "багрепортом"

Нет, не была.


Данное описание из документации сделано по материалам исходной статьи.

Я продолжаю вас не понимать. Вы писали, что есть какая-то "помойка в коде" и синтаксический сахар, на который уходят дикие временные потери.


Можете привести хотя бы один пример этого?


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

Только в статье речь не о конкатенации строк, а о форматировании.


Логика во всем этом простая — проблема работы со строками у Microsoft существует и она ни как не решается.

Какая проблема? Где?


Трехкратное увеличение производетельности пусть положат себе в "карман" и ни кому не показывают.

Вам не надо — вы не пользуйтесь. А мне увеличение производительности без потери читаемости очень пригодится.

UFO just landed and posted this here
Вы из геймдева не можете "вылезти"?

Не могу. Никогда им не занимался, поэтому и не могу.


Мне постоянно приходилось работать с огромными массивами данных

Это все прекрасно, но какое это имеет отношение к тому, что в статье?

UFO just landed and posted this here
в реальной жизни все эти слова "попахивают":

Что там попахивает-то? Конкретно?


То есть весь этот синтаксический сахар с автоматическим приведением типов через интерфейсы просто на корню убивает производительность элементарных операций.

Гм. А почему убивает, если боксинг наоборот убрали?


Вообще, что за "автоматическое приведение типов через интерфейсы" вы конкретно имеете в виду в этом случае?

UFO just landed and posted this here
Да все вместе — и приведение типов и вызов перегруженных методов

Не понимаю. Что конкретно не так? Где конкретно проблема с производительностью?


Не абстрактно "где-то там в системе медленно", а в том коде, который приводится в статье — где там проблемы из-за приведения типов и/или перегруженных методов?


Откуда вообще в .NET проблема с производительностью на вызове перегруженных методов?


Вы посмотрите на это "издалека": создали такой "велосипед", что для сложения двух строк в одну бъются головой об стену

Нет, никто не бьется для этого головой об стену.


str1 + str2

Все. Какие проблемы? Где конкретно?


пишут статьи с радостными "вздохами" размером с простыню.

Статья — не про сложение строк, а про форматирование. Я столько раз это повторил, но вы продолжаете это игнорировать.


Народ уже вовсю возмущается концепцией DI из Net Core. Вы этого не замечали?, а я видел.

Нет, не замечал. Что конкретно за "концепция DI из Net Core"?

UFO just landed and posted this here
Может я чего то не понимаю, но по моему это те же штаны, но только в "профиль"

Не понимаете, да. Форматирование включает в себя сложение строк, но внутри себя сложнее. Например, надо строку форматирования распарсить, а все, что не строки, превратить в строку.


Вот здесь самое начало и вы что то видимо пропустили читая эту "простынь":

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

UFO just landed and posted this here

Пожалуйста, перечитайте статью (лучше — в оригинале). Вы явно ее не поняли.


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

UFO just landed and posted this here
а я вам о чем все это время пишу?

А я не понимаю, о чем вы пишете. Явно не о том, о чем статья.

UFO just landed and posted this here
Статья намекает на решение проблем с производительностью в самом тяжелом месте

Где?


но я ни когда не поставлю себе строковые функции

Что значит "не поставлю"? Какие функции?

UFO just landed and posted this here

Да и хрен с ним. В чем проблема с DI-то?

UFO just landed and posted this here
UFO just landed and posted this here

Нет, это не правильная ссылка. ASP.NET уже устарел. Сейчас актуален именно ASP.NET Core (и именно в нем есть описанный по ссылке DI).

Таки позанудствую.
В общем случае это неверно. Посмотрите на пространство имен, в котором определена основная часть DI: это — Microsoft.Extensions (сейчас для современных версий .NET это, по факту, часть стандартной библиотеки, и живет код из этого пространства имен в ее репозитории), а не Microsoft.AspNetCore (ну, а IServiceProvider вообще определен в System и существует с незапаметных времен: в старину он ЕМНИП использовался не для DI, а для визуального программирования — в связке с компонентами, которые в Дизайнере мышкой можно было двигать).
И Generic Host может использоваться для асинхронного выполнения любой нагрузки, зарегистрированной в контейнере DI как реализация IHostedService. Веб-приложение — внутренний класс GenericWebHostService — туда добавляет метод расширения ConfigureWebHost для IHostBuilder (или ConfigureWebHostDefaults, который его вызывает). Не будете вызывать эти методы — ваше приложение с DI к ASP.NET Core никакого отношения иметь не будет.
Правда, я не знаю, где, кроме ASP.NET Core этот шаблон Generic Host реально используется. Но при желании — можно.

Если занудствовать, то речь шла о противопоставлении ASP.NET Core обычному ASP.NET. Из этих двух, конкретный DI на основе IServiceProvider "есть" только в Core, а в ванильном ASP.NET его надо мучительно добавлять.

Прмеры из личного опыта:

  1. TCP сервис. очень удобно иметь общие подходы с Asp.Net Core

  2. Сервис, который Кафку читает, например

ЗЫ. Это разные сервис провайдеры. Просто количество комбинаций слов, описывающих этот функционал весьма ограниченно :) И в контексте нэймспэйса DependencyInjection выглядит весьма органично ;)

UFO just landed and posted this here

Ежу, может быть, и понятно. А мне — нет. О чем тогда речь? Приведите полный пример кода и объясните, как он работает. Потом сравните с тем, как работает код из статьи.

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

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


Правду слушать всегда не приятно, а критику уж тем более.

Пока что вы не высказали ни слова критики в мой адрес.


Ваши подчиненные не могут этого сделать

Действительно, не могут: у меня их нет.

У вас тут все кони смешались.

Давайте сразу разберем два основных кейса, которые я вижу по вашим коментариям:

  1. Разовое форматирование строки, которое не поддается батч процессингу

  2. Батч процессинг строк

Пункт 1:

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

Пункт 2:

Не используйте сахар, берем unsafe, работаем с ArrayPool, спанами и тд и тп в зависимости от необходимости. Никакой серебряной пули нет, как и одного решения всех проблем.

Обычно что бы объяснить что где использовать и разжевать есть сениоры и принципалы.

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

Кидаться какашками в геймдэв не совсем красиво, так как современная игровая платформа на бэкенде запросто переплюнет 99%+ "бизнес" проектов по нагруженности и объему данных. Давайте обсуждать вопросы предментно и без фанатизма пожалуйста :)

UFO just landed and posted this here

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

Это все хорошо, но большинство вызовов string.Format выполняется с загрузкой шаблона форматирования из ресурсов для локализации и соответственно такие вызовы не оптимизируются настолько глубоко или я не прав?

Насколько я понимаю, такая оптимизация создается только в момент компиляции, когда шаблон форматирования известен заранее.

При локализации шаблон форматирования известен только в момент выполнения, соответственно такая оптимизация не создается компилятором.

Насколько я прав?

Это все хорошо, но большинство вызовов string.Format выполняется с загрузкой шаблона форматирования из ресурсов для локализации

Я за последние пять, что ли, лет, не видел ни одного вызова string.Format, который бы что-то грузил из ресурсов (не считая кода в BCL и сторонних библиотеках). При этом работаю я со строками регулярно.

Ну я у себя в проекте format string гружу из ресурсов.

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

Можно использовать следующий паттерн:

sealed class MyDebug
{
    [Pure]
    public static MyDebug? Assert(bool condition) => condition ? null : new MyDebug();
    
    [DoesNotReturn]
    public void Message(string message) => Environment.FailFast(message);
    
    [DoesNotReturn]
    public void Message(string format, params object[] args) => Environment.FailFast(string.Format(format, args));
    
    MyDebug() {}
}

static void AssertExample()
{
    MyDebug.Assert(true);   // Warning: Return value of pure method is not used
    MyDebug.Assert(true)?.Message(Strings.SomeMessage);
    MyDebug.Assert(false)?.Message(Strings.ErrorMsgFormat, "condition is false");
}

Здесь используется фича в виде ?., которая разворачивается в код, в котором format string извлекается только при необходимости:

if (assertReturnValue != null)
{
    assertReturnValue.Message(...);
}

И атрибут [Pure], который генерит предупреждение при статическом анализе и не даёт забыть написать вызов метода Message.

Единственный недостаток такого подхода: это нестандартный велосипед.

Sign up to leave a comment.