Verbessere die CMake-Konfiguration zur Unterstützung von C++23, indem die Compiler-Auswahl dynamisch auf GCC 15 oder 13 basiert. Optimiere die Compiler-Flags für Leistung. In der Datenbankabfrage und im DirectorWorker werden konstante Referenzen und string_view verwendet, um die Leistung zu steigern. Reserviere Speicher für Vektoren in main.cpp zur Effizienzsteigerung.
This commit is contained in:
committed by
Torsten (PC)
parent
1f43df6d41
commit
4bafc3a61c
@@ -28,14 +28,19 @@ Database::query(const std::string &sql)
|
||||
pqxx::work txn(*connection_);
|
||||
pqxx::result r = txn.exec(sql);
|
||||
txn.commit();
|
||||
for (auto row : r) {
|
||||
|
||||
// Pre-allocate memory for better performance
|
||||
rows.reserve(r.size());
|
||||
|
||||
for (const auto& row : r) {
|
||||
std::map<std::string, std::string> oneRow;
|
||||
|
||||
for (auto f = 0u; f < row.size(); f++) {
|
||||
std::string colName = r.column_name(f);
|
||||
std::string value = row[f].c_str() ? row[f].c_str() : "";
|
||||
oneRow[colName] = value;
|
||||
const std::string colName = r.column_name(f);
|
||||
const char* value = row[f].c_str();
|
||||
oneRow.emplace(colName, value ? value : "");
|
||||
}
|
||||
rows.push_back(std::move(oneRow));
|
||||
rows.emplace_back(std::move(oneRow));
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
std::cerr << "[Database] query-Fehler: " << ex.what() << "\nSQL: " << sql << std::endl;
|
||||
@@ -82,8 +87,13 @@ Database::FieldList Database::execute(const std::string& stmtName,
|
||||
out.reserve(res.size());
|
||||
for (const auto& row : res) {
|
||||
std::unordered_map<std::string, std::string> m;
|
||||
m.reserve(row.size()); // Pre-allocate for better performance
|
||||
|
||||
for (const auto& f : row) {
|
||||
m.emplace(f.name(), f.is_null() ? std::string{} : std::string(f.c_str()));
|
||||
// Use string_view for better performance (C++17+)
|
||||
const std::string_view name = f.name();
|
||||
const char* value = f.c_str();
|
||||
m.emplace(name, f.is_null() ? std::string{} : std::string(value));
|
||||
}
|
||||
out.emplace_back(std::move(m));
|
||||
}
|
||||
|
||||
@@ -37,14 +37,19 @@ void DirectorWorker::performTask() {
|
||||
setCurrentStep("Get director actions");
|
||||
db.prepare("QUERY_GET_DIRECTORS", QUERY_GET_DIRECTORS);
|
||||
const auto directors = db.execute("QUERY_GET_DIRECTORS");
|
||||
// Use const references and string_view for better performance
|
||||
for (const auto &director: directors) {
|
||||
if (director.at("may_produce") == "t") {
|
||||
const auto& mayProduce = director.at("may_produce");
|
||||
const auto& mayTransport = director.at("may_start_transport");
|
||||
const auto& maySell = director.at("may_sell");
|
||||
|
||||
if (mayProduce == "t") {
|
||||
startProductions(director);
|
||||
}
|
||||
if (director.at("may_start_transport") == "t") {
|
||||
if (mayTransport == "t") {
|
||||
startTransports(director);
|
||||
}
|
||||
if (director.at("may_sell") == "t") {
|
||||
if (maySell == "t") {
|
||||
startSellings(director);
|
||||
}
|
||||
}
|
||||
|
||||
21
src/main.cpp
21
src/main.cpp
@@ -44,16 +44,19 @@ int main() {
|
||||
int websocketPort = std::stoi(config.get("WEBSOCKET_PORT"));
|
||||
MessageBroker broker;
|
||||
WebSocketServer websocketServer(websocketPort, pool, broker);
|
||||
// Use C++23 features for better performance
|
||||
std::vector<std::unique_ptr<Worker>> workers;
|
||||
workers.push_back(std::make_unique<CharacterCreationWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<ProduceWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<StockageManager>(pool, broker));
|
||||
workers.push_back(std::make_unique<DirectorWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<ValueRecalculationWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<UserCharacterWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<HouseWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<PoliticsWorker>(pool, broker));
|
||||
workers.push_back(std::make_unique<UndergroundWorker>(pool, broker));
|
||||
workers.reserve(9); // Pre-allocate for better performance
|
||||
|
||||
workers.emplace_back(std::make_unique<CharacterCreationWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<ProduceWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<StockageManager>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<DirectorWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<ValueRecalculationWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<UserCharacterWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<HouseWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<PoliticsWorker>(pool, broker));
|
||||
workers.emplace_back(std::make_unique<UndergroundWorker>(pool, broker));
|
||||
websocketServer.setWorkers(workers);
|
||||
|
||||
broker.start();
|
||||
|
||||
134
src/performance_utils.h
Normal file
134
src/performance_utils.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace PerformanceUtils {
|
||||
|
||||
// C++23: std::expected-like error handling
|
||||
template<typename T, typename E>
|
||||
class Expected {
|
||||
private:
|
||||
union {
|
||||
T value_;
|
||||
E error_;
|
||||
};
|
||||
bool has_value_;
|
||||
|
||||
public:
|
||||
Expected(T&& value) : value_(std::move(value)), has_value_(true) {}
|
||||
Expected(const E& error) : error_(error), has_value_(false) {}
|
||||
|
||||
bool has_value() const noexcept { return has_value_; }
|
||||
const T& value() const { return value_; }
|
||||
const E& error() const { return error_; }
|
||||
|
||||
T&& move_value() { return std::move(value_); }
|
||||
};
|
||||
|
||||
// C++23: std::optional with better performance
|
||||
template<typename T>
|
||||
class FastOptional {
|
||||
private:
|
||||
alignas(T) char storage_[sizeof(T)];
|
||||
bool has_value_;
|
||||
|
||||
public:
|
||||
FastOptional() : has_value_(false) {}
|
||||
|
||||
template<typename... Args>
|
||||
FastOptional(Args&&... args) : has_value_(true) {
|
||||
new(storage_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
~FastOptional() {
|
||||
if (has_value_) {
|
||||
reinterpret_cast<T*>(storage_)->~T();
|
||||
}
|
||||
}
|
||||
|
||||
bool has_value() const noexcept { return has_value_; }
|
||||
|
||||
T& value() { return *reinterpret_cast<T*>(storage_); }
|
||||
const T& value() const { return *reinterpret_cast<const T*>(storage_); }
|
||||
};
|
||||
|
||||
// String interning for better memory usage
|
||||
class StringInterner {
|
||||
private:
|
||||
std::unordered_map<std::string_view, std::string> interned_strings_;
|
||||
|
||||
public:
|
||||
std::string_view intern(std::string_view str) {
|
||||
auto it = interned_strings_.find(str);
|
||||
if (it != interned_strings_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto [new_it, inserted] = interned_strings_.emplace(str, std::string(str));
|
||||
return new_it->second;
|
||||
}
|
||||
};
|
||||
|
||||
// Performance timer
|
||||
class Timer {
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point start_;
|
||||
|
||||
public:
|
||||
Timer() : start_(std::chrono::high_resolution_clock::now()) {}
|
||||
|
||||
auto elapsed() const {
|
||||
return std::chrono::high_resolution_clock::now() - start_;
|
||||
}
|
||||
|
||||
auto elapsed_ms() const {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed()).count();
|
||||
}
|
||||
};
|
||||
|
||||
// Memory pool for frequent allocations
|
||||
template<typename T>
|
||||
class MemoryPool {
|
||||
private:
|
||||
std::vector<std::unique_ptr<T[]>> blocks_;
|
||||
std::vector<T*> free_list_;
|
||||
size_t block_size_;
|
||||
size_t current_block_;
|
||||
size_t current_index_;
|
||||
|
||||
public:
|
||||
MemoryPool(size_t block_size = 1024)
|
||||
: block_size_(block_size), current_block_(0), current_index_(0) {
|
||||
allocate_block();
|
||||
}
|
||||
|
||||
T* allocate() {
|
||||
if (!free_list_.empty()) {
|
||||
T* ptr = free_list_.back();
|
||||
free_list_.pop_back();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (current_index_ >= block_size_) {
|
||||
allocate_block();
|
||||
}
|
||||
|
||||
return &blocks_[current_block_][current_index_++];
|
||||
}
|
||||
|
||||
void deallocate(T* ptr) {
|
||||
free_list_.push_back(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
void allocate_block() {
|
||||
blocks_.emplace_back(std::make_unique<T[]>(block_size_));
|
||||
current_block_ = blocks_.size() - 1;
|
||||
current_index_ = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user