415 lines
46 KiB
Markdown
415 lines
46 KiB
Markdown
# Все объекты, скорость 6
|
||
|
||
Создано скриптом `tests/create_full_benchmark_save.gd`. Пароль нативного сохранения: `qwerty`.
|
||
Генератор не читает и не перезаписывает сохранение игрока.
|
||
|
||
Начальное состояние: 151 запись каталога (включая группы), все 44 стадии правил цивилизаций, все шесть этик на каждой стадии, 1000 когорт (по десять на сущность с временными партиями). У большинства обычных объектов количество равно 6e60, у стадий цивилизаций — 6e20. Пространство и водород имеют количество 1e90, гелий и металлы — 1e80, энергия — 1e100. Возраст — 1e15 лет. Запасов достаточно для требований продвинутых стадий звезд и структур. Оставшиеся сроки жизни когорт покрывают весь срок жизни сущностей, поэтому переходы происходят во время замера.
|
||
|
||
Это искусственный экстремальный сценарий, а не прогноз для обычного сохранения.
|
||
|
||
Машина: Apple M4 Pro, Godot 4.7.2, рендерер Metal Mobile.
|
||
|
||
| Замер | Результат |
|
||
|---|---:|
|
||
| Headless, скорость 6, шесть шагов по 0,5 секунды | 943,936–1221,992 мс на шаг |
|
||
| Среднее время headless-шага | 1122,287 мс |
|
||
| Пропускная способность headless | 0,446 секунды симуляции на секунду CPU |
|
||
| Настоящий UI, страница цивилизаций, 600 кадров | 17,38 FPS |
|
||
| Средний / p95 / максимальный кадр UI | 57,55 / 99,78 / 116,94 мс |
|
||
| Завершенные транзакции | 23 |
|
||
| Запрошенный прирост игрового времени | 3464662,267 лет |
|
||
| Опубликованный прирост игрового времени | 1080000 лет |
|
||
| Пропускная способность с UI | 0,3117 |
|
||
| Накопленный долг за замер | 2384662,267 игровых лет (23,85 реальных секунд на скорости 6) |
|
||
| Записей каталога осталось в конце | 151 |
|
||
|
||
Динамический шаг достигает предела в 0,5 секунды. Рендеринг идет быстрее 5 FPS, но симуляция не успевает за заданным темпом в этом сценарии. На обработку поколений приходится примерно 94% времени CPU. Подготовка цивилизаций занимает в среднем 634 мс на шаг, в том числе дрифт этик — 218 мс, войны — 124 мс; колонизация — 121 мс на шаг. Интервалы профилировщика вложенные и частично перекрываются.
|
||
|
||
## Сравнение оптимизации дрифта (2026-10-05)
|
||
|
||
Замеры сделаны на одном сгенерированном сохранении и одной машине до и после прямого распределения потоков для обычного и колониального дрифта, а также кеширования ставок дипломатии в фиксированной точке. Каждый headless-запуск выполняет шесть последовательных шагов по 0,5 секунды на каждой скорости.
|
||
|
||
| Замер | До | После |
|
||
|---|---:|---:|
|
||
| Средний headless-шаг на скорости 6 | 1122,287 мс | 1018,559 мс |
|
||
| Пропускная способность headless на скорости 6 | 0,446 | 0,491 |
|
||
| Дрифт этик, сумма интервалов за шесть шагов | 1,338 с | 0,643 с |
|
||
| UI, FPS за 600 кадров | 17,38 | 17,04 |
|
||
| Средний / p95 / максимальный кадр UI | 57,55 / 99,78 / 116,94 мс | 58,70 / 102,67 / 114,30 мс |
|
||
| Завершенные UI-транзакции | 23 | 25 |
|
||
| Запрошено / опубликовано игровых лет в UI | 3464662 / 1080000 | 3533627 / 1180000 |
|
||
| Пропускная способность симуляции с UI | 0,3117 | 0,3339 |
|
||
|
||
Средний headless-шаг ускорился примерно на 9,2%, а интервал профиля дрифта этик сократился примерно на 52%. Частота кадров UI практически не изменилась (в этом запуске снизилась примерно на 2%), при этом завершилось больше транзакций и выросла доля опубликованного игрового времени. На скорости 6 стресс-сценарий все еще отстает от реального времени: пропускная способность — около 0,49 секунды симуляции на секунду CPU в headless и 0,33 с UI. Самыми затратными остаются планирование поколений и войны.
|
||
|
||
Прямые пути сохраняют целое население, но разносят малые целочисленные потоки по нескольким последовательным переходам с помощью остатков для каждого источника. Поэтому распределение в отдельном переходе отличается от независимого округленного распределения по матрице 6×6. Ставки дипломатии округляются до сетки фиксированной точки с шагом 1e-9. Целевая регрессия: 769 проверок эволюции цивилизаций, оптимизаций симуляции, границ партий, укрупненных поколений и эволюции кадров; все пройдены.
|
||
|
||
## Последующая оптимизация подготовки поколений и кешей (2026-10-05)
|
||
|
||
На той же нагрузке среднее время headless-шага на скорости 6 снизилось с 1018,559 до 1005,138 мс (примерно на 1,3%). Пропускная способность headless изменилась с 0,491 до 0,497. Суммарные интервалы `generations` близки: 5,703 с и 5,629 с за шесть шагов. Подготовка цивилизаций остается самой затратной измеренной подфазой — 3,130 с. UI также почти не изменился: 17,04 → 17,09 FPS, пропускная способность симуляции — 0,3339 → 0,3351. Улучшение небольшое: арифметика населения в поколениях по-прежнему дорога при сотнях активных когорт и множестве правил цивилизаций.
|
||
|
||
Профиль теперь отдельно показывает `generation_withdrawal` и `generation_products`. Первый интервал занимает 55,5 мс, второй — 120,2 мс за шесть headless-шагов на скорости 6. Эти значения нельзя складывать с общим временем поколений, поскольку интервалы профилировщика вложенные.
|
||
|
||
## Инкрементальная обработка партий новорожденных (2026-10-05)
|
||
|
||
Удалены снимки когорт до и после рождения и последующий полный обход когорт. `append_batch` теперь сразу накапливает поправку на возраст новорожденных при добавлении частей когорт. Финальный замер после повторного использования сумм завершившихся партий в пределах поколения дал 1028,991 мс на headless-шаг скорости 6 и пропускную способность 0,486. В повторных прогонах этой же версии получилось 1005–1011 мс, поэтому при выборке всего в шесть шагов разброс велик, и устойчивое ускорение утверждать нельзя. В UI получилось 17,05 FPS, среднее время кадра 58,66 мс и пропускная способность 0,3342. Новый профиль показывает 319 мс на обработку партий новорожденных за шесть шагов. Это изменение пока не демонстрирует снижения общего времени на этом сохранении; его потенциальная польза относится прежде всего к сценариям с гораздо большим числом когорт на сущность, где прежние обходы росли пропорционально числу когорт.
|
||
|
||
Повторить замеры из родительской папки проекта:
|
||
|
||
```sh
|
||
godot --headless --path Owniverse.GI --script res://tests/create_full_benchmark_save.gd
|
||
godot --headless --path Owniverse.GI --script res://tests/benchmark_saved_state.gd -- Owniverse.GI/tests/artifacts/all_objects_speed6.adventure.json 0.5 profile
|
||
godot --path Owniverse.GI --script res://tests/benchmark_full_ui.gd
|
||
```
|
||
|
||
## Проверка на Android Note8 (2026-10-06)
|
||
|
||
Сборка benchmark установлена отдельным пакетом `com.KIDGameProduction.Owniverse.AndroidBench`, сохранение основной игры не использовалось. Подготовка и декодирование сохранения выполнялись в фоновом потоке; ход и результат записывались в файл приложения. Устройство: Samsung SM-N950F, Android 9. Сценарий: все объекты и цивилизации, скорость 6, 120 кадров (119 интервалов).
|
||
|
||
| Метрика | Результат |
|
||
|---|---:|
|
||
| FPS UI | 1,76 |
|
||
| Средний / p95 / максимальный кадр | 567,28 / 817,54 / 1278,33 мс |
|
||
| Завершенные транзакции за прогон | 1 |
|
||
| Запрошено / опубликовано игрового времени | 1599938,57 / 10000 лет |
|
||
| Доля опубликованного от запрошенного | 0,00625 |
|
||
| Итоговый динамический шаг | 0,2 с |
|
||
|
||
Самый дорогой участок профиля — `generations`: 5,350 с суммарно за единственную завершенную транзакцию; внутри него `civilization_prepare` занял 3,186 с, `wars` — 2,217 с, `civilization_transitions` — 1,034 с. Интервалы вложены, поэтому их нельзя складывать с `generations`. Этот экстремальный сценарий на Note8 не достигает целевых 5 FPS и сильно отстает по игровому времени. Это замер именно полного стресс-сохранения, а не обычного игрового сохранения.
|
||
|
||
### Покадровая уступка в расчётах цивилизаций
|
||
|
||
Добавлены контрольные точки внутри обработки этик, проигравших в войне, падения популяции и выходов между стадиями. Математика и порядок переходов не меняются. На том же Note8 повторный прогон дал 1,87 FPS против 1,76 FPS до изменения (прирост около 6%). Средний кадр сократился с 567 до 535 мс, но p95 остался 630 мс, максимум — 1281 мс. Это слишком малое улучшение для цели 5 FPS.
|
||
|
||
В повторном профиле `generations` заняли 5,166 с, `civilization_prepare` — 3,040 с, войны — 0,985 с, переходы между стадиями — 0,640 с. Профиль не показывает явного трёхкратного ускорения: контрольные точки лучше дробят отдельные подциклы, но главный синхронный участок остается слишком дорогим. Диагностическая сборка для измерения максимального непрерывного участка не завершила прогон на телефоне; при следующем проходе сначала нужно локализовать этот участок, а затем оптимизировать его отдельно.
|
||
|
||
Контрольный запуск UI-бенчмарка на Apple M4 Pro после изменения: 21,51 FPS, средний / p95 / максимальный кадр — 46,49 / 89,62 / 107,19 мс. Этот результат подтверждает отсутствие регрессии на компьютере, но не заменяет Android-замер.
|
||
|
||
### После перехода этик на доли (2026-10-06)
|
||
|
||
Этическое состояние теперь хранит шесть долей `float`, а точное целое население берётся из реестра объектов. Исходы одной стадии сначала собираются по назначениям; доли состояния обновляются после агрегации потоков. Формат сохранения повышен до версии 6; миграции прежних сохранений нет.
|
||
|
||
Финальная APK повторно проверена на Samsung SM-N950F, Android 9, тем же полным сценарием и 120 кадрами. Два последовательных прогона дали **14,57 и 15,02 FPS**, средний кадр — **68,61 и 66,58 мс**, p95 — **113,03 и 123,03 мс**, по одной завершённой транзакции из 119 интервалов. Опубликовано 10 000 лет из 647 331 и 634 134 запрошенных; пропускная способность — 0,01545 и 0,01577. В последнем профиле `generations` заняли 5,120 с, `civilization_prepare` — 3,162 с, войны — 1,026 с, переходы — 0,728 с, дрейф этик — 0,474 с. Самый длинный непрерывный участок составил **458,14 мс** в `deep_copy_and_coarsen`, максимальный кадр — 976 мс. Предыдущий одиночный запуск старой benchmark-сборки показал 1,83 FPS, поэтому сравнивать его с этой парой напрямую нельзя; оба финальных прогона выполнены на одной APK и подтверждают результат около 15 FPS.
|
||
|
||
На компьютере прошли тесты состояния (70), эволюции (555), оптимизаций симуляции (364), индикаторов (63) и жизни (25). Полный набор всё ещё сообщает о двух отказах в `test_descriptions.gd` при обновлении выбранного описания и смене языка; оба относятся к UI-описаниям, а не к модели этик. В логах Android ошибок GDScript/Godot за прогон не найдено.
|
||
|
||
|
||
## Непрерывная модель цивилизаций — 2026-10-06
|
||
|
||
Сравнены исходная симуляция из коммита `6ee66a6` и новая модель потоков. Оба запуска используют один диагностический JSON, скорость 6, 100 последовательных полных циклов с запросом 0,1 секунды каждый и включённый CPU-профиль. Подготовка каталога и чтение JSON не включены в длительность цикла. Запуски выполнены последовательно, без параллельных тестов. Сохранение игрока не читалось и не изменялось.
|
||
|
||
| Полный цикл и пропускная способность | До | После |
|
||
|---|---:|---:|
|
||
| Среднее время полного цикла | 811,292 мс | 401,796 мс |
|
||
| Минимум / максимум | 488,914 / 963,141 мс | 323,427 / 435,607 мс |
|
||
| Завершённых полных циклов в секунду | 1,233 | 2,489 |
|
||
| Обработанных секунд симуляции на секунду CPU | 0,123 | 0,249 |
|
||
| Применено игровых лет за 100 циклов | 1 000 000 | 1 000 000 |
|
||
|
||
Полный цикл ускорился в **2,02 раза**, среднее время сократилось на **50,5%**. Цель **100 мс / 10 полных циклов в секунду не достигнута**: для неё требуется ещё примерно 4,02-кратное ускорение текущей версии. При непрерывном запросе времени на шестой скорости и шаге 0,1 секунды этот стресс-сценарий продолжит накапливать долг. Это измерение полных завершённых шагов симуляции, без показателя FPS.
|
||
|
||
Текущие внешние интервалы CPU-профиля, по убыванию среднего времени на цикл:
|
||
|
||
| Расчёт | Среднее за цикл |
|
||
|---|---:|
|
||
| Поколения звёзд и биологической жизни | 151,6 мс |
|
||
| Подготовка непрерывных потоков цивилизаций | 98,5 мс |
|
||
| Применение потоков к количествам и владельцам | 53,2 мс |
|
||
| Производство за период | 28,7 мс |
|
||
| Тренды | 18,1 мс |
|
||
| Дрейф, проверка вместимости и поклонение после потоков | 8,8 мс |
|
||
| Инициализация жизни | 6,1 мс |
|
||
| Ограничение потоков ресурсными бюджетами | 5,8 мс |
|
||
| Применение колонизации | 5,5 мс |
|
||
|
||
Внутри подготовки потоков разреженный оператор занимает 24,5 мс на цикл; этот вложенный интервал нельзя прибавлять к 98,5 мс. Внешние интервалы не покрывают всё время: остальная работа включает копирование транзакции, построение физических снимков и обновление представления.
|
||
|
||
Модель C0.2–C4.4 теперь использует точные целые количества и шесть долей float без возрастных партий. Оператор учитывает несколько последовательных переходов за интервал. Конечные количества и ресурсные потолки сохраняются точно; пропорции потоков и владельцев приближены float и квантованием долей до 15 десятичных знаков. Изменяется распределение событий во времени, поэтому тесты проверяют законы новой модели, сохранение количества, владение, ресурсные ограничения и воспроизводимое продолжение сохранения.
|
||
|
||
Регрессия: 27 из 28 наборов прошли. Новые переходы — 1895 проверок; арифметика распределения и кеши — 1889; кадровое выполнение — 24. В `test_descriptions.gd` сохраняются две ранее обнаруженные ошибки обновления выбранного описания и языка; этот UI-код не изменён в данном рефакторинге.
|
||
|
||
Повторение из папки `Owniverse.GI`:
|
||
|
||
```sh
|
||
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- tests/artifacts/all_objects_speed6.adventure.json 0.1 profile cycles=100
|
||
```
|
||
|
||
## Фиксированные пять циклов в секунду — 2026-10-07
|
||
|
||
Текущая версия после отката агрегации и возврата 40 возрастных групп.
|
||
Планировщик использует шаг 0,2 реальной секунды на всех скоростях. Замер:
|
||
диагностическое сохранение со всеми объектами и цивилизациями, скорость 6,
|
||
100 полных синхронных циклов с CPU-профилем, без отрисовки интерфейса.
|
||
Проверка сохранения: OK. Исходное сохранение не изменялось.
|
||
|
||
| Метрика | Результат |
|
||
|---|---:|
|
||
| Среднее время полного цикла | 439,228 мс |
|
||
| Минимум / максимум | 340,370 / 483,152 мс |
|
||
| Завершённых полных циклов в секунду | 2,277 |
|
||
| Требуется циклов в секунду | 5 |
|
||
| Обработано игровых лет | 2 000 000 |
|
||
| Запрошенное время сценария | 20 с |
|
||
| Время расчёта 100 циклов | 43,923 с |
|
||
| Пропускная способность | 0,455 с симуляции / с расчёта |
|
||
|
||
Цель 200 мс на полный цикл не достигнута: по среднему времени требуется
|
||
ускорение примерно в 2,20 раза. Увеличение шага с 0,1 до 0,2 секунды улучшило
|
||
отношение обработанного времени к затратам, но при непрерывном поступлении
|
||
времени этот стресс-сценарий продолжит накапливать долг. Это измерение
|
||
пропускной способности симуляции, без оценки FPS. Один прогон не задаёт
|
||
гарантированную производительность для других сохранений или устройств.
|
||
|
||
Внешние интервалы CPU-профиля, по убыванию среднего времени на цикл:
|
||
|
||
| Расчёт | Среднее на цикл |
|
||
|---|---:|
|
||
| Поколения звёзд и биологической жизни | 168,294 мс |
|
||
| Подготовка непрерывных потоков цивилизаций | 111,835 мс |
|
||
| Применение потоков к количествам и владельцам | 59,516 мс |
|
||
| Производство за период | 29,248 мс |
|
||
| Тренды | 17,787 мс |
|
||
| Завершение цивилизационных потоков | 8,864 мс |
|
||
| Ограничение потоков вместимостью | 6,439 мс |
|
||
| Инициализация жизни | 6,172 мс |
|
||
| Колонизация | 6,111 мс |
|
||
|
||
Вложенные интервалы нельзя прибавлять к внешним: построение физических
|
||
снимков — 27,845 мс/цикл; изъятие партий — 42,015 мс/цикл; решение оператора
|
||
цивилизаций — 31,835 мс/цикл. Проверки кадрового планировщика:
|
||
35 проверок, 0 ошибок, включая все шесть скоростей, сохранение долга,
|
||
возобновление расчёта и пять завершённых циклов на одну секунду запроса.
|
||
|
||
```sh
|
||
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- tests/artifacts/all_objects_speed6.adventure.json 0.2 profile cycles=100
|
||
```
|
||
|
||
## Новые звёздные партии с целым переходом за цикл — 2026-10-07
|
||
|
||
На скоростях 4–6 новые звёзды одного типа объединяются по общей границе
|
||
завершения жизни и переходят целиком. Временная сетка равна одному полному
|
||
циклу (200/2000/20000 игровых лет). Старые постепенные партии из сохранения
|
||
не преобразуются; SN/GRB сохраняют прежнюю обработку.
|
||
|
||
Повторён тот же замер: диагностическое сохранение, скорость 6, шаг 0,2 с,
|
||
100 полных циклов с CPU-профилем. Проверка сохранения OK.
|
||
|
||
| Метрика | До | После |
|
||
|---|---:|---:|
|
||
| Среднее время полного цикла | 439,228 мс | 445,690 мс |
|
||
| Минимум / максимум | 340,370 / 483,152 мс | 345,276 / 486,647 мс |
|
||
| Полных циклов в секунду | 2,277 | 2,244 |
|
||
| Пропускная способность | 0,455 | 0,449 |
|
||
| Обработано игровых лет | 2 000 000 | 2 000 000 |
|
||
| Поколения, среднее на цикл | 168,294 мс | 171,039 мс |
|
||
| Обработка партий новорождённых, среднее на цикл | 7,768 мс | 6,199 мс |
|
||
| Вызовы обработки партий новорождённых | 16 147 | 13 885 |
|
||
|
||
Общего ускорения на этой выборке нет: среднее выросло примерно на 1,5%.
|
||
Обработка новорождённых занимает на 20% меньше времени, но это небольшая
|
||
доля полного цикла. Замер включает существующие постепенные партии;
|
||
он не доказывает ускорения вселенной, целиком созданной по новой схеме.
|
||
Цель пяти полных циклов в секунду остаётся недостигнутой.
|
||
|
||
Проверки: границы партий — 109, звёздные правила — 333, короткие события —
|
||
841, укрупнённые поколения — 28, кадровое выполнение — 35; все без ошибок.
|
||
Тестируются точные большие количества, целый однократный переход,
|
||
распределённые рождения, сохранения и интеграл производства.
|
||
|
||
## Первоначальный замер больших сохранений до исправления сетки — 2026-10-07
|
||
|
||
Созданы `large_star_cohorts_legacy.adventure.json` и
|
||
`large_star_cohorts_cycle.adventure.json`: по 6×10^60 звёзд каждого из 15
|
||
типов (главная последовательность и красные гиганты), остальные объекты,
|
||
жизнь и цивилизации взяты из диагностического сценария. Возраст — 10^12 лет.
|
||
Для каждого типа заново сформирована одинаковая история рождения длиной
|
||
`min(эффективный срок жизни, 2 млн лет)` перед началом завершения жизни.
|
||
Исходные физические количества и этические профили совпадают строго.
|
||
Сохранения валидируются и проходят точное сравнение состояния после записи
|
||
и чтения JSON с полной точностью float. Сохранение игрока не изменялось.
|
||
|
||
Старая схема измеряется переключателем `batches.cycle_stars = false`, новая
|
||
включена по умолчанию. В обоих вариантах одинаковый остальной код симуляции,
|
||
скорость 6, шаг 0,2 с и CPU-профиль. Два прогона по 50 полных циклов на модель,
|
||
порядок запусков: старая → новая → новая → старая. Перед каждым прогоном
|
||
восстанавливается исходное состояние; каждый обрабатывает 1 млн игровых лет.
|
||
|
||
| Метрика | Старая схема | Новая схема |
|
||
|---|---:|---:|
|
||
| Среднее первого прогона | 417,265 мс | 423,419 мс |
|
||
| Среднее второго прогона | 431,081 мс | 427,011 мс |
|
||
| Среднее всех 100 циклов на модель | 424,173 мс | 425,215 мс |
|
||
| Полных циклов в секунду | 2,358 | 2,352 |
|
||
| Пропускная способность | 0,472 | 0,470 |
|
||
| Звёздных партий в исходном сохранении | 118 | 1 300 |
|
||
| Пиковое число звёздных партий | 132 | 1 300 |
|
||
| Поколения, среднее на цикл | 157,711 мс | 147,906 мс |
|
||
| Производство, среднее на цикл | 28,692 мс | 34,704 мс |
|
||
| Применение потоков цивилизаций, среднее на цикл | 58,642 мс | 62,160 мс |
|
||
| Изъятие партий, вложенное в поколения | 37,015 мс | 41,379 мс |
|
||
| Партии новорождённых, вложенное в поколения | 7,648 мс | 4,248 мс |
|
||
|
||
**Устойчивого выигрыша полного цикла не обнаружено.** Разница средних —
|
||
около +0,25% у новой схемы; в первом парном сравнении она медленнее, во втором
|
||
быстрее. Поколения занимают примерно на 6,2% меньше времени, но производство
|
||
стало дороже примерно на 21%. Пять полных циклов в секунду не достигнуты.
|
||
|
||
Причина роста числа партий: для долгоживущих звёзд сетка одного цикла
|
||
значительно мельче `lifespan / 40`. Например, у RD прежняя ширина — 1 млрд
|
||
лет, новая на скорости 6 — 20 тыс. лет. Поэтому изменение не всегда
|
||
укрупняет партии: на таком наборе исходных рождений их стало в 11 раз больше.
|
||
Итоговое временное распределение переходов у моделей различается; совпадение
|
||
их конечных состояний не является условием этого замера.
|
||
|
||
Для дальнейшего упрощения следует сохранять широкие группы долгоживущих
|
||
звёзд и применять целый переход только к партиям, уже укладывающимся в один
|
||
цикл. Это предложение в данном замере не реализовано.
|
||
|
||
```sh
|
||
godot --headless --path . --script res://tests/benchmark_large_star_cohorts.gd -- cycles=50 repeats=2
|
||
```
|
||
|
||
Полные результаты первоначального замера: `large_star_cohorts_before_dynamic_fix_results.json`.
|
||
Набор с 1300 партиями сохранён в `large_star_cohorts_before_dynamic_fix_cycle.adventure.json`.
|
||
Последующие файлы без этого суффикса относятся к исправленной динамической схеме.
|
||
|
||
## Исправленное динамическое укрупнение без дробления — 2026-10-07
|
||
|
||
Ошибка первоначальной реализации устранена: циклическая сетка больше не
|
||
заменяет широкие возрастные окна долгоживущих звёзд. При создании новая сетка
|
||
используется только если прежнее окно не шире цикла. Иначе используется
|
||
прежнее широкое окно. Из существующих партий объединяются две или более
|
||
одного типа, чей оставшийся интервал завершения целиком лежит в общем цикле.
|
||
Партии, пересекающие границу циклов или занимающие несколько циклов, не делятся.
|
||
|
||
Повторён парный замер на отдельных больших сохранениях, с теми же исходными
|
||
количествами и входными интервалами рождения: скорость 6, шаг 0,2 с,
|
||
два прогона по 50 циклов на модель в порядке старая → новая → новая → старая.
|
||
Каждый прогон обрабатывает 1 млн игровых лет; состояния валидируются до и
|
||
после, записанные файлы проходят точное сравнение после чтения.
|
||
|
||
| Метрика | Старая схема | Исправленная динамическая |
|
||
|---|---:|---:|
|
||
| Исходных звёздных партий | 118 | 113 |
|
||
| Пиковое число партий | 132 | 127 |
|
||
| Число партий после 50 циклов | 130 | 125 |
|
||
| Среднее первого прогона | 420,388 мс | 424,307 мс |
|
||
| Среднее второго прогона | 431,605 мс | 428,498 мс |
|
||
| Среднее всех 100 циклов на модель | 425,996 мс | 426,402 мс |
|
||
| Полных циклов в секунду | 2,347 | 2,345 |
|
||
| Поколения, среднее на цикл | 158,622 мс | 157,606 мс |
|
||
| Партии новорождённых, вложенный интервал | 7,679 мс | 6,693 мс |
|
||
|
||
На этом наборе партиям стало меньше примерно на 4,2%, вместо прежнего
|
||
ошибочного роста до 1300. Проверено, что долгая группа RD остаётся одной
|
||
широкой партией и её окно не меняется при добавлении новых звёзд.
|
||
Новый тест запрещает рост числа исходных партий в диагностическом сценарии.
|
||
|
||
Устойчивого ускорения полного цикла по этим прогонам нет: разница средних
|
||
около +0,10%; знак разницы в отдельных парных сравнениях меняется.
|
||
Обработка партий новорождённых занимает примерно на 13% меньше времени,
|
||
но её доля недостаточна для заметного выигрыша всего расчёта.
|
||
Цель пяти циклов в секунду по-прежнему не достигнута.
|
||
|
||
Проверки: границы партий — 117, звёздные правила — 333, короткие события —
|
||
841, кадровое выполнение — 35; все без ошибок. Дополнительные проверки
|
||
охватывают сохранение широких окон, объединение старых партий с точными
|
||
количествами и остатками, соседние циклы и повторное укрупнение.
|
||
|
||
Актуальные сохранения: `large_star_cohorts_legacy.adventure.json` и
|
||
`large_star_cohorts_cycle.adventure.json`; результаты: `large_star_cohorts_results.json`.
|
||
|
||
## Новая вселенная с множеством объектов и мелких звёздных партий — 2026-10-07
|
||
|
||
Создано отдельное состояние с нуля по текущим таблицам: 150 типов объектов,
|
||
все 44 стадии этических цивилизаций (включая Ct), 15 типов живых звёзд.
|
||
Запасы большинства объектов — 10^60 каждого типа; планет и цивилизаций —
|
||
10^28. Жизнь размещена у четырёх типов карликов, четверть звёзд каждого типа
|
||
связана со структурами. Этические профили различаются между стадиями.
|
||
Высокий запас пространства сохраняет жизнь при бластах. Интерфейс не отрисовывался.
|
||
|
||
Для проверки укрупнения заданы валидные синтетические исторические партии:
|
||
40 последовательных циклов завершения × 8 узких партий × 15 типов звёзд.
|
||
Все восемь партий типа целиком завершаются в общем цикле; это целевой
|
||
стресс-сценарий большого числа партий, а не утверждение, что обычное создание
|
||
с неизменным временем жизни обязательно порождает такую фрагментацию.
|
||
Исходный состав и интервалы одинаковы для обеих моделей. Долгоживущие звёзды
|
||
не дробились алгоритмом: ему переданы уже существующие узкие партии.
|
||
|
||
До укрупнения — 4800 звёздных партий. Старая схема сохраняет 4560,
|
||
исправленная динамическая — 600. Созданы два отдельных диагностических файла,
|
||
проверены запись/чтение без изменения состояния и валидация до и после каждого
|
||
прогона. Сохранение игрока не затрагивалось.
|
||
|
||
Два прогона по 40 полных циклов на модель; порядок старая → новая → новая →
|
||
старая. Скорость 6, фиксированный шаг 0,2 с, CPU-профиль включён.
|
||
Каждый прогон восстанавливает исходное состояние и обрабатывает 800 тыс. лет.
|
||
|
||
| Метрика | Старая схема | Динамическое укрупнение |
|
||
|---|---:|---:|
|
||
| Исходных звёздных партий после укрупнения | 4 560 | 600 |
|
||
| Пиковое число партий | 4 560 | 607 |
|
||
| Среднее первого прогона | 612,606 мс | 530,285 мс |
|
||
| Среднее второго прогона | 624,625 мс | 532,578 мс |
|
||
| Среднее всех 80 циклов на модель | 618,616 мс | 531,431 мс |
|
||
| Полных циклов в секунду | 1,617 | 1,882 |
|
||
| Обработанных секунд симуляции / секунду расчёта | 0,323 | 0,376 |
|
||
| Поколения, среднее на цикл | 211,916 мс | 138,339 мс |
|
||
| Производство, среднее на цикл | 51,201 мс | 38,038 мс |
|
||
| Подготовка потоков цивилизаций | 113,371 мс | 113,270 мс |
|
||
| Применение потоков цивилизаций | 114,343 мс | 113,820 мс |
|
||
| Колонизация | 55,284 мс | 55,291 мс |
|
||
| Обработка партий новорождённых, вложенная в поколения | 29,464 мс | 2,967 мс |
|
||
|
||
**Выигрыш полного цикла подтверждён обоими парными сравнениями:** время
|
||
сократилось на 14,1%, ускорение около 1,16 раза. Поколения занимают на 34,7%
|
||
меньше времени. Механизм даёт эффект при множестве подходящих для объединения
|
||
партий; в предыдущем сценарии с небольшим числом широких партий эффект был
|
||
незаметен. Изменение моментов переходов допускается моделью: конечные состояния
|
||
двух схем не обязаны совпадать, но обе полностью обработали запрошенный интервал.
|
||
|
||
Пять циклов в секунду не достигнуты: для данного сценария требуется ещё
|
||
примерно 2,66-кратное ускорение. Главные оставшиеся затраты — поколения и
|
||
подготовка/применение цивилизационных потоков; колонизация также заметна.
|
||
|
||
Сохранения: `many_objects_fragmented_stars_legacy.adventure.json` и
|
||
`many_objects_fragmented_stars_cycle.adventure.json`.
|
||
Полные результаты: `many_objects_fragmented_stars_results.json`.
|
||
|
||
```sh
|
||
godot --headless --path . --script res://tests/benchmark_many_objects.gd -- cycles=40 repeats=2
|
||
```
|
||
|
||
## Консолидация применения потоков и колонизации — 2026-10-08
|
||
|
||
Первый этап: исходное население распределяется по строкам владельцев одной таблицы переходов. Свободные стадии применяют готовые целые квоты напрямую. При колонизации списания планет объединяются по владельцам; каждая стадия колоний получает одну суммарную выдачу. Общие целые количества и статистика сохранены. Изменён порядок распределения единичных остатков между владельцами; полного совпадения состояния с прежним порядком округления не заявляется. Ct остаётся свободной от привязок.
|
||
|
||
До и после загружались одни и те же диагностические файлы с теми же количествами и партиями. Скорость 6, полный интервал 0,2 секунды (20 000 игровых лет), CPU-профилирование включено, UI отсутствует. По два прогона из исходного состояния, каждый по 20 циклов: до → после → после → до. На каждую модель и сохранение обработано 800 000 игровых лет. Валидация начальных и конечных состояний прошла; SHA-256 входных файлов до и после совпали. Сохранение игрока не использовалось.
|
||
|
||
| Сохранение | До, мс | После, мс | Сокращение времени | Полных циклов/с после |
|
||
|---|---:|---:|---:|---:|
|
||
| Все объекты | 385,263 | 377,222 | 2,09% | 2,651 |
|
||
| Много объектов и партий | 506,888 | 443,303 | 12,54% | 2,256 |
|
||
|
||
Для тяжёлого сохранения:
|
||
|
||
| Участок | До, мс/цикл | После, мс/цикл |
|
||
|---|---:|---:|
|
||
| Применение переходов | 113,011 | 91,591 |
|
||
| Колонизация | 53,487 | 11,520 |
|
||
| Подготовка потоков | 114,808 | 114,742 |
|
||
| Поколения звёзд и жизни | 116,085 | 115,999 |
|
||
|
||
Первый этап сокращает полный тяжёлый цикл на 12.54%, но цель пяти циклов в секунду не достигнута. До 200 мс нужно ещё примерно 2.22-кратное ускорение. Следующие крупные затраты — подготовка цивилизационных потоков, поколения и оставшееся применение переходов.
|
||
|
||
Проверки: целочисленные квоты и владельцы, включая 10^400 + 103 — 1068; цивилизационные потоки — 1895; состояние цивилизаций — 70; кадровый планировщик — 38. Всего 3071 проверка без ошибок. Проверены сохранение населения каждого владельца при планетных переходах, точные поступления по стадиям, замена планет колониями, статистика и Ct.
|
||
|
||
Полные профили, отдельные прогоны и контрольные суммы: `flow_commit_step1_results.json`. Базовая версия: `413f2be9044090c878c2909dd9d0646f77513a5f`.
|
||
|
||
Для замера текущей версии на тех же входных файлах:
|
||
|
||
```sh
|
||
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- res://tests/artifacts/all_objects_speed6.adventure.json 0.2 profile cycles=20
|
||
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- res://tests/artifacts/many_objects_fragmented_stars_cycle.adventure.json 0.2 profile cycles=20
|
||
```
|