46 KiB
Все объекты, скорость 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 мс на обработку партий новорожденных за шесть шагов. Это изменение пока не демонстрирует снижения общего времени на этом сохранении; его потенциальная польза относится прежде всего к сценариям с гораздо большим числом когорт на сущность, где прежние обходы росли пропорционально числу когорт.
Повторить замеры из родительской папки проекта:
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:
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 ошибок, включая все шесть скоростей, сохранение долга, возобновление расчёта и пять завершённых циклов на одну секунду запроса.
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 раз больше.
Итоговое временное распределение переходов у моделей различается; совпадение
их конечных состояний не является условием этого замера.
Для дальнейшего упрощения следует сохранять широкие группы долгоживущих звёзд и применять целый переход только к партиям, уже укладывающимся в один цикл. Это предложение в данном замере не реализовано.
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.
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.
Для замера текущей версии на тех же входных файлах:
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