Skip to content
nixel2007Public

About

No description or website provided.

Topics

Resources

Stars

13 stars

Watchers

3 watching

Forks

Repository files navigation

decorator

Тестирование Статус порога качества

Библиотека для создания оберток (декораторов) над классами.

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

Возможности:

  • создание декоратора с идентичным интерфейсом;
  • синхронизация значений полей декоратора и реального объекта;
  • добавление методов, импортов, полей, шагов инициализации в runtime;
  • добавление перехватчиков ("перед", "после", "вместо") вызова метода;
  • объединение слоёв: декоратор над декоратором строится сразу над реальным объектом.

docs - todo;

Пример использования:

#Использовать decorator

КакойТоКласс = Новый КакойТоКласс();
КакойТоКласс.Поле = 123;

Поле = Новый Поле("НовоеПоле")
	.Публичное()
	.ЗначениеПоУмолчанию("ЗначениеПоУмолчанию");

Метод = Новый Метод("ДобавленнаяФункция")
	.Публичный()
	.ТелоМетода("Возврат Поле + 1;");

Перехватчик = Новый Перехватчик("ДобавленнаяФункция")
	.ТипПерехватчика(ТипыПерехватчиковМетода.Перед)
	.Тело("Сообщить(""Привет, мир!"")");

Декоратор = Новый ПостроительДекоратора(КакойТоКласс)
    .Импорт(Новый Импорт("fs"))
    .Поле(Поле)
    .Метод(Метод)
    .Перехватчик(Перехватчик)
    .Построить();

Ожидаем.Что(Декоратор.Поле).Равно(123);
Ожидаем.Что(Декоратор.РоднаяФункцияВозвращающаяИстина()).ЭтоИстина();
Ожидаем.Что(Декоратор.ДобавленнаяФункция()).Равно(124);

Объединение слоёв

Декоратор над декоратором не вкладывается: построитель добирается до реального объекта и переносит внутрь изменения развёрнутых слоёв. Цепочка вызовов остаётся одноуровневой, а поля, методы, перехватчики, импорты и шаги инициализации всех слоёв оказываются в одном модуле.

КакойТоКласс = Новый КакойТоКласс();
КакойТоКласс.Поле = 123;

Внутренний = Новый ПостроительДекоратора(КакойТоКласс)
    .Поле(Новый Поле("СчётчикВызовов").Публичное().ЗначениеПоУмолчанию(0))
    .Перехватчик(Новый Перехватчик("РоднаяФункцияВозвращающаяИстина")
        .ТипПерехватчика(ТипыПерехватчиковМетода.Перед)
        .Тело("СчётчикВызовов = СчётчикВызовов + 1;"))
    .Построить();

Внешний = Новый ПостроительДекоратора(Внутренний)
    .Метод(Новый Метод("Удвоить").Публичный().ТелоМетода("Возврат Поле * 2;"))
    .Построить();

Внешний.РоднаяФункцияВозвращающаяИстина();

// Поле и перехватчик внутреннего слоя оказались во внешнем декораторе,
// а вызов пошёл сразу в КакойТоКласс, минуя Внутренний
Ожидаем.Что(Внешний.СчётчикВызовов).Равно(1);
Ожидаем.Что(Внешний.Удвоить()).Равно(246);

Правила слияния:

  • поля и методы слоёв добавляются после полей и методов реального объекта;
  • импорты объединяются, повторы отбрасываются;
  • шаги инициализации выполняются от внутреннего слоя к внешнему;
  • перехватчики "до" (Перед, ПередСинхронизациейПолей) отрабатывают от внешнего слоя к внутреннему, "после" (После, ПослеВызоваИсключения) — наоборот;
  • перехватчик Вместо заменяет всё, что внутри него: перехватчики внутренних слоёв и сам метод выполняются, только если он вызвал Декоратор_ПродолжитьВызов(), как было бы с вложенными декораторами;
  • одинаковое имя поля или метода в двух слоях, либо совпадение с именем у реального объекта или со служебным полем декоратора — исключение при построении.

Развёрнутый декоратор в цепочке вызовов больше не участвует: его состояние копируется в построенный декоратор один раз, дальше объекты живут независимо.

Внутри перенесённых тел Декоратор_ИсходныйОбъект всегда указывает на реальный объект. Обращение вида Декоратор_ИсходныйОбъект.<метод соседнего слоя> до объединения работало, а после — сломалось бы, поэтому построитель ловит его и выбрасывает исключение с подсказкой использовать ЭтотОбъект.<метод>. Код при этом разбирается по правилам языка: регистр и пробелы вокруг точки не важны, комментарии и строковые литералы не просматриваются. Вызов через промежуточную переменную проверка не увидит.

Как отключить

ОбъединятьСлои(Ложь) означает и "сам не разворачиваю то, что мне передали", и "не даю развернуть себя": построенный декоратор не оставляет рецепта, поэтому следующий слой вложит его, как в версии 2.x.

Внутренний = Новый ПостроительДекоратора(КакойТоКласс)
    .ОбъединятьСлои(Ложь)
    .Построить();

Внешний = Новый ПостроительДекоратора(Внутренний).Построить();
// Внешний -> Внутренний -> КакойТоКласс

Отладка добавляемых методов

Для того, что бы работал отладчик и заходил в добавленные методы нужно: Либо установить любое значение переменной окружения с именем OSCRIPT_DECORATOR_DEBUG. Либо вызвать у построителя метод Отладка()

Декоратор = Новый ПостроительДекоратора(КакойТоКласс)
    .Импорт(Новый Импорт("fs"))
    .Поле(Поле)
    .Метод(Метод)
    .Перехватчик(Перехватчик)
    .Отладка()
    .Построить();

Регистрация типов из фоновых заданий

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

Модуль типа регистрация пишет во временный файл и удаляет его сразу после подключения. Временные файлы, созданные другим кодом через ВременныеФайлы, она не трогает.

Документация по методам

ПостроительДекоратора

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   Объект - Произвольный - Инстанс объекта, над которым нужно создать декоратор
//          - Тип          - Тип объекта, инстанс которого нужно создать и задекорировать
//          - Неопределено - Декоратор создаётся с нуля
//
Процедура ПриСозданииОбъекта(Объект = Неопределено)

Поле

// Добавляет в декоратор новое поле
//
// Параметры:
//   Поле - Поле - Добавляемое поле
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Поле(Поле) Экспорт

Метод

// Добавляет в декоратор новый метод.
//
// Параметры:
//   Метод - Метод - Добавляемый метод.
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Метод(Метод) Экспорт

Перехватчик

// Добавляет в декоратор перехватчик
//
// Параметры:
//   Перехватчик - Перехватчик - Добавляемый перехватчик
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Перехватчик(Перехватчик) Экспорт

Импорт

// Добавляет в декоратор импорт библиотеки (#Использовать).
//
// Параметры:
//   Импорт - Импорт - Импорт библиотеки
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Импорт(Импорт) Экспорт

ШагИнициализации

// Добавляет в декоратор шаг инициализации в тело модуля.
//
// Параметры:
//   ШагИнициализации - ШагИнициализации - Выполняемый шаг инициализации
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ШагИнициализации(ШагИнициализации) Экспорт

ЗначениеПараметраКонструктораПоТипу

// Добавляет значение параметра для инициализации объекта, в случае создания декоратора из типа
//
// Параметры:
//   ЗначениеПараметра - Произвольный - Значение параметра конструктора по типу
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ЗначениеПараметраКонструктораПоТипу(ЗначениеПараметра) Экспорт

ОбъединятьСлои

// Управляет объединением слоёв вложенных декораторов.
//
// При включённом объединении декоратор над декоратором строится сразу над
// исходным объектом, а изменения развёрнутых слоёв переносятся внутрь.
// При выключенном декоратор вкладывается, и построенный объект не оставляет
// рецепта, поэтому и следующий слой развернуть его не сможет.
//
// Параметры:
//   Включено - Булево - Объединять слои
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ОбъединятьСлои(Включено = Истина) Экспорт

ДопуститьОтсутствиеИнстанса

// Разрешает построение декоратора без инстанса исходного объекта.
// Действует в режиме создания из типа: если конструктор типа выбрасывает исключение,
// построение не прерывается, а декоратор строится без инстанса (Неопределено).
// Интерфейс типа при этом полностью сохраняется, но делегирование вызовов
// в исходный объект и синхронизация полей недоступны.
//
// Параметры:
//   Допустить - Булево - Признак допустимости отсутствия инстанса
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ДопуститьОтсутствиеИнстанса(Допустить = Истина) Экспорт

Пример — декоратор над типом, который нельзя создать через конструктор (например, HTTPОтвет):

Перехватчик = Новый Перехватчик("ПолучитьТелоКакСтроку")
	.ТипПерехватчика(ТипыПерехватчиковМетода.Перед)
	.Тело("Возврат ""Переопределенный ответ"";");

Декоратор = Новый ПостроительДекоратора(Тип("HTTPОтвет"))
	.ДопуститьОтсутствиеИнстанса()
	.Перехватчик(Перехватчик)
	.Построить();

ТекстСценария

// Получить сконструированный текст сценария будущего декоратора
//
//  Возвращаемое значение:
//   Строка - Текст сценария декоратора
//
Функция ТекстСценария() Экспорт

Построить

// Сконструировать готовый декоратор по настройкам конструктора Декоратор.
//
// Параметры:
//   ТекстСценария - Строка - Текст сценария декоратора. Если не задан, формируется автоматически.
//
//  Возвращаемое значение:
//   Произвольный - Декоратор над объектом, переданным в конструктор Декоратор
//
Функция Построить(ТекстСценария = Неопределено) Экспорт

ЗарегистрироватьВСистемеТипов

// Сконструировать готовый декоратор по настройкам конструктора Декоратор,
//  и зарегистрировать его как новый тип в системе типов
//
// Параметры:
//   ИмяТипа - Строка - Имя, под которым тип будет зарегистрирован в системе
//
Процедура ЗарегистрироватьВСистемеТипов(ИмяТипа) Экспорт

Аннотация

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяАннотации - Строка - Имя добавляемой аннотации
//
Процедура ПриСозданииОбъекта(ИмяАннотации)

Параметр

// Добавляет параметр аннотации, допускается указание одного безымянного параметра
//
// Параметры:
//   Значение - Строка, Число, Булево, Дата - Значение параметра
//   Имя      - Строка - Необязательный, имя параметра 
//
//  Возвращаемое значение:
//   Аннотация - Ссылка на текущий инстанс Аннотация
//
Функция Параметр(Значение, Имя = "") Экспорт

Импорт

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ПодключаемаяБиблиотека - Строка - Имя или путь подключаемой библиотеки
//
Процедура ПриСозданииОбъекта(ПодключаемаяБиблиотека)

ТипПодключения

// Устанавливает тип подключения библиотеки
//
// Параметры:
//   УстанавливаемыйТипПодключения - ТипыПодключенияБиблиотек - Устанавливаемый тип подключения библиотеки
//
//  Возвращаемое значение:
//   Импорт - Ссылка на текущий инстанс Импорт
//
Функция ТипПодключения(УстанавливаемыйТипПодключения) Экспорт

Метод

// Конструктор
//
// Параметры:
//   ИмяМетода - Строка - Имя создаваемого метода
//
Процедура ПриСозданииОбъекта(ИмяМетода)

Аннотация

// Добавляет аннотацию метода
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Аннотация(Аннотация) Экспорт

ТелоМетода

// Устанавливает тело метода
//
// Параметры:
//   ТелоМетода - Строка - Устанавливаемое тело метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция ТелоМетода(ТелоМетода) Экспорт

Параметр

// Добавляет параметр метода
//
// Параметры:
//   Параметр - ПараметрМетода - Добавляемый параметр метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Параметр(Параметр) Экспорт

Публичный

// Устанавливает экспорт метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Публичный() Экспорт

ЭтоПроцедура

// Устанавливает признак того что этот метод Процедура
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция ЭтоПроцедура() Экспорт

ПараметрМетода

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПараметра - Строка - Имя параметра метода
//
Процедура ПриСозданииОбъекта(ИмяПараметра)

ПоЗначению

// Устанавливает Знач параметра
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция ПоЗначению() Экспорт

ЗначениеПоУмолчанию

// Устанавливает значение по умолчанию для параметра
//
// Параметры:
//   ЗначениеПоУмолчаниюПараметра - Строка, Число, Дата, Булево, Неопределено - Значение параметра по умолчанию
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция ЗначениеПоУмолчанию(ЗначениеПоУмолчаниюПараметра) Экспорт

Аннотация

// Добавляет аннотацию параметра
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция Аннотация(Аннотация) Экспорт

Перехватчик

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПерехватываемогоМетода - Строка - Имя метода для которого предназначен перехватчик
//
Процедура ПриСозданииОбъекта(ИмяПерехватываемогоМетода)

Тело

// Устанавливает тело перехватчика
//
// Параметры:
//   ТелоПерехватчика - Строка - Устанавливаемое тело перехватчика
//
//  Возвращаемое значение:
//   Перехватчик - Ссылка на текущий инстанс Перехватчик
//
Функция Тело(ТелоПерехватчика) Экспорт

ТипПерехватчика

// Устанавливает тип перехватчика
//
// Параметры:
//   ТипПерехватчика - ТипыПерехватчиковМетода - Устанавливаемое тип перехватчика
//
//  Возвращаемое значение:
//   Перехватчик - Ссылка на текущий инстанс Перехватчик
//
Функция ТипПерехватчика(ТипПерехватчика) Экспорт

Поле

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПоля - Строка - Имя поля
//
Процедура ПриСозданииОбъекта(ИмяПоля)

Публичное

// Устанавливает Экспорт поля
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция Публичное() Экспорт

ЗначениеПоУмолчанию

// Устанавливает значение по умолчанию для поля
//
// Параметры:
//   УстанавливаемоеЗначениеПоУмолчанию - Произвольный - Значение поля по умолчанию
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция ЗначениеПоУмолчанию(УстанавливаемоеЗначениеПоУмолчанию) Экспорт

Аннотация

// Добавляет аннотацию поля
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция Аннотация(Аннотация) Экспорт

ШагИнициализации

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ТелоШага - Строка - тело шага инициализации
//
Процедура ПриСозданииОбъекта(ТелоШага)

Перечисление ТипыПерехватчиковМетода

Перед

Перехватчик вызывается перед выполнением перехватываемого метода

Вместо

Перехватчик выполняется вместо перехватываемого метода, как &Вместо в расширениях 1С. Он отрабатывает после перехватчиков Перед своего слоя; исходный метод и перехватчики внутренних слоёв выполняются, только если тело вызвало Декоратор_ПродолжитьВызов().

  • Тело пишется как тело метода: у функции результат возвращается через Возврат, без него функция вернёт Неопределено; у процедуры Возврат; просто завершает перехватчик. Возврат не пропускает ни После, ни синхронизацию полей — они видят результат в Декоратор_ВозвращаемоеИзМетодаЗначение, как обычно.
  • Декоратор_ПродолжитьВызов() вызывает то, что внутри перехватчика, с текущими значениями параметров метода. У функции это выражение, оно возвращает результат; у процедуры — только инструкция Декоратор_ПродолжитьВызов();. Параметры можно поменять до вызова, результат — после, вызов можно повторить или обернуть в Попытка.
  • Метода Декоратор_ПродолжитьВызов в модуле нет: построитель заменяет его вызов в коде тела. Регистр и пробелы у скобок не важны, строки и комментарии не затрагиваются.
  • Исключение из тела обрабатывается как исключение вызова: отрабатывают ПослеВызоваИсключения.
  • Несколько перехватчиков Вместо на одном методе вкладываются друг в друга: первый зарегистрированный — внешний.

Кэширование результата:

Декоратор = Новый ПостроительДекоратора(КакойТоКласс)
	.Поле(Новый Поле("Кэш"))
	.Перехватчик(Новый Перехватчик("ТяжёлаяФункция")
		.ТипПерехватчика(ТипыПерехватчиковМетода.Вместо)
		.Тело("Если Кэш = Неопределено Тогда
		|	Кэш = Декоратор_ПродолжитьВызов();
		|КонецЕсли;
		|Возврат Кэш;"))
	.Построить();

Продолжение вызывается только синхронно. Чтобы выполнить метод в другом потоке, слою нужен отдельный объект, в который можно войти снаружи: постройте его с ОбъединятьСлои(Ложь) поверх остальных слоёв и вызывайте из фонового задания Декоратор_ИсходныйОбъект — вызов пройдёт через перехватчики всех внутренних слоёв.

После

Перехватчик вызывается после выполнения перехватываемого метода

ПослеВызоваИсключения

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

ПередСинхронизациейПолей

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

Перечисление ТипыПодключенияБиблиотек

ПоИмени

Библиотека подключается по имени:

#Использовать fs

ПоПути

Библиотека подключается по пути к библиотеке:

#Использовать "./libs/myLib"

Модуль ОбработкаДекоратора

ЭтоДекоратор

// Проверяет, что объект является декоратором, построенным этой библиотекой.
//
// Параметры:
//   Объект - Произвольный - Проверяемый объект
//
//  Возвращаемое значение:
//   Булево - Истина, если объект - декоратор
//
Функция ЭтоДекоратор(Объект) Экспорт

ИсходныйОбъект

// Получает объект, вокруг которого построен декоратор.
//
// Параметры:
//   Декоратор - Произвольный - Декоратор, у которого нужно получить обёрнутый объект
//
//  Возвращаемое значение:
//   - Произвольный - обёрнутый объект
//   - Неопределено - объект не является декоратором либо декоратор построен
//     без исходного объекта
//
Функция ИсходныйОбъект(Декоратор) Экспорт

ИсходныйТип

// Получает тип объекта, вокруг которого построен декоратор (рекурсивно).
//
// Параметры:
//   Декоратор - Произвольный - Объект, у которого нужно найти исходный тип объекта
//
//  Возвращаемое значение:
//   Тип - Исходный тип объекта
//
Функция ИсходныйТип(Декоратор) Экспорт

СинхронизироватьПоля

// Синхронизировать значения экспортных полей двух объектов.
//
// Параметры:
//   ИсходныйОбъект - Произвольный - Источник значений свойств
//   Потребитель - Произвольный - Получатель значений свойств
//
Процедура СинхронизироватьПоля(ИсходныйОбъект, Потребитель) Экспорт

ИмяМетодаДекоратора

// Возвращает имя, которое получит метод исходного объекта в декораторе.
// Имена, совпадающие с зарезервированными, получают префикс "_".
//
// Параметры:
//   ИмяМетода - Строка - Имя метода исходного объекта
//
//  Возвращаемое значение:
//   Строка - Имя метода в декораторе
//
Функция ИмяМетодаДекоратора(Знач ИмяМетода) Экспорт

ИмяПараметраДекоратора

// Возвращает имя, которое получит параметр метода исходного объекта в декораторе.
// Имена, совпадающие с ключевыми словами языка (например, val у Структура.Вставить),
// получают префикс "_".
//
// Параметры:
//   ИмяПараметра - Строка - Имя параметра метода исходного объекта
//
//  Возвращаемое значение:
//   Строка - Имя параметра в декораторе
//
Функция ИмяПараметраДекоратора(Знач ИмяПараметра) Экспорт

Модуль Константы_Декоратор

// Имя поля, в котором хранится ссылка на исходный объект.
Перем Поле_ИнстансОбъекта Экспорт;

// Имя поля, в котором хранится лог декоратора.
Перем Поле_Лог Экспорт;

// Имя поля, в котором хранится рецепт декоратора - массив слоёв изменений,
// от внутреннего слоя к внешнему.
Перем Поле_Рецепт Экспорт;

// Массив имён служебных полей декоратора.
Перем ИменаСлужебныхПолей Экспорт;

Переход с 2.x на 3.0

Всё, кроме первого пункта, откатывается вызовом ОбъединятьСлои(Ложь) у построителя.

  1. Удалён класс КонструкторДекоратора и весь API версии 1. Используйте ПостроительДекоратора.
  2. Декоратор_ИсходныйОбъект теперь всегда содержит реальный объект, а не соседний декоратор.
  3. Переданный в конструктор декоратор в цепочке вызовов больше не участвует: его состояние копируется один раз при построении, дальше объекты живут независимо.
  4. Блок Попытка охватывает только вызов метода реального объекта. Раньше Попытка внешнего декоратора охватывала всю обёртку внутреннего, поэтому исключение из перехватчика внутреннего слоя запускало ПослеВызоваИсключения внешнего. Теперь нет.
  5. Конфликт имён полей и методов между слоями, с реальным объектом или со служебными полями декоратора — исключение при построении вместо ошибки компиляции сценария.
  6. Обращение Декоратор_ИсходныйОбъект.<метод соседнего слоя> в теле метода, перехватчика или шага инициализации — исключение при построении.

Замеры производительности

Замеры построения декоратора, вызова его метода и создания экземпляра зарегистрированного типа лежат в каталоге benchmarks: один или три слоя, в каждом — без перехватчиков, с Перед и После или ещё и с Вместо. Запускаются библиотекой benchmark. В зависимости разработки она не входит: ей нужен OneScript 1.9.4, а декоратору хватает 1.9.2. Поставьте её отдельно:

opm install -l benchmark
oscript tasks/benchmark.os
  • Замеряется decorator из репозитория, а не пакет из oscript_modules, который benchmark подтягивает через свои зависимости: benchmarks/oscript.cfg подключает benchmarks/lib, где decorator перенаправлен на корень репозитория. Если перенаправление не сработает, замер упадёт, а не пойдёт молча по чужой версии.
  • tasks/benchmark.os отключает профилирование многоуровневой компиляции .NET (DOTNET_TieredPGO=0): с ним первые кейсы в процессе выходят завышенными и с большим разбросом.
  • Абсолютные значения сильно зависят от загрузки машины. Сравнивайте версии прогонами подряд.

About

No description or website provided.

Topics

Resources

Stars

13 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages