#include <boost/pool/object_pool.hpp>
#include <boost/pool/singleton_pool.hpp>
#include <spdlog/spdlog.h>
#include <thread>
struct TimeCost {
TimeCost(const std::string& _title, const std::string& describe = "", bool defaultP = true) :
title(_title), start(std::chrono::steady_clock::now()), end(start) {
}
TimeCost(const TimeCost& rhs) : title(rhs.title), start(rhs.start), end(rhs.end) {};
~TimeCost() {
print();
}
void print(const std::string& _text = "") {
if (end == start) {
end = std::chrono::steady_clock::now();
}
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
SPDLOG_INFO("TimeCost:{},cost:{}ms", title, duration.count());
}
std::string title;
std::chrono::steady_clock::time_point start{ std::chrono::steady_clock::time_point::min() };
std::chrono::steady_clock::time_point end { std::chrono::steady_clock::time_point::min() };
};
template <typename T>
class Benchmark {
public:
template <typename... Args>
inline static T* construct(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
inline static void destroy(T* ptr) {
delete ptr;
}
};
template <typename T, std::size_t N = 2000>
class ObjectFactory
{
private:
struct SharedDeleter
{
ObjectFactory<T>* m_pFact;
SharedDeleter(ObjectFactory<T>* fact) : m_pFact(fact) {}
inline void operator()(T* p) const
{
m_pFact->destroy(p);
}
};
static thread_local boost::object_pool<T>* m_tlsPool;
SharedDeleter m_Deleter;
public:
ObjectFactory() : m_Deleter(this)
{
SPDLOG_INFO("ObjectFactory init");
}
virtual ~ObjectFactory()
{
if (m_tlsPool)
delete m_tlsPool;
}
template<typename TType = T, typename... TArgs>
inline static TType* construct(TArgs&&... mArgs)
{
return m_tlsPool->construct(mArgs...);
}
inline static void destroy(T* mObj)
{
if (!mObj)
return;
m_tlsPool->destroy(mObj);
}
template<typename TType = T, typename... TArgs>
inline std::shared_ptr<TType> make_shared(TArgs&&... mArgs)
{
return std::shared_ptr<TType>(this->construct(mArgs...), m_Deleter);
}
};
template<typename T, std::size_t N>
/*static*/thread_local boost::object_pool<T>* ObjectFactory<T, N>::m_tlsPool = new boost::object_pool<T>();
template <typename T, std::size_t N = 2000>
class ObjectFactoryThreadSafe
{
typedef boost::singleton_pool<T, N> SigPool;
private:
struct SharedDeleter
{
SharedDeleter() {}
inline void operator()(T* p) const
{
SigPool::destroy(p);
}
};
inline static SharedDeleter m_Deleter{};
public:
ObjectFactoryThreadSafe() = default;
virtual ~ObjectFactoryThreadSafe() {}
template<typename TType = T, typename... TArgs>
inline static TType* construct(TArgs&&... mArgs)
{
auto ptr = static_cast<TType*>(SigPool::malloc());
new(ptr) TType(mArgs...);
return ptr;
}
inline static void destroy(T* mObj)
{
if (!mObj)
return;
mObj->~T();
SigPool::free(mObj);
}
template<typename TType = T, typename... TArgs>
inline std::shared_ptr<TType> make_shared(TArgs&&... mArgs)
{
return std::shared_ptr<TType>(this->construct(mArgs...), m_Deleter);
}
};
struct MyClass {
std::string name;
int id;
double score{ 0 };
double age { 0 };
double weight { 0 };
MyClass(const std::string& name, int id) : id(id), name(name) {
//std::cout << "MyClass constructed: " << id << ", " << name << std::endl;
}
};
void threadlocal(std::size_t N = 100000) {
TimeCost t("threadlocal");
using TestPool = ObjectFactory<MyClass>;
for (auto i = 0; i < N; i++) {
auto m = TestPool::construct("threadlocal", i);
m->weight = i * 100;
m->age = i * 10;
m->score = i * 0.1;
TestPool::destroy(m);
}
}
void benchmark(std::size_t N = 100000) {
TimeCost t("benchmark");
using TestPool = Benchmark<MyClass>;
for (auto i = 0; i < N; i++) {
auto m = TestPool::construct("benchmark", i);
m->weight = i * 100;
m->age = i * 10;
m->score = i * 0.1;
TestPool::destroy(m);
}
}
void threadsafe(std::size_t N = 100000) {
TimeCost t("threadsafe");
using TestPool = ObjectFactoryThreadSafe<MyClass>;
for (auto i = 0; i < N; i++) {
auto m = TestPool::construct("threadsafe", i);
m->weight = i * 100;
m->age = i * 10;
m->score = i * 0.1;
TestPool::destroy(m);
}
}
int main() {
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e][%P:%5t][%^%l%$][%s:%#]%v");
spdlog::flush_on(spdlog::level::info);
spdlog::flush_every(std::chrono::seconds(5));
auto numThreads = 5;
auto callTimes = 1000000;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; ++i) {
threads.push_back(std::thread([callTimes]() { benchmark(callTimes); }));
}
for (int i = 0; i < numThreads; ++i) {
threads.push_back(std::thread([callTimes]() { threadlocal(callTimes); }));
}
for (int i = 0; i < numThreads; ++i) {
threads.push_back(std::thread([callTimes]() { threadsafe(callTimes); }));
}
for (auto& t : threads) {
t.join();
}
auto case1 = getchar();
return 0;
}
--
FROM 14.154.27.*