Нотатки про програмування, музику, подорожі та плівку
Про мене  •  Список нотаток  •  Плівка

Пізніше Ctrl + ↑

Мої поїздки

  • 🇺🇦 Україна

    Київ, Львів, Одеса, Припять, Івано-Франківськ, Надвірна, Ворохта, Вінниця, Чернівці, Крим (Ялта, Сімферополь)

  • 🇨🇦 Канада

    Victoria, Whistler, Hope, Vancouver, Toronto

  • 🇫🇷 Франція

    Париж

  • 🇩🇪 Німетчина

    Дортмунд (2019), Берлін (2023)

  • 🇬🇧 Британія

    Гібралтар (2023)

  • 🇪🇸 Іспанія

    Барселона, Мадрид, Марбелья, Монсерат (2023)

  • 🇵🇹 Португалія

    Лісабон, Мис Року (2023)

  • 🇬🇷 Греція

    Афіни, Неа Стіра, Карістос, Стіра, Неа Стіра (2022 — 2023)

  • 🇬🇪 Грузія

    Батумі (2021)

  • 🇹🇷 Турція

    Кемер (2018), Мармаріс (2019)

  • 🇮🇹 Італія

    Рим, Фьюмічіно (2019)

  • 🇳🇱 Голандія

    Амстердам (2019)

  • 🇸🇰 Словакія

    Братислава (2016)

  • 🇨🇿 Чехія

    Прага (2016)

  • 🇦🇹 Австрія

    Відень (2016)

  • 🇭🇺 Угорщина

    Будапешт (2016)

  • 🇵🇱 Польща

    Краків, Ополе (2012)




Gudak camera

Гудак представляет из себя эмулятор пленочной камеры. Видоискатель, в который толком ничего не увидишь, 24 кадра в катушке. Когда использовал катушку, следующая появится только через час, а предыдущая отправляется на «проявку» и фотки будут доступны через 3 дня.

Также нету никаких пресетов, только рандомные эффекты.

Но результат получается действительно интересный:

Инструменты для анализа дампа приложения

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

Инструменты

  1. PerfView — открытое решение от компании Microsoft для анализа производительности.
  2. dotMemory — платное решение от компании JetBrains. Привлекает тем что не только умеет анализировать дампы, но и многое другое. Также имеет красивый и удобный GUI
  3. MemoScope — открытое решение от независимого разработчика.
  4. Visual Studio — имеет встроенный функционал по анализу дампов приложения.

Ссылки

PerfView

  1. Блог MSDN по тегу PerfView
  2. Video: PerfView: Measure and Improve Your App’s Performance For Free
  3. Video: Video tutorial by Chanel 9
  4. Improving Your App’s Performance with PerfView
  5. Video: PerfView: The Ultimate .NET Performance Tool

MemoScope

  1. Официальная Wiki

Visual Studio

  1. Video: Debugging Memory Leaks Using New NET Memory Diagnostic Tools
  2. Visual Studio Docs

DotMemory

  1. Official Page

Кратко о WebSocket

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

Основной библиотекой для упрощения работы с сокетами от Microsoft является SignalR. Она берет на себя всю работу с данным протоколом и дает разработчику удобный интерфейс для работы.

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

SignalR предоставляет разработчикам две модели: постоянные подключения (Persistent Connection) и хабы (Hubs).
Постоянные подключения (Persistent Connection API) представляют разработчикам прямой доступ к низкоуровневому протоколу коммуникации. Подключения в этой модели представляют конечную точку, к которой подключаются клиенты, наподобие модели подключений в WCF.
Хабы же предоставляют протокол взаимодействия более высокого уровня. Они представляют верхний слой над Persistent Connection API и позволяют клиенту и серверу напрямую вызывать методы друг друга.

SignalR предоставляет следующие типы технологий для взаимодействия сервера и клиента:

  • WebSockets
  • Server-sent events
  • Forever Frames
  • Long polling

Картинка, которая иллюстрирует процесс установления связи по протоколу WebSocket

Следующий код был взят из websocket.org, но он демонстрирует базовое взаимодействие со стороны клиента с данным протоколом:

var wsUri = "ws://echo.websocket.org/";
var output;

function init()
{
  output = document.getElementById("output");
  testWebSocket();
}

function testWebSocket()
{
  websocket = new WebSocket(wsUri);
  websocket.onopen = function(evt) { onOpen(evt) };
  websocket.onclose = function(evt) { onClose(evt) };
  websocket.onmessage = function(evt) { onMessage(evt) };
  websocket.onerror = function(evt) { onError(evt) };
}

function onOpen(evt)
{
  writeToScreen("CONNECTED");
  doSend("WebSocket rocks");
}

function onClose(evt)
{
  writeToScreen("DISCONNECTED");
}

function onMessage(evt)
{
  writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
  websocket.close();
}

function onError(evt)
{
  writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}

function doSend(message)
{
  writeToScreen("SENT: " + message);
  websocket.send(message);
}

function writeToScreen(message)
{
  var pre = document.createElement("p");
  pre.style.wordWrap = "break-word";
  pre.innerHTML = message;
  output.appendChild(pre);
}

window.addEventListener("load", init, false);

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

По мнению многих, WebSockets — едва ли не самое полезное изобретение после горячей воды. Когда вы ухватите суть WebSockets, вы будете удивляться, как это мир программного обеспечения мог обходиться без этих сокетов. WebSockets здорово пригодится в ряде приложений, но отнюдь не во всех. В любом приложении, где мгновенный обмен сообщениями является ключевым требованием, — имеет смысл серьезно подумать о создании WebSocket-сервера и клиентов (веб-приложения, мобильные и даже настольные программы). Еще одна группа приложений, которые получат выигрыш от внедрения WebSocket Protocol, — игры и каналы реального времени. Да, WebSockets — определенно лучшее, что было изобретено после горячей воды!

Ссылки:

  1. Отличный пример реализации клиента и сервера без использования сторонних библиотек
  2. SignalR Core. Первое приложение
  3. Офф. сайт

C# Debug vs Release. Сборки и дебаг

Оригинальная статья: тык.

Из коробки в C# нам доступны 2 способа сборки проекта release и debug.

О компиляции C# кода

Исходный код C # проходит через 2 этапа компиляции, чтобы стать инструкциями CPU, которые могут быть выполнены.

Обычно первый этап происходит на вашем CI сервере, а второй шаг происходит позже, во время работы самого приложения. Когда же мы работаем локально в Visual Studio, то она все эти шаги выполняет перед запуском приложения из меню Debug.

Шаг первый. Компиляция приложения
Ваш код превращается в Common Intermediate Language (CIL), который уже может быть выполнен в любом окружении, которое поддерживает CIL. Обратите внимание, что собранная сборка не является читаемым текстом IL, а фактически метаданными и байтовым кодом в виде двоичных данных.

На данном шаге будет выполнена некоторая оптимизация кода (будет описано дальше).

Шаг второй. JIT компилятор
JIT компилятор конвертирует IL код в инструкции процессора, которые можно выполнить на вашей машине. Однако не вся компиляция происходит заранее — в нормальном режиме, код компилируется, только тогда когда его вызывают в первый раз, после чего он кэшируется.

Компилятор JIT — это всего лишь один из целого ряда сервисов, которые составляют Common Language Runtime (CLR), позволяя ему выполнять код .NET.

Основная часть оптимизации кода будет проведена на этом шаге.

Что такое оптимизация кода в одном предложении?

Это процесс улучшения таких факторов, как скорость выполнения, размер кода, энергопотребление, а в случае .NET — время, которое требуется для компилятора JIT — без изменения функциональности.

Почему мы заинтересованы в оптимизации в этой статье?

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

Оптимизация компилятора C#

C# компилятор на самом деле делает очень мало оптимизаций. На самом деле большенство оптимизаций производит JIT компилятор во время генерирования машинного кода. Тем не менее это все равно ухудшит работу по отладке.

Инструкция nop в IL
Команда nop имеет ряд применений при программировании на низком уровне, например, для включения небольших предсказуемых задержек или инструкции по перезаписи, которые вы хотите удалить. В IL коде данные конструкции помогают при использовании точек останова (breakpoints) для того чтобы они вели себя предсказуемо.

Если мы посмотрим на IL код, который сгенерирован с отключенными оптимизациями:

Эта инструкция мапиться с фигурной скобкой, для того чтобы мы могли поставить на нее точку остановки:

Даная инструкция была бы удалена если у нас включены оптимизации, что повлияло бы на отладку приложения.

Более подробное обсуждение оптимизаций компилятора C# в статье Эрика Липперта: Что делает переключатель оптимизации?. Существует также хороший комментарий о IL до и после оптимизации здесь.

Оптимизация JIT компилятора

Несмотря на то, что он быстро выполняет свою работу во время выполнения, компилятор JIT также выполняет множество оптимизаций. О его внутренних деталях мало информации. Даже во время работы вашего приложения он производит профилирование и, возможно, перекомпилирование кода для повышения производительности.
Хорошие примеры оптимизации с помощью JIT компилятора можете посмотреть здесь.

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

Для реальной оптимизации, сделанной компилятором JIT, я буду показывать инструкции по сборке. Это всего лишь макет на C #, чтобы дать вам общую идею.

Предположим, что у меня есть:

private long Add(int a, int b)
{
    return a + b;
}
public void MethodA()
{
    var r = Add(a, b);
}

Компилятор JIT, скорее всего, выполнит встроенное расширение. Он заменит вызов метода Add() телом данного метода:

public void MethodA()
{
    var r = a + b;
}

Конфигурации сборки по умолчанию

Итак, теперь, когда мы обновили понимание компиляции .NET и двух «слоев» оптимизации, давайте взглянем на 2 конфигурации сборки, доступные «из коробки»:

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

Внутренности аргументов оптимизации и отладки

Я попытался продемонстрировать данные аргументы из кода Roslyn и mscorlib. Теперь мы имеем следующие классы:

  1. CSharpCommandLineParser
  2. CodeGenerator
  3. ILEmitStyle
  4. debuggerattributes
  5. Optimizer
  6. OptimizationLevel

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

Перечисление OptimizationLevel

OptimizationLevel.Debug отключает все оптимизации для C# и JIT компилятора с помощью DebuggableAttribute.DebuggingModes, который с помощью ildasm, мы можем видеть:

OptimizationLevel.Release включает все оптимизации (DebuggableAttribute.DebuggingModes = ( 01 00 02 00 00 00 00 00 )) что в свою очередь соответсвует DebuggingModes.IgnoreSymbolStoreSequencePoints

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

Типы IL

Типы IL кода описаны в классе ILEmitStyle.

На диаграмме выше показано, что тип генерируемого IL кода C# компилятором зависит от OptimizationLevel.
Аргумент debug не меняет его, за исключение аргумента debug+ когда OptimizationLevel установлен в Release.

  • ILEmitStyle.Debug — нету оптимизация IL в дополнение к добавлению nop инструкций для сопоставления точекостановки с IL.
  • LEmitStyle.Release — полная оптимизация.
  • ILEmitStyle.DebugFriendlyRelease — выполняет только те оптимизации, которые не помешаю отладке приложения.

Следующий кусок кода продемонстрирует все это наглядно.

if(optimizations == OptimizationLevel.Debug)
{
    _ilEmitStyle = ILEmitStyle.Debug;
}
else
{
    _ilEmitStyle = IsDebugPlus() ?
    ILEmitStyle.DebugFriendlyRelease :
    ILEmitStyle.Release;
}

Комментарий в исходном файле Optimizer.cs гласит, что они не опускают никаких определенных пользователем локальных переменных (примеры на 28 строчке) и не переносят значения в стек между операторами.

Я рад, что прочитал это, так как я был немного разочарован своими собственными экспериментами в ildasm с debug +, поскольку все, что я видел, это сохранение локальных переменных.

Нет намеренной «деоптимизации», например, добавления команд nop.

Разница между debug, debug:full и debug:pdbonly.

На самом деле разницы никакой нету, что подтверждает официальная документация:

Результат остается одним и тем же — pdb файл создается.
Подгланув в CSharpCommandLineParser можем убедиться в этом. И для того чтобы проверить это, мне удалось отладить код с помощью WinDbg для обох аргументов (pdbonly и full).

Они не влияют на оптимизацию кода.
Как плюсом могу отметить что документация на Github более актуальна, но она не открывает свет на специфическое поведение для debug+

А что же такое этот ваш pdb файл?
Все очень просто, данный файл содержит всю необходимую информацию для отладки DLL и EXE. Что помогает сопоставить отладчику IL код с инструкциями в оригинальном C# коде.

Что на счет debug+?

debug+ это особенный аргумент, который не может быть заменен с помощью full и pdbonly. Как многие заметили, данный аргумент соответствует debug:full — это на самом деле не совсем правда. Если мы используем аргумент optimize-, поведение будет таким же, но для optimize+ будет свое собственное уникальное поведение (DebugFriendlyRelease).

debug- или без аргументов?

Значения по умолчанию, которые установлены в CSharpCommandLineParser.cs.

bool debugPlus = false;
bool emitPdb = false;

а значения для debug=:

case "debug-":
    if (value != null)
        break;
 
    bool emitPdb = false;
    bool debugPlus = false;

Таким образом, мы можем с уверенностью сказать, что debug- и отсутствие аргументов отладки, приводет к одному и тому же эффекту — pdb файл не будет создан.

Запрет оптимизации JIT при загрузке модуля (Suppress JIT optimizations)

Флажок в разделе «Options->Debugging->General» это опция для отладчика в Visual Studio и не повлияет на сборки, которые вы создаете.

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

Обычно этот параметр включаю для того чтобы отладить внешние библиотеки или пакеты NuGet.

Если мы хотим подключиться отладчиком Visual Studion к продакшен сборке, которая собрана в релизной конфигурации, то при наличии у нас pdb файла, мы может еще одним способом указать JIT компилятору, о том чтобы он не оптимизировал код. Для этого нужно добавить .ini файл с таким же названием как выполняемая библиотека и указать в нем:

[.NET Framework Debugging Control]
AllowOptimize=0

Что такое Just My Code?

По умолчанию эта настройка уже включена (Options->Debugging→Enable Just My Code) и отладчик думает что оптимизированный код не является пользовательским. Поэтому отладчик никогда не зайдет в такой код.

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

Этот параметр стоит отключать в том случае, когда у вас есть pdb файл.

Взглянем ближе на DebuggableAttribute

Выше я упомянул использование ildasm для изучения манифеста сборок для изучения DebuggableAttribute. Я также написал небольшой PowerShell скрипт для получения более дружественного результата (ссылка на скачивание).

Сборка Debug:

Сборка Release:

Вы можете игнорировать IsJITTrackingEnabled, поскольку он был проигнорирован компилятором JIT с .NET 2.0.
Компилятор JIT всегда будет генерировать информацию для отслеживания во время отладки, чтобы сопоставлять IL с машинным кодом и отслеживать, где хранятся локальные переменные и аргументы функции.

IsJITOptimizerDisabled — просто проверяет DebuggingFlags на наявность DebuggingModes.DisableOptimizations. Он отвечает за включение оптимизация с помощью JIT.

DebuggingModes.IgnoreSymbolStoreSequencePoints — говорит отладчику выработать точки последовательности из IL кода вместо загрузки .pdb файла. Точки последовательности используются для сопоставления местоположений в коде IL с местоположениями в исходном коде C#. Если он включен, то JIT не будет загружать .pdb файл. Я не уверен, почему этот флаг добавляется в оптимизированные сборки компилятором C#.
Также об этом флаге можно почитать здесь

Ключевые понятия

  1. debug- или отсутствие аргумента приводит к тому что не создается .pdb файл.
  2. debug, debug:full и debug:pdbonly приводят к созданию .pdb файла. debug+ делает тоже самое в случае когда установлен флаг optimize-.
  3. debug+ и optimize+ создают такой IL код, который легче отлаживать.
  4. Каждый слой оптимизации ухудшает отладку кода.
  5. С .NET 2.0 компилятор JIT всегда будет генерировать информацию для отслеживания независимо от атрибута IsJITTrackingEnabled.
  6. Будь то сборка через VS или csc.exe, атрибут DebuggableAttribute теперь всегда присутствует.
  7. optimised+ создает бинарники, которые отладчик воспринимает как сторонний код. Это поведение управляется с помощью опции Just My Code, но при ее отключении вы можете получить очень сомнительный опыт отладки.

Теперь у вас есть выбор:

  1. Debug: debug|debug:full|debug:pdbonly optimize+
  2. Release: debug-|no debug argument optimize+
  3. DebugFriendlyRelease: debug+ optimize+

Рубрикатор

Здесь вы можете увидеть список все статей, которые есть в данном блоге.
Со временем будут добавляться новые категории и статьи.

Статьи

  1. Прочитанные книги
  2. Мои инструменты
  3. Обзор приложени: Gudak camera
  4. Эгея
  5. Самообучение
  6. Обзор приложени: NOMI camera
  7. Мои расширения для Google Chrome
  8. Обзор фотопленок
  9. RSS
  10. Эксперименты над пленкой
  11. Кстати, не путайте проект и продукт
  12. Чек лист для поездок
  13. 36
  14. sleepover.fm
  15. Mubert
  16. Atlas Weekend 2019
  17. Халтура или ремесло?
  18. Квалификация

Программирование и ИТ

  1. C# Debug vs Release. Сборка и дебаг.
  2. Кратко о WebSocket
  3. Инструменты для анализа дампа приложения
  4. Best Practices for Building Async APIs with ASP.NET Core
  5. Digital Ocean
  6. Sublime Merge
  7. Изучение SQL: триггеры
  8. PowerShell: работа с credentials
  9. Изучение SQL: Операторы GROUP BY и HAVING
  10. Изучение SQL: UNION
  11. Изучение SQL: EXCEPT и INTERSECT
  12. Логирование
  13. Документация
  14. UAT и Staging
  15. Лучшие практики использования PowerShell c TeamCity
  16. Парадигмы ООП
  17. Автоматизация релизов Github с помощью Powershell и Teamcity
  18. CancellationToken в C#
  19. Разработка на C# с помощью Visual Studio Code
  20. Работа с файлами в Powershell
  21. Первый проект
  22. Коллекции в .NET
  23. Правила использования AutoMapper в .NET
  24. Изучение нового языка программирования
  25. Название для Unit-тестов
  26. Команды systemctl
  27. Шпаргалка по паттернам проектирования
  28. Изучение SQL: ключевое слово GO
  29. Цель любой библиотеки

Алгоритмы и структуры данных

Конспекты

Годнота

Фотокарточки и поездки

Архитектура высоконагруженных систем

Серия статей в которых я хочу разобраться с разными способами и подходами построения highload систем.
Также я провожу обучения для своей команды на данную тему.
Список тем (будет дополнятся):

  1. Сервисно-ориентированная архитектура
  2. Вертикальное масштабирование
  3. Горизонтальное масштабирование
  4. Отложенные вычисления
  5. Асинхронная обработка
  6. Конвейерная обработка
  7. Использование толстого клиента
  8. Кеширование
  9. Функциональное разделение
  10. Шардинг
  11. Виртуальные шарды
  12. Центральный диспетчер
  13. Репликация
  14. Партиционирование
  15. Кластеризация
  16. Денормализация
  17. Введение избыточности
  18. Параллельное выполнение

👋🏻Всім привіт!

Я — Богдан, фулстек розробник з Києва. Останні шість років пишу бекенд на C#, але час від часу використовую JavaScript та Python.

Мав можливість спробувати себе в невеликій веб-студії, продуктовій компанії та аутсорсі, а зараз працюю в стартапі, де відповідаю за всі аспекти розробки бекенду та інфраструктури.

Окрім роботи, захоплююсь електронною музикою та фотографую на плівку. Крім того, вивчаю дизайн та подорожую різними країнами.

Якщо вас цікавить мій професійний досвід — моє резюме та LinkedIn.

Місця, де мене можна знайти:

Раніше блог був російськомовним, але після повномасштабного вторгнення росії в Україну я вирішив вести його українською мовою. Деякі статті планую перекладати та постити англійською.

🇺🇦 Support Ukraine: savelife.in.ua/en