Skip to content

Проект, иллюстрирующий разбор и анализ событий уборок мусора Garbage Collector'а, блокирующих работу приложения

Notifications You must be signed in to change notification settings

Dobby007/EventsProcessingAPI

Repository files navigation

EventsProcessingAPI - проект, иллюстрирующий разбор и анализ событий уборок мусора Garbage Collector'а, блокирующих работу приложения

Данный проект представляет собой АПИ для обработка событий и wpf-компонент с его использованием.

Терминология

  • Временная метка - время происхождения события в CPU тиках.
  • Временной интервал (или просто интервал) - интервал времени, задающийся в виде двух временных меток начала и конца данного интерала.
  • Плотность - вещественное число в интервале [0; 1], обозначающее отношение суммы всех временных интервалов между событием типа Start и событием типа Stop ко всему интервалу, где произошли данные события.
  • Сегмент - временной интервал для определения одной значения плотности. На графике один такой сегмент отображается в виде одного логического пикселя на устройстве.
  • Размер сегмента - длительность временного интервала в CPU тиках.

Структура солюшена

Схема солюшена

Солюшен разделен можно разделить на 4 части:

  • АПИ - квинтэссенция всего проекта. Позволяет загружать сессию событий с использованием различных стратегий. Состоит из:

    • EventsDomain - бизнес-домен предметной области. В проекте представлены модели для работы с событиями в АПИ. В нем представлены модели как реальных неоптимизированных сущностей, так и моделей, оптмизированных по отношению к потребляемой памяти.
    • EventsProcessingAPI - АПИ для загрузки и работы с событиями. Точка входа в АПИ класс ApiFacade. Для непосредстенной работы с событиями после их загрузки используется класс BucketContainer.
  • ConsoleApplications - консольные приложения, являющиеся частью всего решения:

    • RandomDataGenerator - генератор событий. Может генерировать как фейковые случайные события, так и отслеживать активность GC при жесткой манипуляции с объектами и кучей. В этом режиме генератор пытается сэмулировать работу программы, написанной неоптимальным образом.
    • EventUtility - консольное приложение, демонстрирующее работу с АПИ на базовом уровне. Поддерживается два пользовательских режима: режим отображения плотностей на определенный интервал времени и режим отображения всех полезных нагрузок, входящих в этот интервал.
  • Wpf - часть проекта, представляющая собой WPF-компонент, отображающий плотность распределения событий и пример приложения, использующего данный компонент.

    • EventsChart - WPF-компонент, состоящий в свою очередь из нескольких других компонентов. Может отображать как плотность распределения событий, так и сами события. Поддерживает масштабирование и перемещение по графику с помощью полосы прокрутки.
    • EventsChartExample - пример WPF-приложения, использующего вышеописанный компонент.
  • Test - benchmark, unit и функциональные тесты, написанные для тестирования работы АПИ:

    • BenchmarkTest - Benchmark-тестирование трех основных функций АПИ: подсчет плотностей с различным размером сегмента, выборка событий и выборка полезных нагрузок.
    • UnitTests - UNIT-тесты.
    • FunctionalTests - функциональные тесты АПИ. Есть два вида теста: тестирование подсчета плотностей при использовании различных стратегий загрузки и тестирование суммарной средне-арифметической плотности на всю сессию событий.
    • PerfomanceTest - небольшое консольное приложение для быстрой проверки производительности подсчета плотностей при различном размере сегментов.

Работа с АПИ

Точка входа в АПИ - это класс-фасад ApiFacade. Он инкапсулирует в себе логику загрузки событий из файлов и абстрактного Stream-объекта при различных видах стратегий. События загружаются асинхронно и фасад дает возможность клиентам получить статус загрузки через стандартный BCL-интерфейс IProgress<T>.

Типы стратегий:

  • LoadEventsAndPayloadsForChart - загрузка событий и соответствующих им полезных нагрузок с расчетом подсказок для будущего определения плотностей
  • LoadEventsForChart - загрузка событий с подсчетом подсказок для будущего определения плотностей
  • LoadOnlyEvents - загрузка только событий без расчета подсказок
  • LoadEventsAndPayloads - загрузка событий и полезных нагрузок без расчета подсказок

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

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

  • GetEvents - выборка оптимизированных по отношению к памяти событий с информацией о текущем месте расположения курсора (enumerator'а)
  • GetRealEvents - выборка событий с реальными временными метками
  • GetPayloads - выборка полезных нагрузок

Данные методы имеют одинаковую сигнатуру. Граница start - включающая (inclusive), граница end - исключающая (exclusive). При установленном флаге includeEventsOutOfRange при отсутствии событий входящих в заданный интервал выбирается ближайшее событие слева.

Данные методы возвращают экземпляр enumerable-типа, который можно использовать в цикле foreach. К сожалению, по причине природы оптимизаций, сделанных в АПИ, данные типы не реализуют стандартные BCL-интерфейсы IEnumerable и IEnumerator. Цикл foreach работает на основе утиной типизации.

Для получения максимального выхлопа по производительности для выборки полезных нагрузок следует код foreach в виде:

foreach (ref readonly Payload payload in payloads)
{
}

Результаты benchmark'ов можно увидеть в папке BechmarkResults в репозитории проекта.

Для расчета плотностей используются две перегрузки метода GetDensities. Одна из них позволяет записывать плотности в уже размещенный в куче буфер. Для создания такого буфера можно использовать метод CreateBufferForDensities. Обе границы start и end - включающие (inclusive). Аргумент segmentSize предсталяет собой размер сегмента (длительность интервала времени в CPU тиках), который будет использовать для расчета одной плотности. Количество таких плотностей зависит от длительности переданного интервала и размера сегмента.

Внутреннее устройство АПИ

Самое важное, что нужно сказать, это то, что все события после загрузки распределяются по бакетам. Каждый бакет имеет максимальную длительность в 1 секунду (10 миллионов CPU тиков). При отсутствии событий в определеннную секунду бакет тоже будет отсутствовать.

Внутри бакета есть события и такое же число полезных нагрузок (при условии выбора правильной стратегии загрузки).

Каждый бакет имеет свойство Offset, определяющее его смещение, относительно которого определяется абсолютное время возникновения события.

Событие внутри бакета это структура размеров в 4 байта. Имея в распоряжении только лишь данную сущность события можно определить время его происхождения относительно смещения бакета, а также его тип. Данное время будет может находиться в интервале [0; 9 999 999]. Время внутри структуры хранится в двух полях. Поле EventTimeHigh типа ushort определяет старшие 8 бит числа, задающего время в микросекундах [0; 999 999]. Поле EventTimeLow типа byte является битовой маской: старшие 4 бита поля - это младшие 4 бита числа, задающего время в микросекундах [0; 999 999], а младшие 4 бита - число, являющееся осткатком от деления относительного времени события на 10, что расширяет разрешение времени до CPU тиков.

В сущности события есть его тип - поле EventType типа EventType (enum размером в 1 байт).

Ограничения АПИ

  • Длительность всей сессии событий не может превышать 4294967295 секунд (~49710 суток)
  • Количество сегментов для расчета плотностей на весь интервал не может превышать 65535 штук

Benchmark-тесты

Результаты проведения benchmark-тестирования основных методов для работы с событиями и расчета плотностей имеются в папке репозитория BechmarkResults.

Лицензия распространения кода

Весь код в проекте распространяется в соответствии с условиями лицензии Apache License, Version 2.0.

About

Проект, иллюстрирующий разбор и анализ событий уборок мусора Garbage Collector'а, блокирующих работу приложения

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published