yet another dev
206 subscribers
124 photos
1 video
94 links
Yet another channel of a backend developer living in Serbia.

Очередной канал обычного бэкенд разработчика живущего в Сербии.

Связь: @alexeyfv
Download Telegram
Используйте индексаторы вместо методов LINQ

Это часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1826: Use property instead of Linq Enumerable method.

Описание правила

Правило рекомендует не использовать методы First(), Last(), Count() из LINQ с IReadOnlyList<T>:

IReadOnlyList<string> list = ["str1", "str2", "str3"];
var first = list.First(); // CA1826
var last = list.Last(); // CA1826
var count = list.Count(); // CA1826


Вместо этого стоит использовать индексатор или свойство Count:

IReadOnlyList<string> list = ["str1", "str2", "str3"];
var first = list[0];
var last = list[^1];
var count = list.Count;


Анализ производительности

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

Как видно, разница есть. Но она совсем небольшая — всего несколько микросекунд на моём ноутбуке.

Стоит ли заморачиваться?

В большинстве случаев нет. Прирост производительности минимальный. Но если вы пишете высокопроизводительный код или используете LINQ методы в цикле — возможно код стоит отрефакторить.
👍6
Скриптинг на C# всё ближе

Microsoft продолжает двигаться в сторону упрощения C#. В свежем видео они показали функционал, позволяющий запускать cs-файлы без sln и csproj. Фича доступна в Preview версии .NET 10.

Пример:

dotnet run hello.cs


Работает даже с NuGet-пакетами прямо в файле:

#:package Spectre.Console@0.50
#:package Spectre.Console.Cli@0.50

using Spectre.Console;

AnsiConsole.Markup("[underline red]Hello[/] [underline green]World![/]");


Как выглядит результат - на скриншоте.

Пока не совсем ясно, будет ли возможность запускать такие файлы в Docker, то есть через Runtime, а не через SDK.
👍8👎2
StringBuilder: избегайте ToString при использовании Append

Read on website.
Читать на сайте.

Это новая часть серии, в которой я разбираю правила качества кода .NET с точки зрения производительности. Сегодня поговорим про CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder.

Описание правила

Правило рекомендует не преобразовывать значения в строку при вызове методов Append или Insert.

var i = 123;
var sb = new StringBuilder();
sb.Append(i.ToString()); // CA1830


Вместо этого лучше передать значение напрямую:

var i = 123;
var sb = new StringBuilder();
sb.Append(i);


Это правило касается примитивных типов вроде byte, short, int, double, long и других.

Анализ производительности

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

Разница по времени — небольшая: около 5 микросекунд на моём ноутбуке. Разница по памяти более заметная: около 20 кБ.

Как работает эта оптимизация?

Когда вы используете метод Append(int), под капотом StringBuilder вызываются методы AppendSpanFormattable<T> и InsertSpanFormattable<T>.

Например, упрощённая версия AppendSpanFormattable<T> выглядит так:

private StringBuilder AppendSpanFormattable<T>(T value) where T : ISpanFormattable
{
if (value.TryFormat(
RemainingCurrentChunk,
out int charsWritten,
format: default,
provider: null))
{
m_ChunkLength += charsWritten;
return this;
}

return Append(value.ToString());
}


Этот метод использует интерфейс ISpanFormattable.TryFormat, чтобы записать значение напрямую во внутренний буфер StringBuilder как Span<char>. Это позволяет: избежать аллокации строки; упаковки (boxing) и вызова виртуального метода ToString().

Стоит ли заморачиваться?

Скорее да. Даже если не брать в расчёт прирост производительности, такой код:

sb.Append(i);


и выглядит проще и чище, чем:

sb.Append(i.ToString());


И в качестве бонуса, он работает быстрее и потребляет меньше памяти. Win-win.
👍8
👩‍💻 Awesome Free PostgreSQL as a Service

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

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

За это время проект получил 23 звезды и 1 пул реквест. Два сервиса были удалены из списка, и два новых добавлены.

Новые сервисы

Xata.io Lite – предоставляет бесплатный тариф с 15 ГБ и ежедневными бэкапами.

Rapidapp.io – бесплатный план с 20 МБ хранилища.

Удалённые сервисы

Tembo.io – отменили бесплатный план с 30 мая. Жалко, т.к., на мой взгляд, у этого провайдера были самые адекватные условия.

Turso.tech – удалён, так как это SQLite as a Service, а не PostgreSQL (добавил по ошибке).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
👩‍💻 Быстрый способ записать большой массив данных в SQL Server

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

Задача

Нужно было скачать большие csv-файлы, прочитать их, отфильтровать нужные строки и загрузить в базу данных. Под большими я имею в виду файлы по 0,5–1 ГБ – это месячные отчёты от облачных провайдеров о расходах.

Это стандартная ETL-задача. Сложность была в том, что у подов в нашем Kubernetes-кластере ограничение по памяти на 250 МБ. Можно было просто поднять лимит, но это слишком просто и неинтересно. Я решил попробовать сделать всё с минимальными затратами памяти.

Пост не влезает в Telegram, поэтому продолжение на сайте.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
👩‍💻Как мы переезжали с SQL Server + Analytics Services на PostgreSQL

Последние два месяца я пишу мало, т.к. работа отнимает много сил. Но не могу не рассказать, как в прошлом месяце я мигрировал проект с SQL Server на PostgreSQL.

Предыстория

Проект, над которым работаю в данный момент, – это FinOps приложение для аналитики трат на облачные провайдеры. В первоначальной версии дашборда, которую мы сделали 2 года назад, в качестве хранилища использовалась SQL Server. Это основная база данных для приложений у нас в команде. Данные обрабатывались при помощи OLAP-кубов из SQL Server Analytics Services (SSAS).

В начале лета к нам пришёл запрос на доработку дашборда. Доработка затрагивала многие аспекты приложения, из-за чего приложение пришлось практически переписать. Поэтому заодно я решил и мигрировать проект на Postgres.

Почему отказались от SSAS

1. Для OLAP-кубов SSAS есть отдельный тип проектов, который поддерживается только Visual Studio. Ничего не имею против Visual Studio, но когда ты Full Stack инженер, которому приходится работать с C#, TypeScript, React, Docker, Kubernetes, Helm, то Visual Studio не самый подходящий выбор.

2. Несмотря на то, что Visual Studio – это единственная IDE, поддерживающие такие проекты, она периодически крэшится и зависает при работе с ними.

3. Деплой OLAP-куба возможен только через Visual Studio. Настроить деплой через CI/CD нельзя.

4. Синтаксис запросов Analytics Services (MDX) отличается от SQL:

-- SQL
SELECT service, SUM(cost) AS cost
FROM costs
WHERE provider='AWS' AND environment_tag='prod'
AND date >= DATE '2025-08-01' AND date < DATE '2025-09-01'
GROUP BY service
ORDER BY cost DESC
FETCH FIRST 3 ROWS ONLY;

-- MDX
SELECT
{ [Measures].[Cost] } ON COLUMNS,
TopCount([Service].[Name].Members, 3, [Measures].[Cost]) ON ROWS
FROM [Cloud FinOps]
WHERE ( [Date].[Calendar].[Month].&[2025]&[8],
[Provider].[Provider].&[AWS],
[Tags].[Environment].&[prod] )


5. Запуск перерасчёта OLAP-куба из приложения в Docker требует танцев с бубнами. Есть кроссплатформенные библиотеки от Microsoft, но они не работают из коробки.

Всё это послужило причиной переезда на Postgres с использованием материализованных представлений (Materialized Views). В SQL Server тоже есть похожий функционал (Indexed Views), но их создание и поддержка сложнее.

Lessons Learned

Теперь о том, какой опыт я приобрёл, пока делал миграцию проекта.

1. Потоковая вставка данных в Postgres проще, чем в SQL Server.

В предыдущем посте я рассказывал, как записать большой массив данных в SQL Server. Так вот, в Postgres это делается значительно проще. Не нужно писать портянки кода, реализовывая интерфейс IDataReader.

2. Материализованные представления способны заменить OLAP-куб.

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

3. Использование каскада представлений позволяет уменьшить время обновления.

Каскад материализованных представлений (cascade / nested materialized views) – это техника, при которой одно материализованное представление строится на основе другого MV, а то на основе третьего, и так далее. Например, сначала агрегируем данные по дням, потом по месяцам, а затем, агрегируем траты по категориям ресурсов для конкретного месяца.

4. Главная таблица (Fact Table) должна занимать как можно меньше места.

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

К примеру, у нас каждый месяц от трёх облачных провайдеров суммарно приходит около 12 млн событий. Строка Fact Table сейчас состоит из 3-х столбцов: Timestamp (Date, 4 байт), Cost (decimal, примерно 8 байт), ResourceId (integer, 4 байт). Добавление, например, столбца Id в качестве первичного ключа спокойно может увеличить размер таблицы на 100 – 200 Мб в месяц (размер столбца + размер индекса первичного ключа).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8