Last active
February 25, 2026 22:48
-
-
Save xthexder/4466e4625cd70059ae632f9ca4e9e32e to your computer and use it in GitHub Desktop.
Tecs benchmark of TPS to compare with SpacetimeDB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "utils.hh" | |
| #include <Tecs.hh> | |
| #include <c_abi/Tecs.hh> | |
| #include <chrono> | |
| #include <cstring> | |
| #include <future> | |
| #include <iomanip> | |
| #include <random> | |
| #include <thread> | |
| #ifdef _WIN32 | |
| #include <windows.h> | |
| #endif | |
| #define ENTITY_COUNT 100000 | |
| #define THREAD_COUNT 50 | |
| #define INITIAL_BALANCE 1000000 | |
| using namespace testing; | |
| namespace benchmark { | |
| std::atomic_bool running; | |
| typedef int64_t Balance; | |
| using ECS = Tecs::ECS<Balance>; | |
| static ECS ecs; | |
| std::atomic_size_t transactionCount; | |
| void transferJob([[maybe_unused]] MultiTimer *workerTimer) { | |
| std::random_device rd; | |
| std::mt19937 gen(rd()); | |
| gen.seed((uint32_t)std::hash<std::thread::id>{}(std::this_thread::get_id())); | |
| std::uniform_int_distribution<> randEntity(0, ENTITY_COUNT - 1); | |
| std::uniform_int_distribution<> randAmount(1, INITIAL_BALANCE); | |
| while (running) { | |
| Timer t(*workerTimer); | |
| Tecs::Entity source = randEntity(gen); | |
| Tecs::Entity dest = randEntity(gen); | |
| uint32_t amount = randAmount(gen); | |
| { | |
| auto lock = ecs.StartTransaction<Tecs::Write<Balance>>(); | |
| int64_t &sourceBalance = source.Get<Balance>(lock); | |
| if (sourceBalance >= amount) { | |
| int64_t &destBalance = dest.Get<Balance>(lock); | |
| sourceBalance -= amount; | |
| destBalance += amount; | |
| } | |
| } | |
| transactionCount++; | |
| } | |
| } | |
| #if THREAD_COUNT > 0 | |
| void workerThread() { | |
| MultiTimer workerTimers[THREAD_COUNT]; | |
| std::future<void> workers[THREAD_COUNT]; | |
| for (size_t i = 0; i < THREAD_COUNT; i++) { | |
| workerTimers[i].Reset("ScriptWorker " + std::to_string(i) + " Run"); | |
| } | |
| for (size_t i = 0; i < THREAD_COUNT; i++) { | |
| workers[i] = std::async(&transferJob, &workerTimers[i]); | |
| } | |
| for (auto &worker : workers) { | |
| worker.wait(); | |
| } | |
| } | |
| #endif | |
| int runBenchmark() { | |
| #if __cpp_lib_atomic_wait | |
| std::cout << "Compiled with C++20 atomic.wait()" << std::endl; | |
| #endif | |
| #ifdef _WIN32 | |
| // Increase thread scheduler from default of 15ms | |
| timeBeginPeriod(1); | |
| std::shared_ptr<UINT> timePeriodReset(new UINT(1), [](UINT *period) { | |
| timeEndPeriod(*period); | |
| delete period; | |
| }); | |
| #endif | |
| { | |
| MultiTimer timer1("Create entities Start"); | |
| MultiTimer timer2("Create entities Run"); | |
| MultiTimer timer3("Create entities Commit"); | |
| Timer t(timer1); | |
| auto writeLock = ecs.StartTransaction<Tecs::AddRemove>(); | |
| t = timer2; | |
| for (size_t i = 0; i < ENTITY_COUNT; i++) { | |
| Tecs::Entity e = writeLock.NewEntity(); | |
| e.Set<Balance>(writeLock, INITIAL_BALANCE); | |
| } | |
| t = timer3; | |
| } | |
| { | |
| auto readLock = ecs.StartTransaction<>(); | |
| std::cout << "Running with " << readLock.Entities().size() << " Entities and " << THREAD_COUNT << " threads" | |
| << std::endl; | |
| } | |
| { | |
| Timer t("Run threads"); | |
| running = true; | |
| #if THREAD_COUNT > 0 | |
| auto worker = std::async(&workerThread); | |
| #endif | |
| std::this_thread::sleep_for(std::chrono::seconds(100)); | |
| running = false; | |
| #if THREAD_COUNT > 0 | |
| worker.wait(); | |
| #endif | |
| } | |
| std::cout << "Completed " << transactionCount << " transactions in 100 seconds (" << (transactionCount / 100.0f) | |
| << " tps)" << std::endl; | |
| std::cout << "Benchmark complete" << std::endl; | |
| return 0; | |
| } | |
| } // namespace benchmark | |
| int main(int /* argc */, char ** /* argv */) { | |
| return benchmark::runBenchmark(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment