Ты сейчас в пустой обвязке для проекта, посвященном бенчмаркингу. Проект называется "microbenchmark", потому что я планирую оставлять код проекта очень простым и минималистичным. Нам предстоит разработать его сейчас с нуля.
Основная цель проекта: дать разработчикам инструментарий для быстрого написания бенчмарков и включения их в состав своих библиотек.
Главные принципы разработки следующие:
- Мы много думаем прежде, чем что-то делать.
- Дизайн - важен. Мы делаем вещи красивыми и максимально минималистичными.
- Мы проводим обширное ревью каждого сделанного шага. Источник ревью - программа qwen code, которая установлена на этом компьютере. Мы просим у нее ревью постоянно, как можно чаще, по несколько раз подряд.
- Мы поддерживаем крайне высокий уровень тестирования. Покрытие тестами в 100% - сильно ниже минимальной планки, в которую мы целимся. Наша задача: покрыть тестами все мыслимые сценарии использования, а потом еще и все немыслимые, которые мы можем придумать.
- Мы избегаем использования моков в тестировании, стараемся все возможное тестировать "в живую".
- Мы придерживаемся принципов TDD: сначала продумываем тесты, и только потом приступаем к реализации.
- Документация (README) - это источник правды. Тесты - основаны на документации. Основной код - основан на тестах.
- Каждое содержательное утверждение в документации должно опираться на соответствующие тесты.
- Нет внешним зависимостям, разрешены только зависимости на проекты, находящиеся внутри организации https://github.com/mutating
Работа должна вестись в таком порядке:
- Определяем цели.
- Определяемся с тем, какой именно код хотим написать.
- Детально продумываем тест-сьют.
- Пишем все тесты.
- Пишем основной код.
- Добиваемся прохождения новых тестов.
- Фиксим issues линтеров и проверяем, не упали ли старые тесты.
- Проверяем покрытие.
- Пишем или дополняем/исправляем документацию.
После каждого этапа разработки (создание плана, написание основного кода, документации или тестов) нужно запрашивать детальное ревью у qwen code. Программа установлена на данном компьютере, ее можно запустить командой qwen. Qwen нужно промптить, описывая ему текущую подзадачу и наши основные принципы разработки. Нужно просить его быть максимально дотошным. Qwen нужно запустить минимум 5 раз (если доработка сложная - 10+), агрегировать результаты вызовов, "отделить зерна от плевел", и только потом приступать к исправлениям.
Я хочу создать кодовую обвязку для бенчмаркинга проекта. Весь код мы положим в папку benchmarks, и все тесты нового кода - туда же.
Важно: мы не создаем CLI-тулинг для бенчмарков. Это скорее набор сценариев / некий базовый код, который уже при желании можно вызвать из CLI-тулзы или из тестов производительности.
Базовый дизайн состоит из:
- Класса Сценария
- Класса Группы Сценариев
- Класса Результата Бенчмарка
Подробнее о классе Сценария:
- Нужно создать базовый класс Сценария
- Сценарий принимает в конструктор функцию, которую он должен вызывать, список аргументов для нее (именно список, а не *args и **kwargs, чтобы мы могли расширять API в будущем), параметр doc (текстовое описание бенчмарка), параметр name (имя конкретного сценария), а также параметр количества раз, которое будет вызван бенчмарк
- У Сценария есть метод run(), который возвращает объект Результата Бенчмарка
- Метод run() должен иметь также опциональный аргумент, отвечающий за прогрев - сколько раз запустить сценарий до того, как время прогонов начнет заменяться и счетчик прогонов начнет считаться - результаты этих прогонов не должны сохраняться в Результате
- Конструктор Сценария должен иметь опциональный аргумент - функцию, которая будет использоваться для генерации таймстемпов, со значением по умолчанию
- У Сценария есть метод cli(), который запускает конкретный сценарий как CLI-программу, принимающую в качестве опционального CLI-аргумента количество итераций бенчмарка и выводящая в консоль все базовые параметры Результата Бенчмарка
- Метод cli() также должен принимать опциональный CLI-параметр с средним временем бенчмарка, и если среднее время выше - он должен "падать" (чтобы можно было использовать в CI)
О классе Группы Сценариев:
- Группу сценариев можно создать 4 способами: создав инстанс класса Группы напрямую, (опционально) передав ему один или несколько Сценариев в качестве аргументов (через *args); просто суммировав несколько сценариев через оператор "+"; суммировав одну или несколько Групп; суммировав один или несколько Сценариев и одну или несколько групп. Все суммы должны быть "плоскими", то есть если будет два плюсика, то не должна образовываться вложенная иерархия.
- Группа сценариев имеет внешний API, похожий на API одного сценария: метод run(), возвращающий список Результатов Бенчмарка и метод cli(), запускающий все бенчмарки группы сразу и выводящий общий результат в консоль через разделители
О классе Результата Бенчмарка:
- Результат Бенчмарка - это датакласс
- У Результата Бенчмарка которого должны быть следующие поля: среднее время, худшее время, лучшее время, а также объект Сценария, из которого получен этот результат
- Также Результат Бенчмарка должен хранить в себе продолжительность каждого отдельного запуска бенчмарка
- Результат должен иметь метод percentile(), который возвращает другой объект Результата Бенчмарка, суженный по данному персентилю
- Также в Результате должен быть кэшируемый property с 95 персентилем, и такой же с 99 персентилем, возвращающий тоже объекты Результатов Бенчмарка
- У результата бенчмарка должно быть bool-поле, показывающее, является он первичным или производным (то есть суженным, например по персентилю)
- Результат должен иметь метод сериализации в json и метод десериализации из json
- Для аггрегации результатов должны использоваться методы, минимизирующие погрешность из-за складывания чисел с плавающей точкой
Про документацию:
- Документация должна содержаться только в README.md
- Она должна быть простой и понятной, но исчерпывающей
- Должна сопровождаться примерами кода
- В примерах кода не нужно дублировать импорты, вывод должен демонстрироваться через print'ы и потом строчку с комментарием, начинаяющимся с "#>" и потом реальный ожидаемый вывод
- Она должна иметь следующую структуру: краткое описание проекта и ключевые фичи, оглавление (с якорными ссылками на разделы), способ установки, быстрый старт, раздел про Сценарий, раздел про Группу Сценариев, раздел про Результат Бенчмарка, раздел сравнения с конкурентами
- Документация должна быть оформлена в спокойном и дружелюбном стиле, без злоупотребления эмодзи
- Документация должна быть на английском
- Нужно активно использовать бэктики в тексте для выделения сущностей из кода, имен библиотек и всякого подобного
- Хороший пример документации, на который можно равняться, показан в проекте https://github.com/mutating/pristan
Про тесты:
- Минимальное покрытие - 100%
- Все, о чем сказано в README, должно быть тщательно протестировано
- Не скупимся как на негативные, так и на позитивные кейсы в тестах
- Все mypy-контракты должны быть покрыты тестами с использованием библиотеки pytest-mypy-testing, также должно быть много негативных кейсов и все возможные положительные
- Все CLI-штуки должны быть протестированы с помощью библиотеки subprocess
- ClI-тесты должны лежать в tests/cli, обычные юнит-тесты в tests/units, а тесты типизации - в tests/typing
- На основе каждого примера кода нужно также создать по тесту, эти тесты должны лежать в tests/documentation/test_readme.py
- Тесты должны быть function-based (не class-based)