135 lines
3.7 KiB
C++
135 lines
3.7 KiB
C++
#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;
|
|
}
|
|
};
|
|
}
|