Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9de5547
Add evolution dashboard window with dummy data
chrxh Jul 11, 2026
f5d7686
Fix dashboard layout and support multi-color lineages
chrxh Jul 12, 2026
831a672
Refine dashboard layout and use live customization colors
chrxh Jul 12, 2026
ef8e0f3
Make dashboard maximizable, brighten chip ring, rename color filter
chrxh Jul 12, 2026
4f90dee
Split accumulatedMutations into lineage and total counters
chrxh Jul 12, 2026
eef8db6
CR changes
chrxh Jul 12, 2026
0acb345
Remove obsolete migration pattern
chrxh Jul 12, 2026
852585a
Test fixed
chrxh Jul 12, 2026
5da002c
Feed Evolution Dashboard with real simulation data
chrxh Jul 12, 2026
4fc59dc
Remove unused per-lineage sumAccumulatedMutations, derive lineage col…
chrxh Jul 12, 2026
cd17865
Run evolution statistics at deterministic timesteps
chrxh Jul 12, 2026
c26dd23
Print actual angles on creature test failures
chrxh Jul 12, 2026
888df09
Minor changes
chrxh Jul 13, 2026
ac40125
Replace evolution/creature statistics with dedicated OverallStatistic…
chrxh Jul 13, 2026
766ad03
SimulationStatistics simplified, part 1
chrxh Jul 13, 2026
a2c87b3
SimulationStatistics simplified, part 2
chrxh Jul 13, 2026
85170b0
Refactor, part 1
chrxh Jul 13, 2026
f68d6a8
Refactor statistics
chrxh Jul 13, 2026
71d86b9
Merge lineage and overall statistics
chrxh Jul 13, 2026
ae4703f
DataPointCollection refactored
chrxh Jul 13, 2026
fd34e45
compile fixes
chrxh Jul 13, 2026
7752df0
Renamings
chrxh Jul 13, 2026
712f9e5
Remove plot scale switcher and drop lineage data from statistics history
chrxh Jul 14, 2026
0e95590
Show plots in time horizont
chrxh Jul 14, 2026
36704ac
Labels corrected
chrxh Jul 14, 2026
f4b2cc8
Fix bogus growth-rate spikes in Evolution Dashboard header cards
chrxh Jul 14, 2026
4a1fe2c
Use SessionId instead of timestep to detect simulation reload
chrxh Jul 14, 2026
e14fa99
Mouseover in plots + minor adaptions
chrxh Jul 14, 2026
3ec3dc9
Crash in timeline header fixed
chrxh Jul 15, 2026
71bc767
Fix for TimelineMode_LastSteps
chrxh Jul 15, 2026
26f0887
Improve dashboard visualization, part 1
chrxh Jul 15, 2026
46e3755
Improve dashboard visualization, part 2
chrxh Jul 15, 2026
f46796d
Improve dashboard visualization, part 3
chrxh Jul 15, 2026
a29189f
Minor adaptions
chrxh Jul 15, 2026
d47e0fe
Make columns in lineage table sortable
chrxh Jul 15, 2026
a178753
Colors and labels in spatial control window adapted
chrxh Jul 16, 2026
a2ad476
Separate sampling of lineage statistics
chrxh Jul 16, 2026
65ff4e6
Comment added
chrxh Jul 16, 2026
1d6b2c6
Improve dashboard visualization, part 4
chrxh Jul 16, 2026
38e0545
Fix tooltip in dashboard
chrxh Jul 16, 2026
bc22e14
Implement serialization of new statistics + minor dashboard corrections
chrxh Jul 16, 2026
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 source/Base/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Const
{
std::string const ProgramVersion = "5.0.0-alpha.21";
std::string const ProgramVersion = "5.0.0-alpha.22";
std::string const DiscordURL = "https://discord.gg/7bjyZdXXQ2";
std::string const AlienServerURL = "api.alien-project.org";

Expand Down
24 changes: 23 additions & 1 deletion source/Base/StringHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ std::string StringHelper::format(uint64_t n, char separator)
}

std::string StringHelper::format(float v, int fracPartDecimals)
{
return format(static_cast<double>(v), fracPartDecimals);
}

std::string StringHelper::format(double v, int fracPartDecimals)
{
std::string result;
if (v < 0) {
result = "-";
v = -v;
}
auto scale = static_cast<uint64_t>(std::llround(std::pow(10.0, fracPartDecimals)));
auto scaled = static_cast<uint64_t>(std::llround(static_cast<double>(v) * scale));
auto scaled = static_cast<uint64_t>(std::llround(v * scale));
result += format(scaled / scale);
if (fracPartDecimals > 0) {
result += ".";
Expand Down Expand Up @@ -105,6 +110,23 @@ std::string StringHelper::formatInHex(uint64_t value)
return ss.str();
}

std::string StringHelper::formatInThousands(double value)
{
if (value == 0.0) {
return "0";
}
auto result = format(value / 1000, 3);
if (result.find('.') != std::string::npos) {
while (result.back() == '0') {
result.pop_back();
}
if (result.back() == '.') {
result.pop_back();
}
}
return result + "K";
}

void StringHelper::copy(char* target, int maxSize, std::string const& source)
{
auto sourceSize = source.size();
Expand Down
2 changes: 2 additions & 0 deletions source/Base/StringHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ class StringHelper
public:
static std::string format(uint64_t n, char separator = ',');
static std::string format(float v, int decimalsAfterPoint);
static std::string format(double v, int decimalsAfterPoint);
static std::string format(std::chrono::seconds duration);
static std::string format(std::chrono::milliseconds duration);
static std::string format(std::chrono::system_clock::time_point const& timePoint);
static std::string formatInHex(uint64_t value);
static std::string formatInThousands(double value); //e.g. 12000 -> "12K", 1000000 -> "1,000K"

static void copy(char* target, int maxSize, std::string const& source);
static bool compare(char const* target, int maxSize, char const* source);
Expand Down
2 changes: 1 addition & 1 deletion source/Cli/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int main(int argc, char** argv)
app.add_option(
"-o",
outputFilename,
"Specifies the name of the output file for the simulation. The *.settings.json and *.statistics.csv file will also be saved.");
"Specifies the name of the output file for the simulation. The *.settings.json and *.statistics.bin file will also be saved.");
app.add_option("-t", timesteps, "The number of time steps to be calculated.");
app.add_flag(
"-p,--profile",
Expand Down
2 changes: 2 additions & 0 deletions source/EngineImpl/DescConverterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@ CreatureDesc DescConverterService::createCreatureDesc(TOs const& to, int creatur
result._lineageId = creatureTO.lineageId;
NumberGenerator::get().adaptMaxLineageId(creatureTO.lineageId);
result._accumulatedMutations = creatureTO.accumulatedMutations;
result._accumulatedMutationsInLineage = creatureTO.accumulatedMutationsInLineage;
result._headUpdateId = creatureTO.headUpdateId;

return result;
Expand Down Expand Up @@ -1258,6 +1259,7 @@ void DescConverterService::convertCreatureToTO(
creatureTO.mutationState = creatureDesc._mutationState;
creatureTO.lineageId = creatureDesc._lineageId;
creatureTO.accumulatedMutations = creatureDesc._accumulatedMutations;
creatureTO.accumulatedMutationsInLineage = creatureDesc._accumulatedMutationsInLineage;
creatureTO.genomeArrayIndex = genomeTOIndexById.at(creatureDesc._genomeId);
}

Expand Down
15 changes: 5 additions & 10 deletions source/EngineImpl/EngineWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,6 @@ Desc EngineWorker::getInspectedSimulationData(std::vector<uint64_t> objectsIds)
return DescConverterService::get().convertTOtoDescription(dataTO);
}

StatisticsRawData EngineWorker::getStatisticsRawData() const
{
return _simulationCudaFacade->getStatisticsRawData();
}

StatisticsHistory const& EngineWorker::getStatisticsHistory() const
{
return _simulationCudaFacade->getStatisticsHistory();
Expand All @@ -114,6 +109,11 @@ void EngineWorker::setStatisticsHistory(StatisticsHistoryData const& data)
_simulationCudaFacade->setStatisticsHistory(data);
}

StatisticsEntry EngineWorker::getStatisticsEntry() const
{
return _simulationCudaFacade->getStatisticsEntry();
}

void EngineWorker::addAndSelectSimulationData(Desc&& dataToUpdate)
{
EngineWorkerGuard access(this);
Expand Down Expand Up @@ -263,7 +263,6 @@ void EngineWorker::setCurrentTimestep(uint64_t value)
{
EngineWorkerGuard access(this);
_simulationCudaFacade->setCurrentTimestep(value);
resetTimeIntervalStatistics();
}

SimulationParameters EngineWorker::getSimulationParameters() const
Expand Down Expand Up @@ -538,10 +537,6 @@ void EngineWorker::testOnly_syncNumberGenerator()
NumberGenerator::get().adaptMaxIds(maxIds);
}

void EngineWorker::resetTimeIntervalStatistics()
{
_simulationCudaFacade->resetTimeIntervalStatistics();
}

void EngineWorker::processJobs()
{
Expand Down
5 changes: 2 additions & 3 deletions source/EngineImpl/EngineWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
#include <EngineInterface/CudaSettings.h>
#include <EngineInterface/Definitions.h>
#include <EngineInterface/GeometryBuffers.h>
#include <EngineInterface/StatisticsEntry.h>
#include <EngineInterface/PreviewDesc.h>
#include <EngineInterface/SelectionShallowData.h>
#include <EngineInterface/SettingsForSimulation.h>
#include <EngineInterface/ShallowUpdateSelectionData.h>
#include <EngineInterface/SimulationParameters.h>
#include <EngineInterface/SimulationParametersUpdateConfig.h>
#include <EngineInterface/StatisticsHistory.h>
#include <EngineInterface/StatisticsRawData.h>

#include <EngineKernels/Definitions.h>

Expand Down Expand Up @@ -55,9 +55,9 @@ class EngineWorker
Desc getSimulationData(IntVector2D const& rectUpperLeft, IntVector2D const& rectLowerRight);
Desc getSelectedSimulationData(bool includeClusters);
Desc getInspectedSimulationData(std::vector<uint64_t> objectsIds);
StatisticsRawData getStatisticsRawData() const;
StatisticsHistory const& getStatisticsHistory() const;
void setStatisticsHistory(StatisticsHistoryData const& data);
StatisticsEntry getStatisticsEntry() const;

void addAndSelectSimulationData(Desc&& dataToUpdate);
void setSimulationData(Desc const& dataToUpdate);
Expand Down Expand Up @@ -132,7 +132,6 @@ class EngineWorker
void testOnly_syncNumberGenerator();

private:
void resetTimeIntervalStatistics();
void processJobs();

void syncSimulationWithRenderingIfDesired();
Expand Down
49 changes: 24 additions & 25 deletions source/EngineImpl/SimulationCudaFacade.cu
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <EngineKernels/GarbageCollectorKernels.cuh>
#include <EngineKernels/GeometryKernels.cuh>
#include <EngineKernels/Map.cuh>
#include <EngineKernels/MaxAgeBalancer.cuh>
#include <EngineKernels/SelectionResult.cuh>
#include <EngineKernels/SimulationData.cuh>
#include <EngineKernels/SimulationStatistics.cuh>
Expand All @@ -50,7 +49,10 @@

namespace
{
std::chrono::milliseconds const StatisticsUpdate(30);
// The evolution statistics kernels are heavy; running them at wall-clock-throttled (i.e. run-to-run varying)
// timesteps perturbs the simulation's GPU execution timing and makes simulation runs non-reproducible.
// They are therefore scheduled at deterministic timestep intervals instead.
auto constexpr EvolutionStatisticsUpdateInterval = 10;
ArraySizesForGpuEntities const PreviewCapacityGpu{10000, 10000, 10000000};
ArraySizesForTOs const PreviewCapacityTO{1000, 1000, 1000, 10000, 10000, 10000, 10000000};
}
Expand All @@ -76,7 +78,6 @@ _SimulationCudaFacade::_SimulationCudaFacade(uint64_t timestep, SettingsForSimul
_cudaTOProvider = std::make_shared<_CudaTOProvider>();
_cudaSimulationStatistics = std::make_shared<SimulationStatistics>();
_cudaPreviewStatistics = std::make_shared<SimulationStatistics>();
_maxAgeBalancer = std::make_shared<_MaxAgeBalancer>();

_simulationTimestep = timestep;
_cudaSimulationData->init({_settings.worldSizeX, _settings.worldSizeY}, timestep);
Expand Down Expand Up @@ -112,6 +113,7 @@ _SimulationCudaFacade::~_SimulationCudaFacade() noexcept
_cudaSimulationData->free();
_cudaPreviewData->free();
_cudaSimulationStatistics->free();
_cudaPreviewStatistics->free();
_cudaSelectionResult->free();

SimulationKernelsService::get().shutdown();
Expand Down Expand Up @@ -430,41 +432,42 @@ ArraySizesForTOs _SimulationCudaFacade::estimateCapacityNeededForTO() const
return DataAccessKernelsService::get().estimateCapacityNeededForTO(_settings.cudaSettings, getSimulationDataPtrCopy());
}

StatisticsRawData _SimulationCudaFacade::getStatisticsRawData()
void _SimulationCudaFacade::updateStatistics()
{
std::lock_guard lock(_mutexForStatistics);
if (_statisticsData) {
return *_statisticsData;
} else {
return StatisticsRawData();
}
updateEvolutionStatistics();
}

void _SimulationCudaFacade::updateStatistics()
void _SimulationCudaFacade::updateEvolutionStatistics()
{
StatisticsKernelsService::get().updateStatistics(_settings.cudaSettings, getSimulationDataPtrCopy(), *_cudaSimulationStatistics);
syncAndCheck();

auto statisticsEntry = _cudaSimulationStatistics->getStatisticsEntry();
{
std::lock_guard lock(_mutexForStatistics);
_statisticsData = _cudaSimulationStatistics->getStatistics();
_statisticsEntry = statisticsEntry;
}
StatisticsService::get().addDataPoint(_statisticsHistory, _statisticsData->timeline, getCurrentTimestep());
StatisticsService::get().addDataPoint(_statisticsHistory, statisticsEntry, getCurrentTimestep());
}

StatisticsHistory const& _SimulationCudaFacade::getStatisticsHistory() const
{
return _statisticsHistory;
}

void _SimulationCudaFacade::setStatisticsHistory(StatisticsHistoryData const& data)
StatisticsEntry _SimulationCudaFacade::getStatisticsEntry()
{
StatisticsService::get().rewriteHistory(_statisticsHistory, data, getCurrentTimestep());
std::lock_guard lock(_mutexForStatistics);
if (_statisticsEntry) {
return *_statisticsEntry;
} else {
return StatisticsEntry();
}
}

void _SimulationCudaFacade::resetTimeIntervalStatistics()
void _SimulationCudaFacade::setStatisticsHistory(StatisticsHistoryData const& data)
{
_cudaSimulationStatistics->resetAccumulatedStatistics();
StatisticsService::get().rewriteHistory(_statisticsHistory, data, getCurrentTimestep());
}

uint64_t _SimulationCudaFacade::getCurrentTimestep() const
Expand Down Expand Up @@ -582,7 +585,7 @@ TOs _SimulationCudaFacade::getPreviewData()
void _SimulationCudaFacade::testOnly_mutate(uint64_t objectId)
{
checkAndProcessSimulationParameterChanges();
TestKernelsService::get().testOnly_mutate(_settings.cudaSettings, getSimulationDataPtrCopy(), objectId);
TestKernelsService::get().testOnly_mutate(_settings.cudaSettings, getSimulationDataPtrCopy(), *_cudaSimulationStatistics, objectId);
syncAndCheck();

resizeArraysIfNecessary();
Expand Down Expand Up @@ -811,19 +814,15 @@ void _SimulationCudaFacade::calcTimestepsInternal(uint64_t timesteps, bool force
resizeArraysIfNecessary();
}

auto statistics = getStatisticsRawData();
{
std::lock_guard lock(_mutexForSimulationParameters);
if (SimulationParametersUpdateService::get().updateSimulationParametersAfterTimestep(
_settings, _maxAgeBalancer, simulationData, getCurrentTimestep(), statistics)) {
if (SimulationParametersUpdateService::get().updateSimulationParametersAfterTimestep(_settings, simulationData, getCurrentTimestep())) {
CHECK_FOR_DEVICE_ERRORS(
cudaMemcpyToSymbol(cudaSimulationParameters, &_settings.simulationParameters, sizeof(SimulationParameters), 0, cudaMemcpyHostToDevice));
}
}
auto now = std::chrono::steady_clock::now();
if (!_lastStatisticsUpdateTime || now - *_lastStatisticsUpdateTime > StatisticsUpdate) {
_lastStatisticsUpdateTime = now;
updateStatistics();
if (getCurrentTimestep() % EvolutionStatisticsUpdateInterval == 0) {
updateEvolutionStatistics();
}
}
if (forceUpdateStatistics) {
Expand Down
11 changes: 5 additions & 6 deletions source/EngineImpl/SimulationCudaFacade.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#include <EngineInterface/ArraySizesForTOs.h>
#include <EngineInterface/Definitions.h>
#include <EngineInterface/GeometryBuffers.h>
#include <EngineInterface/StatisticsEntry.h>
#include <EngineInterface/SelectionShallowData.h>
#include <EngineInterface/SettingsForSimulation.h>
#include <EngineInterface/ShallowUpdateSelectionData.h>
#include <EngineInterface/SimulationParametersUpdateConfig.h>
#include <EngineInterface/StatisticsHistory.h>
#include <EngineInterface/StatisticsRawData.h>

#include <EngineKernels/Definitions.cuh>
#include <EngineKernels/TOs.cuh>
Expand Down Expand Up @@ -83,12 +83,11 @@ public:

ArraySizesForTOs estimateCapacityNeededForTO() const;

StatisticsRawData getStatisticsRawData();
void updateStatistics();
StatisticsHistory const& getStatisticsHistory() const;
void setStatisticsHistory(StatisticsHistoryData const& data);
StatisticsEntry getStatisticsEntry();

void resetTimeIntervalStatistics();
uint64_t getCurrentTimestep() const;
void setCurrentTimestep(uint64_t timestep);

Expand Down Expand Up @@ -121,6 +120,8 @@ public:
private:
void initCuda();

void updateEvolutionStatistics();

void syncAndCheck();
void copyDataTOtoGpu(TOs const& cudaTO, TOs const& to);
void copyDataTOtoHost(TOs const& to, TOs const& cudaTO);
Expand Down Expand Up @@ -153,10 +154,8 @@ private:
TOProvider _collectionTOProvider;

mutable std::mutex _mutexForStatistics;
std::optional<std::chrono::steady_clock::time_point> _lastStatisticsUpdateTime;
std::optional<StatisticsRawData> _statisticsData;
StatisticsHistory _statisticsHistory;
std::optional<StatisticsEntry> _statisticsEntry;
std::shared_ptr<SimulationStatistics> _cudaSimulationStatistics;
std::shared_ptr<SimulationStatistics> _cudaPreviewStatistics;
MaxAgeBalancer _maxAgeBalancer;
};
10 changes: 5 additions & 5 deletions source/EngineImpl/SimulationFacadeImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,11 +320,6 @@ IntVector2D _SimulationFacadeImpl::getWorldSize() const
return _worldSize;
}

StatisticsRawData _SimulationFacadeImpl::getStatisticsRawData() const
{
return _worker.getStatisticsRawData();
}

StatisticsHistory const& _SimulationFacadeImpl::getStatisticsHistory() const
{
return _worker.getStatisticsHistory();
Expand All @@ -335,6 +330,11 @@ void _SimulationFacadeImpl::setStatisticsHistory(StatisticsHistoryData const& da
_worker.setStatisticsHistory(data);
}

StatisticsEntry _SimulationFacadeImpl::getStatisticsEntry() const
{
return _worker.getStatisticsEntry();
}

std::optional<int> _SimulationFacadeImpl::getTpsRestriction() const
{
auto result = _worker.getTpsRestriction();
Expand Down
2 changes: 1 addition & 1 deletion source/EngineImpl/SimulationFacadeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ class _SimulationFacadeImpl : public _SimulationFacade
bool updateSelectionIfNecessary() override;

IntVector2D getWorldSize() const override;
StatisticsRawData getStatisticsRawData() const override;
StatisticsHistory const& getStatisticsHistory() const override;
void setStatisticsHistory(StatisticsHistoryData const& data) override;
StatisticsEntry getStatisticsEntry() const override;

std::optional<int> getTpsRestriction() const override;
void setTpsRestriction(std::optional<int> const& value) override;
Expand Down
Loading
Loading