Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ benchos run [OPTIONS] [FILE]
| `-e`, `--exporters` | Форматы [экспорта результатов](ЭкспортРезультатов.md) (`md`, `json`, `xml`, `html`) | `-e json,xml` |
| `-a`, `--artifacts` | Каталог для сохранения результатов | `-a path/to/file` |
| `-r`, `--recursive` | Рекурсивный поиск в поддиректориях | |
| `-c`, `--config` | Файл конфигурации бенчмарков в формате JSON | `-c path/to/config.json` |
| `--settings` | Файл настроек бенчмарков в формате JSON | `--settings path/to/settings.json` |

## Примеры

Expand Down
14 changes: 9 additions & 5 deletions packagedef
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Процедура ПередСборкой(РабочийКаталог) Экспорт
Процедура ПередСборкой(РабочийКаталог) Экспорт
ПодготовкаКомпонентов = ЗагрузитьСценарий("build/ПодготовкаКомпонентов.os");
ПодготовкаКомпонентов.Подготовить();
КонецПроцедуры
Expand All @@ -7,6 +7,7 @@
.Версия("0.6.0")
.Автор("Dmitry Ivanov")
.АдресАвтора("https://github.com/Stivo182")
.АдресРепозитория("https://github.com/Stivo182/BenchmarkOneScript")
.Описание("Бенчмаркинг на OneScript")
.ВерсияСреды("1.9.3")
.ВключитьФайл("src/BenchmarkOneScript")
Expand All @@ -17,11 +18,11 @@
.ВключитьФайл("package-loader.os")
.ВключитьФайл("README.md")
.ВключитьФайл("LICENSE")
.ЗависитОт("cpuinfo", "1.3.0")
.ЗависитОт("cpuinfo", "1.4.0")
.ЗависитОт("delegate", "1.0.0")
.ЗависитОт("annotations", "1.3.1")
.ЗависитОт("asserts", "1.4.0")
.ЗависитОт("autumn", "4.3.10")
.ЗависитОт("asserts", "1.5.0")
.ЗависитОт("autumn", "4.3.11")
.ЗависитОт("autumn-cli", "1.2.0")
.ЗависитОт("coloratos", "0.3.0")
.ЗависитОт("fluent", "0.6.1")
Expand All @@ -30,8 +31,11 @@
.ЗависитОт("logos", "1.7.1")
.ЗависитОт("fs", "1.2.0")
.ЗависитОт("tempfiles", "1.1.1")
.ЗависитОт("packageinfo", "1.0")
.ЗависитОт("packageinfo", "1.1.1")
.ЗависитОт("1commands", "1.5.0")
.ЗависитОт("validate", "0.3.0")
.ЗависитОт("reflector", "0.7.1")
.ЗависитОт("collectionos", "0.8.2")
.РазработкаЗависитОт("1testrunner")
.РазработкаЗависитОт("coverage")
.ИсполняемыйФайл("src/BenchmarkOneScript/cmd/main.os", "benchos")
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
&Флаг
Перем _ПропускнаяСпособность; // Булево, Неопределено

&Опция(Имя = "c config", Описание = "Файл конфигурации бенчмарков в формате JSON")
&Опция(Имя = "settings", Описание = "Файл настроек бенчмарков в формате JSON")
&ТСтрока
Перем _ФайлКонфигурации; // Строка
Перем _ФайлНастроек; // Строка

&Опция(Имя = "runtime", Описание = "Версии OneScript через запятую (current, stable, dev, x.x.x)")
&ТСтрока
Expand All @@ -62,51 +62,87 @@
&ТМассивСтрок
Перем _МассивФайлов; // Массив из Строка

Перем _Лог; // Лог

&КомандаПриложения(Имя = "run", Описание = "Запуск бенчмарков")
Процедура ПриСозданииОбъекта()
_Лог = Логирование.ПолучитьЛог("oscript.lib.benchmark");
КонецПроцедуры

&ВыполнениеКоманды
Процедура Запустить() Экспорт

УстановитьРежимВоркер();

Для Каждого Каталог Из КаталогиБенчмарков() Цикл
Бенчмаркинг.ЗапуститьИзКаталога(Каталог, _Рекурсивно, ПрочитатьКонфигурацию());
КонецЦикла;
ПодключенныеТипы = ПодключитьТипы();
Настройки = ПрочитатьНастройки();
Конфигурация = ПрочитатьКонфигурацию(Настройки);

Для Каждого ИмяФайла Из ФайлыБенчмарков() Цикл
Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
Если Не Тип = Неопределено Тогда
Конфигурация = Новый КонфигурацияБенчмарков(Тип);
Конфигурация.Объединить(ПрочитатьКонфигурацию());
Бенчмаркинг.Запустить(Тип, Конфигурация);
Для Каждого Тип Из ПодключенныеТипы Цикл
Comment on lines +77 to +81
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add validation for empty benchmark types.

If ПодключитьТипы() returns an empty array (e.g., no valid benchmark files found), the loop won't execute and the command will exit silently without informing the user. This could lead to confusion.

Consider adding validation:

 ПодключенныеТипы = ПодключитьТипы();
+Если ПодключенныеТипы.Количество() = 0 Тогда
+	_Лог.Предупреждение("Не найдено ни одного файла с бенчмарками для запуска");
+	Возврат;
+КонецЕсли;
+
 Настройки = ПрочитатьНастройки();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ПодключенныеТипы = ПодключитьТипы();
Настройки = ПрочитатьНастройки();
Конфигурация = ПрочитатьКонфигурацию(Настройки);
Для Каждого ИмяФайла Из ФайлыБенчмарков() Цикл
Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
Если Не Тип = Неопределено Тогда
Конфигурация = Новый КонфигурацияБенчмарков(Тип);
Конфигурация.Объединить(ПрочитатьКонфигурацию());
Бенчмаркинг.Запустить(Тип, Конфигурация);
Для Каждого Тип Из ПодключенныеТипы Цикл
ПодключенныеТипы = ПодключитьТипы();
Если ПодключенныеТипы.Количество() = 0 Тогда
_Лог.Предупреждение("Не найдено ни одного файла с бенчмарками для запуска");
Возврат;
КонецЕсли;
Настройки = ПрочитатьНастройки();
Конфигурация = ПрочитатьКонфигурацию(Настройки);
Для Каждого Тип Из ПодключенныеТипы Цикл
🤖 Prompt for AI Agents
In src/BenchmarkOneScript/cmd/Классы/КомандаЗапуска.os around lines 77 to 81,
ПодключенныеТипы may be an empty array which causes the subsequent loop to be
skipped and the command to exit silently; add a validation immediately after
ПодключенныеТипы = ПодключитьТипы() that checks if the array is empty, and if so
write a clear error/message to the user (or лог) indicating "No benchmark types
found" and terminate the command early (throw/exit) with a non-zero status so
the failure is visible to callers. Ensure the check handles null/undefined as
well as zero-length arrays and avoids proceeding to
ПрочитатьНастройки/ПрочитатьКонфигурацию when there are no types.


КонфигурацияТипа = Новый КонфигурацияБенчмарков(Тип);
КонфигурацияТипа.Объединить(Конфигурация);

Если Не Настройки = Неопределено И Настройки.ДескрипторыБенчмарков.Количество() > 0 Тогда
Источник = Настройки.ДескрипторыБенчмарков;
Иначе
Источник = Тип;
КонецЕсли;

Попытка
Бенчмаркинг.Запустить(Источник, КонфигурацияТипа);
Исключение
_Лог.Ошибка("Возникла ошибка при запуске бенчмарков <%1>: %2",
Тип,
ОписаниеОшибки());
КонецПопытки;

КонецЦикла;

КонецПроцедуры

Функция КаталогиБенчмарков()

Каталоги = Новый Массив();
Функция ПрочитатьНастройки()

Для Каждого ИмяФайла Из _МассивФайлов Цикл
Если ФС.КаталогСуществует(ИмяФайла) Тогда
Каталоги.Добавить(ИмяФайла);
Если Не ЗначениеЗаполнено(_ФайлНастроек) Тогда
Возврат Неопределено;
КонецЕсли;

Сериализатор = Новый СериализаторНастроекБенчмарков();
Возврат Сериализатор.ПрочитатьИзJson(_ФайлНастроек);

КонецФункции
Comment on lines +104 to +113
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify error handling in СериализаторНастроекБенчмарков.

Ensure that СериализаторНастроекБенчмарков.ПрочитатьИзJson() properly handles cases where the file doesn't exist, is unreadable, or contains malformed JSON. If not, the command will fail with an unclear error.

Run this script to verify error handling:


🏁 Script executed:

#!/bin/bash
# Description: Check if СериализаторНастроекБенчмарков handles file errors

ast-grep --pattern $'class СериализаторНастроекБенчмарков {
  $$$
  ПрочитатьИзJson($$$) {
    $$$
  }
  $$$
}'

Length of output: 0



---

🏁 Script executed:

```shell
#!/bin/bash
# Find the СериализаторНастроекБенчмарков file
fd СериализаторНастроекБенчмарков

Length of output: 68


🏁 Script executed:

#!/bin/bash
# Search for the ПрочитатьИзJson method definition
rg -n "ПрочитатьИзJson" --type-add 'os:*.os' --type os -A 10 -B 2

Length of output: 7384


🏁 Script executed:

#!/bin/bash
# Search for the СериализаторНастроекБенчмарков class/method structure
rg -n "СериализаторНастроекБенчмарков" --type-add 'os:*.os' --type os -C 5

Length of output: 3872



---

🏁 Script executed:

```shell
#!/bin/bash
# Read the full ПрочитатьИзJson method implementation
cat src/BenchmarkOneScript/core/Классы/СериализаторНастроекБенчмарков.os | sed -n '48,65p'

Length of output: 458


🏁 Script executed:

#!/bin/bash
# Check if there are any Попытка (try) blocks in the file to understand error handling patterns
rg -n "Попытка|Исключение" src/BenchmarkOneScript/core/Классы/СериализаторНастроекБенчмарков.os

Length of output: 0


Add error handling to СериализаторНастроекБенчмарков.ПрочитатьИзJson().

The method reads files and deserializes JSON without any error handling. If the file doesn't exist, is unreadable, or contains invalid JSON, it will crash with an unclear error. Wrap file operations in a try/catch block (Попытка/Исключение) or validate file existence before reading.

Affected code: src/BenchmarkOneScript/core/Классы/СериализаторНастроекБенчмарков.os, lines 52–57 (file read and deserialization).

🤖 Prompt for AI Agents
In src/BenchmarkOneScript/core/Классы/СериализаторНастроекБенчмарков.os around
lines 52–57, the code performs file reading and JSON deserialization with no
error handling; wrap the file read + JSON parse in a Попытка/Исключение block
(or first check file existence/читабельность) and on error either return
Неопределено or rethrow a clear Исключение with context (including filename and
error message) so callers (e.g., КомандаЗапуска.os) don't crash with an unclear
error; ensure resources are handled and the function fails gracefully.


Функция ПодключитьТипы()

ПодключенныеТипы = Новый Массив();
Для Каждого ИмяФайла Из НайтиФайлыБенчмарков() Цикл
Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
Если Не Тип = Неопределено Тогда
ПодключенныеТипы.Добавить(Тип);
КонецЕсли;
КонецЦикла;

Возврат Каталоги;
Возврат ПодключенныеТипы;

КонецФункции
Comment on lines +115 to 127
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add error handling for class connection failures.

If Бенчмаркинг.ПодключитьКласс() throws an exception (e.g., syntax error in benchmark file), the entire function fails and no benchmarks will run. Wrapping in a try-catch allows processing to continue for other files.

Apply this diff:

 Функция ПодключитьТипы()
 		
 	ПодключенныеТипы = Новый Массив();
 	Для Каждого ИмяФайла Из НайтиФайлыБенчмарков() Цикл
-		Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
-		Если Не Тип = Неопределено Тогда
-			ПодключенныеТипы.Добавить(Тип);
-		КонецЕсли;
+		Попытка
+			Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
+			Если Не Тип = Неопределено Тогда
+				ПодключенныеТипы.Добавить(Тип);
+			КонецЕсли;
+		Исключение
+			_Лог.Ошибка("Не удалось подключить класс из файла <%1>: %2", 
+				ИмяФайла, 
+				ОписаниеОшибки());
+		КонецПопытки;
 	КонецЦикла;
 
 	Возврат ПодключенныеТипы;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Функция ПодключитьТипы()
ПодключенныеТипы = Новый Массив();
Для Каждого ИмяФайла Из НайтиФайлыБенчмарков() Цикл
Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
Если Не Тип = Неопределено Тогда
ПодключенныеТипы.Добавить(Тип);
КонецЕсли;
КонецЦикла;
Возврат Каталоги;
Возврат ПодключенныеТипы;
КонецФункции
Функция ПодключитьТипы()
ПодключенныеТипы = Новый Массив();
Для Каждого ИмяФайла Из НайтиФайлыБенчмарков() Цикл
Попытка
Тип = Бенчмаркинг.ПодключитьКласс(ИмяФайла);
Если Не Тип = Неопределено Тогда
ПодключенныеТипы.Добавить(Тип);
КонецЕсли;
Исключение
_Лог.Ошибка("Не удалось подключить класс из файла <%1>: %2",
ИмяФайла,
ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Возврат ПодключенныеТипы;
КонецФункции
🤖 Prompt for AI Agents
In src/BenchmarkOneScript/cmd/Классы/КомандаЗапуска.os around lines 115 to 127,
the loop calling Бенчмаркинг.ПодключитьКласс(ИмяФайла) can throw and abort the
whole function; wrap the per-file call in a try-catch so a thrown exception for
one benchmark does not stop processing others, on catch log or record the error
including ИмяФайла and the exception message, continue the loop, and still
return the ПодключенныеТипы array at the end.


Функция ФайлыБенчмарков()
Функция НайтиФайлыБенчмарков()

Файлы = Новый Массив();

Для Каждого ИмяФайла Из _МассивФайлов Цикл
Если Не ФС.КаталогСуществует(ИмяФайла) Тогда
Файлы.Добавить(ПолноеИмяФайлаСценария(ИмяФайла));
Если ФС.КаталогСуществует(ИмяФайла) Тогда
НайденныеФайлы = НайтиФайлы(ИмяФайла, , _Рекурсивно);
Для Каждого ИмяФайлаВКаталоге Из НайденныеФайлы Цикл
Если Файлы.Найти(ИмяФайлаВКаталоге) = Неопределено Тогда
Файлы.Добавить(ИмяФайлаВКаталоге);
КонецЕсли;
КонецЦикла;
Иначе
ПолноеИмяФайла = ПолноеИмяФайлаСценария(ИмяФайла);
Если Файлы.Найти(ПолноеИмяФайла) = Неопределено Тогда
Файлы.Добавить(ПолноеИмяФайла);
КонецЕсли;
КонецЕсли;
КонецЦикла;

Expand All @@ -131,11 +167,10 @@

КонецФункции

Функция ПрочитатьКонфигурацию()
Функция ПрочитатьКонфигурацию(Настройки)

Если ЗначениеЗаполнено(_ФайлКонфигурации) Тогда
Сериализатор = Новый СериализаторКонфигурацииБенчмарков();
Конфигурация = Сериализатор.ДесериализоватьИзJSON(_ФайлКонфигурации);
Если Настройки <> Неопределено Тогда
Конфигурация = Настройки.Конфигурация;
Иначе
Конфигурация = Новый КонфигурацияБенчмарков();
КонецЕсли;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
#Использовать delegate
#Использовать validate
#Использовать reflector
#Использовать "../../dto"

&Сериализуемое("Type")
&Тип("Тип")
&Заполнено
Перем _Тип; // Тип - Класс бенчмарков

&Сериализуемое("Method")
&Тип("Строка")
&Заполнено
Перем _Метод; // Строка - Метод бенчмарка

&Сериализуемое("IsBaseline")
&Тип("Булево")
Перем _ЭтоЭталон; // Булево

&Сериализуемое("Category")
&Тип("Строка")
Перем _Категория; // Строка
Перем _НаборыПараметров; // Массив из Массив из ПараметрБенчмарка
Перем _ИменаПараметров; // Массив из Строка

&Сериализуемое("ParameterSets")
&Тип("Массив")
&ДляКаждого
&Тип("ПараметрыМетодаБенчмарка")
Перем _НаборыПараметров; // Массив из ПараметрыМетодаБенчмарка

&Сериализуемое("ParameterSources")
&Тип("Массив")
Перем _ИсточникиПараметров; // Массив из Строка, Делегат

&Несериализуемое
Перем _ИменаПараметров; // Массив из Строка

#Область Конструктор

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

_Тип = ?(ТипЗнч(Объект) = Тип("Тип"), Объект, ТипЗнч(Объект));
_Метод = Метод;
Expand All @@ -24,7 +50,9 @@
_Категория = "";
_ИсточникиПараметров = Новый Массив();

ИзвлечьИменаПараметров(Объект);
Если Не Объект = Неопределено Тогда
ИзвлечьИменаПараметров(Объект);
КонецЕсли;

КонецПроцедуры

Expand All @@ -51,7 +79,7 @@
// Наборы параметров, используемые для запуска бенчмарков с различными входными данными.
//
// Возвращаемое значение:
// Массив из Массив из ПараметрБенчмарка
// Массив из ПараметрыМетодаБенчмарка
Функция НаборыПараметров() Экспорт
Возврат Новый Массив(Новый ФиксированныйМассив(_НаборыПараметров));
КонецФункции
Expand All @@ -67,7 +95,7 @@
// ЭтотОбъект
Функция ДобавитьПараметры(Параметры) Экспорт

МассивПараметров = Новый Массив();
ПараметрыМетода = Новый ПараметрыМетодаБенчмарка();
КоличествоТребуемыхПараметров = _ИменаПараметров.Количество();

Если КоличествоТребуемыхПараметров = 0 Тогда
Expand All @@ -90,7 +118,7 @@

Для ИндексПараметра = 0 По Параметры.ВГраница() Цикл
Параметр = Новый ПараметрБенчмарка(_ИменаПараметров[ИндексПараметра], Параметры[ИндексПараметра], Истина);
МассивПараметров.Добавить(Параметр);
ПараметрыМетода.Добавить(Параметр);
КонецЦикла;

Иначе
Expand All @@ -104,11 +132,11 @@
КонецЕсли;

Параметр = Новый ПараметрБенчмарка(_ИменаПараметров[0], Параметры, Истина);
МассивПараметров.Добавить(Параметр);
ПараметрыМетода.Добавить(Параметр);

КонецЕсли;

_НаборыПараметров.Добавить(МассивПараметров);
_НаборыПараметров.Добавить(ПараметрыМетода);

Возврат ЭтотОбъект;

Expand Down Expand Up @@ -239,6 +267,17 @@
Возврат Делегаты.Создать(Объект, _Метод, Параметры);
КонецФункции

#Область Сериализация

Процедура ПослеДесериализации() Экспорт

Check notice on line 272 in src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os#L272

Возможная опечатка в "Десериализации"

Check notice on line 272 in src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os#L272

Добавьте описание метода программного интерфейса

Валидировать();
ИзвлечьИменаПараметров(Новый(_Тип));

КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции
Expand All @@ -254,4 +293,15 @@

КонецПроцедуры

Процедура Валидировать()

Check notice on line 296 in src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/BenchmarkOneScript/core/Классы/ДескрипторБенчмарка.os#L296

Возможная опечатка в "Валидировать"

Валидатор = Новый Валидатор;

Результат = Валидатор.Валидировать(ЭтотОбъект);
Если Результат.Количество() > 0 Тогда
ВызватьИсключение Валидатор.ОписаниеОшибокВалидации(Результат);
КонецЕсли;

КонецПроцедуры

#КонецОбласти
Loading
Loading