Implement civilization flow mechanics and profiling for resource allocation

- Added `civilization_flow.gd` to manage continuous expected flows and resource allocation within civilizations.
- Introduced `allocate_profiled` and `whole_quotas` functions in `quantity_math.gd` for precise stock allocation based on float shares.
- Enhanced `credit` logic in `object_ledger.gd` to handle production remainders more effectively.
- Updated `append_batch` in `object_batches.gd` to prevent batch creation for invalid IDs.
- Introduced `ratio_approx` function in `exact.gd` for better handling of float profiles.
- Added a benchmark script `benchmark_civilization_flows.gd` to evaluate the performance of civilization flow mechanics.
- Refactored various functions to improve clarity and efficiency in handling resource flows and allocations.
This commit is contained in:
Kirill
2026-10-07 22:51:55 +03:00
parent 6ee66a627d
commit 3fcc7211ce
41 changed files with 247959 additions and 817 deletions
@@ -92,3 +92,290 @@ godot --path Owniverse.GI --script res://tests/benchmark_full_ui.gd
Финальная 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
```
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,345 @@
{
"cycles_per_run": 50,
"delta_seconds": 0.2,
"profile_enabled": true,
"repeats": 2,
"runs": [
{
"cycles": 50,
"cycles_per_second": 2.39655612966922,
"final_stellar_cohorts": 130,
"game_years": "1000000",
"max_ms": 454.421,
"mean_ms": 417.26542,
"min_ms": 349.968,
"model": "legacy",
"p95_ms": 448.31,
"peak_stellar_cohorts": 132,
"profile": {
"assign_homes": [
58334,
200
],
"civilization_flow_capacity": [
308485,
50
],
"civilization_flow_colonies": [
272661,
50
],
"civilization_flow_finish": [
432935,
50
],
"civilization_flow_ledger": [
2884631,
50
],
"civilization_flow_plan": [
5425115,
50
],
"civilization_operator_build": [
151687,
50
],
"civilization_operator_solve": [
1609348,
2150
],
"enforce_capacity": [
871224,
200
],
"generation_products": [
542267,
100
],
"generation_withdrawal": [
1820057,
150
],
"generations": [
7751170,
50
],
"initialize": [
297786,
50
],
"newborn_batches": [
375307,
8322
],
"physical_amounts_build": [
1351719,
900
],
"production": [
1410303,
50
],
"trends": [
879262,
50
]
},
"repeat": 1,
"throughput": 0.479311225933843
},
{
"cycles": 50,
"cycles_per_second": 2.36172713483247,
"final_stellar_cohorts": 1300,
"game_years": "1000000",
"max_ms": 460.373,
"mean_ms": 423.41894,
"min_ms": 350.862,
"model": "cycle",
"p95_ms": 458.712,
"peak_stellar_cohorts": 1300,
"profile": {
"assign_homes": [
52297,
176
],
"civilization_flow_capacity": [
314752,
50
],
"civilization_flow_colonies": [
277416,
50
],
"civilization_flow_finish": [
442436,
50
],
"civilization_flow_ledger": [
3097867,
50
],
"civilization_flow_plan": [
5500302,
50
],
"civilization_operator_build": [
156156,
50
],
"civilization_operator_solve": [
1624350,
2150
],
"enforce_capacity": [
841074,
176
],
"generation_products": [
441260,
76
],
"generation_withdrawal": [
2058882,
126
],
"generations": [
7358962,
50
],
"initialize": [
304251,
50
],
"newborn_batches": [
211077,
5960
],
"physical_amounts_build": [
1293092,
826
],
"production": [
1725690,
50
],
"trends": [
899707,
50
]
},
"repeat": 1,
"throughput": 0.472345426966493
},
{
"cycles": 50,
"cycles_per_second": 2.34186004575995,
"final_stellar_cohorts": 1300,
"game_years": "1000000",
"max_ms": 465.408,
"mean_ms": 427.011,
"min_ms": 351.168,
"model": "cycle",
"p95_ms": 460.645,
"peak_stellar_cohorts": 1300,
"profile": {
"assign_homes": [
52872,
176
],
"civilization_flow_capacity": [
317075,
50
],
"civilization_flow_colonies": [
279484,
50
],
"civilization_flow_finish": [
446195,
50
],
"civilization_flow_ledger": [
3118109,
50
],
"civilization_flow_plan": [
5537625,
50
],
"civilization_operator_build": [
158082,
50
],
"civilization_operator_solve": [
1637405,
2150
],
"enforce_capacity": [
854481,
176
],
"generation_products": [
445328,
76
],
"generation_withdrawal": [
2078977,
126
],
"generations": [
7431634,
50
],
"initialize": [
308950,
50
],
"newborn_batches": [
213741,
5960
],
"physical_amounts_build": [
1308770,
826
],
"production": [
1744677,
50
],
"trends": [
903605,
50
]
},
"repeat": 2,
"throughput": 0.468372009151989
},
{
"cycles": 50,
"cycles_per_second": 2.31974771537327,
"final_stellar_cohorts": 130,
"game_years": "1000000",
"max_ms": 462.587,
"mean_ms": 431.08136,
"min_ms": 364.143,
"model": "legacy",
"p95_ms": 461.998,
"peak_stellar_cohorts": 132,
"profile": {
"assign_homes": [
60468,
200
],
"civilization_flow_capacity": [
318914,
50
],
"civilization_flow_colonies": [
281067,
50
],
"civilization_flow_finish": [
446947,
50
],
"civilization_flow_ledger": [
2979604,
50
],
"civilization_flow_plan": [
5570636,
50
],
"civilization_operator_build": [
158593,
50
],
"civilization_operator_solve": [
1643754,
2150
],
"enforce_capacity": [
904863,
200
],
"generation_products": [
564253,
100
],
"generation_withdrawal": [
1881469,
150
],
"generations": [
8019908,
50
],
"initialize": [
312899,
50
],
"newborn_batches": [
389499,
8322
],
"physical_amounts_build": [
1396769,
900
],
"production": [
1458932,
50
],
"trends": [
909402,
50
]
},
"repeat": 2,
"throughput": 0.463949543074653
}
],
"speed": 6
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,345 @@
{
"cycles_per_run": 50,
"delta_seconds": 0.2,
"profile_enabled": true,
"repeats": 2,
"runs": [
{
"cycles": 50,
"cycles_per_second": 2.3787548645537,
"final_stellar_cohorts": 130,
"game_years": "1000000",
"max_ms": 453.742,
"mean_ms": 420.388,
"min_ms": 354.113,
"model": "legacy",
"p95_ms": 452.604,
"peak_stellar_cohorts": 132,
"profile": {
"assign_homes": [
59021,
200
],
"civilization_flow_capacity": [
310616,
50
],
"civilization_flow_colonies": [
276485,
50
],
"civilization_flow_finish": [
436890,
50
],
"civilization_flow_ledger": [
2908982,
50
],
"civilization_flow_plan": [
5444724,
50
],
"civilization_operator_build": [
152980,
50
],
"civilization_operator_solve": [
1604917,
2150
],
"enforce_capacity": [
879602,
200
],
"generation_products": [
550010,
100
],
"generation_withdrawal": [
1834842,
150
],
"generations": [
7827667,
50
],
"initialize": [
300448,
50
],
"newborn_batches": [
379245,
8322
],
"physical_amounts_build": [
1360704,
900
],
"production": [
1417179,
50
],
"trends": [
884554,
50
]
},
"repeat": 1,
"throughput": 0.47575097291074
},
{
"cycles": 50,
"cycles_per_second": 2.3567861205283,
"final_stellar_cohorts": 125,
"game_years": "1000000",
"max_ms": 461.919,
"mean_ms": 424.30664,
"min_ms": 355.62,
"model": "cycle",
"p95_ms": 459.138,
"peak_stellar_cohorts": 127,
"profile": {
"assign_homes": [
59817,
200
],
"civilization_flow_capacity": [
314882,
50
],
"civilization_flow_colonies": [
279378,
50
],
"civilization_flow_finish": [
442443,
50
],
"civilization_flow_ledger": [
2950938,
50
],
"civilization_flow_plan": [
5516132,
50
],
"civilization_operator_build": [
156869,
50
],
"civilization_operator_solve": [
1618413,
2150
],
"enforce_capacity": [
892637,
200
],
"generation_products": [
529169,
100
],
"generation_withdrawal": [
1861386,
150
],
"generations": [
7833909,
50
],
"initialize": [
304443,
50
],
"newborn_batches": [
332349,
7522
],
"physical_amounts_build": [
1382887,
900
],
"production": [
1444907,
50
],
"trends": [
896615,
50
]
},
"repeat": 1,
"throughput": 0.471357224105661
},
{
"cycles": 50,
"cycles_per_second": 2.33373492243879,
"final_stellar_cohorts": 125,
"game_years": "1000000",
"max_ms": 471.891,
"mean_ms": 428.49768,
"min_ms": 363.562,
"model": "cycle",
"p95_ms": 458.377,
"peak_stellar_cohorts": 127,
"profile": {
"assign_homes": [
60419,
200
],
"civilization_flow_capacity": [
317546,
50
],
"civilization_flow_colonies": [
281187,
50
],
"civilization_flow_finish": [
447446,
50
],
"civilization_flow_ledger": [
2973320,
50
],
"civilization_flow_plan": [
5561963,
50
],
"civilization_operator_build": [
157327,
50
],
"civilization_operator_solve": [
1631869,
2150
],
"enforce_capacity": [
900410,
200
],
"generation_products": [
541714,
100
],
"generation_withdrawal": [
1875079,
150
],
"generations": [
7926735,
50
],
"initialize": [
307215,
50
],
"newborn_batches": [
336903,
7522
],
"physical_amounts_build": [
1400661,
900
],
"production": [
1457871,
50
],
"trends": [
908259,
50
]
},
"repeat": 2,
"throughput": 0.466746984487757
},
{
"cycles": 50,
"cycles_per_second": 2.31693373652923,
"final_stellar_cohorts": 130,
"game_years": "1000000",
"max_ms": 466.374,
"mean_ms": 431.60492,
"min_ms": 366.359,
"model": "legacy",
"p95_ms": 465.621,
"peak_stellar_cohorts": 132,
"profile": {
"assign_homes": [
60684,
200
],
"civilization_flow_capacity": [
318805,
50
],
"civilization_flow_colonies": [
282225,
50
],
"civilization_flow_finish": [
448335,
50
],
"civilization_flow_ledger": [
2980134,
50
],
"civilization_flow_plan": [
5579243,
50
],
"civilization_operator_build": [
157141,
50
],
"civilization_operator_solve": [
1638102,
2150
],
"enforce_capacity": [
904255,
200
],
"generation_products": [
565486,
100
],
"generation_withdrawal": [
1885470,
150
],
"generations": [
8034541,
50
],
"initialize": [
308996,
50
],
"newborn_batches": [
388637,
8322
],
"physical_amounts_build": [
1400258,
900
],
"production": [
1465783,
50
],
"trends": [
913581,
50
]
},
"repeat": 2,
"throughput": 0.463386747305846
}
],
"speed": 6
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,345 @@
{
"cycles_per_run": 40,
"delta_seconds": 0.2,
"profile_enabled": true,
"repeats": 2,
"runs": [
{
"cycles": 40,
"cycles_per_second": 1.6323701614814,
"final_stellar_cohorts": 105,
"game_years": "800000",
"max_ms": 628.888,
"mean_ms": 612.60615,
"min_ms": 564.108,
"model": "legacy",
"p95_ms": 624.987,
"peak_stellar_cohorts": 4560,
"profile": {
"assign_homes": [
48558,
160
],
"civilization_flow_capacity": [
263456,
40
],
"civilization_flow_colonies": [
2192836,
40
],
"civilization_flow_finish": [
401558,
40
],
"civilization_flow_ledger": [
4523753,
40
],
"civilization_flow_plan": [
4491368,
40
],
"civilization_operator_build": [
128185,
40
],
"civilization_operator_solve": [
1314272,
1720
],
"enforce_capacity": [
755412,
160
],
"generation_products": [
621550,
80
],
"generation_withdrawal": [
2524452,
120
],
"generations": [
8393123,
40
],
"initialize": [
293736,
40
],
"newborn_batches": [
1166060,
19424
],
"physical_amounts_build": [
1707597,
675
],
"production": [
2026863,
40
],
"trends": [
716666,
40
]
},
"repeat": 1,
"throughput": 0.32647403229628
},
{
"cycles": 40,
"cycles_per_second": 1.88577938012452,
"final_stellar_cohorts": 99,
"game_years": "800000",
"max_ms": 564.379,
"mean_ms": 530.284725,
"min_ms": 448.092,
"model": "cycle",
"p95_ms": 560.287,
"peak_stellar_cohorts": 607,
"profile": {
"assign_homes": [
39924,
132
],
"civilization_flow_capacity": [
265954,
40
],
"civilization_flow_colonies": [
2204837,
40
],
"civilization_flow_finish": [
404568,
40
],
"civilization_flow_ledger": [
4540902,
40
],
"civilization_flow_plan": [
4517593,
40
],
"civilization_operator_build": [
128322,
40
],
"civilization_operator_solve": [
1324328,
1720
],
"enforce_capacity": [
672871,
132
],
"generation_products": [
184761,
52
],
"generation_withdrawal": [
2150050,
92
],
"generations": [
5519639,
40
],
"initialize": [
295834,
40
],
"newborn_batches": [
118202,
3115
],
"physical_amounts_build": [
1594387,
612
],
"production": [
1526313,
40
],
"trends": [
723713,
40
]
},
"repeat": 1,
"throughput": 0.377155876024903
},
{
"cycles": 40,
"cycles_per_second": 1.87765994001252,
"final_stellar_cohorts": 99,
"game_years": "800000",
"max_ms": 566.428,
"mean_ms": 532.5778,
"min_ms": 456.191,
"model": "cycle",
"p95_ms": 565.345,
"peak_stellar_cohorts": 607,
"profile": {
"assign_homes": [
40238,
132
],
"civilization_flow_capacity": [
264957,
40
],
"civilization_flow_colonies": [
2218466,
40
],
"civilization_flow_finish": [
405624,
40
],
"civilization_flow_ledger": [
4564735,
40
],
"civilization_flow_plan": [
4543992,
40
],
"civilization_operator_build": [
127427,
40
],
"civilization_operator_solve": [
1338172,
1720
],
"enforce_capacity": [
672773,
132
],
"generation_products": [
185633,
52
],
"generation_withdrawal": [
2159985,
92
],
"generations": [
5547513,
40
],
"initialize": [
297516,
40
],
"newborn_batches": [
119187,
3115
],
"physical_amounts_build": [
1590461,
612
],
"production": [
1516716,
40
],
"trends": [
731042,
40
]
},
"repeat": 2,
"throughput": 0.375531988002504
},
{
"cycles": 40,
"cycles_per_second": 1.60095961519335,
"final_stellar_cohorts": 105,
"game_years": "800000",
"max_ms": 660.704,
"mean_ms": 624.625375,
"min_ms": 562.732,
"model": "legacy",
"p95_ms": 638.671,
"peak_stellar_cohorts": 4560,
"profile": {
"assign_homes": [
49183,
160
],
"civilization_flow_capacity": [
268901,
40
],
"civilization_flow_colonies": [
2229856,
40
],
"civilization_flow_finish": [
406135,
40
],
"civilization_flow_ledger": [
4623708,
40
],
"civilization_flow_plan": [
4578330,
40
],
"civilization_operator_build": [
130249,
40
],
"civilization_operator_solve": [
1340466,
1720
],
"enforce_capacity": [
765788,
160
],
"generation_products": [
635386,
80
],
"generation_withdrawal": [
2573324,
120
],
"generations": [
8560126,
40
],
"initialize": [
297396,
40
],
"newborn_batches": [
1191081,
19424
],
"physical_amounts_build": [
1738195,
675
],
"production": [
2069255,
40
],
"trends": [
735591,
40
]
},
"repeat": 2,
"throughput": 0.320191923038669
}
],
"speed": 6
}