C++享元结构文档样式应用

class BaseStyle {

public:

enum ProperyID{

PROP_FONT_SIZE,

PROP_PARAGRAPH_INDENT

};

// virtual bool createLocalStyle();

virtual void setProperty(int type, void* val) = 0;

};

using BaseStyleSp = std::shared_ptr<BaseStyle>;

class ShareData {

public:

ShareData(float fontSize): m_fontSize(fontSize){}

size_t hash() const { return std::hash<float>()(m_fontSize);}

public:

float m_fontSize;

};

using ShareDataSp = std::shared_ptr<ShareData>;

using ShareDataWp = std::weak_ptr<ShareData>;

class ShareDocData {

public:

float paragraphIndent;

};

using ShareDocDataSp = std::shared_ptr<ShareDocData>;

using ShareDocDataWp = std::weak_ptr<ShareDocData>;

class ShareDataLRU {

public:

ShareDataLRU(): m_hitCount(0) {}

int m_hitCount;

};

#include <cassert>

#include <unordered_map>

class ShareDataMergeManger{

class CharHash {

public:

std::size_t operator()(const ShareDataSp &sharedPtr) const {

if(!sharedPtr)

return 0;

return sharedPtr->hash();

}

};

class CharCmp {

public:

bool operator()(const ShareDataSp &selfPtr, const ShareDataSp &otherPtr) const {

if(selfPtr == otherPtr)

return true;

if(!selfPtr)

return false;

if(!otherPtr)

return false;

return selfPtr->hash() == otherPtr->hash();

}

};

public:

ShareDataSp allocCharData(const ShareDataSp charData) {

//if(manger.size() > 20000)

// clearUnUsed();

return std::make_shared<ShareData>(*charData);

}

ShareDataSp addCacheCharData(const ShareDataSp& data) {

auto ret = manger.emplace(data, ShareDataLRU());

if(ret.second) { //新添加成功

return ret.first->first;

} else { //已存在,返回旧的

++ret.first->second.m_hitCount;

return ret.first->first;

}

}

ShareDataSp findCharData(const ShareDataSp& data) {

auto shareData = manger.find(data);

if(shareData == manger.end()) {

return nullptr;

}

else {

++shareData->second.m_hitCount; //查找次数+1,热度上升

return shareData->first;

}

}

void removeCharData(const ShareDataSp& data) {

manger.erase(data);

}

// 内存超过指定长度,自动清除未使用的区域

void clearUnUsed() {

for (auto iter = manger.begin(); iter != manger.end(); ) {

if(1 == iter->first.use_count())

iter = manger.erase(iter);

else

++iter;

}

}

public:

std::unordered_map<ShareDataSp, ShareDataLRU, CharHash, CharCmp> manger;

};

using ShareDataMergeMangerSp = std::shared_ptr<ShareDataMergeManger>;

using ShareDataMergeMangerWp = std::weak_ptr<ShareDataMergeManger>;

class LocalStyle : public BaseStyle {

public:

LocalStyle(ShareDataSp charData, ShareDocDataSp docData, const ShareDataMergeMangerSp& shareDataMergeManger):m_charData(shareDataMergeManger->addCacheCharData(charData)), m_docData(docData), m_shareDataMergeManger(shareDataMergeManger){

}

// ~LocalStyle() {

// if(m_shareDataMergeManger.expired()) {

// return;

// }

// auto allocManger = m_shareDataMergeManger.lock();

// if(!allocManger)

// return;

// if(2 == m_charData.use_count())

// allocManger->removeCharData(m_charData);

// }

void setFontSize(float size) {

m_charData->m_fontSize = size;

}

float fontSize() const {

return m_charData->m_fontSize;

}

private:

void setProperty(int type, void* val) override {

if(PROP_FONT_SIZE == type) {

auto newVal = *(float*)val;

auto useCout = m_charData.use_count();

if(fontSize() == newVal)

return;

if(useCout == 2 || useCout == 1) { //自己独占或与内存管理类共享数据

removeCache(); //更新hash,需先移除

} else {

detach(); //创建副本

}

setFontSize(newVal);// 改值

merge(); //缓存更新

}

}

void removeCache() {

auto allocManger = shareMemoryManger();

if(!allocManger)

return;

allocManger->removeCharData(m_charData); //先删除,key值hash不跟随联动,暂无法解决性能损耗

}

void detach() {

auto allocManger = shareMemoryManger();

if(!allocManger)

return;

m_charData = allocManger->allocCharData(m_charData);

}

bool merge() {

auto allocManger = shareMemoryManger();

if(!allocManger)

return false;

auto cacheCharData = allocManger->addCacheCharData(m_charData); //新数据加入

if(cacheCharData != m_charData) {

m_charData = cacheCharData;

return true;

} else {

return false;

}

}

private:

inline ShareDataMergeMangerSp shareMemoryManger() const {

if(m_shareDataMergeManger.expired())

return nullptr;

return m_shareDataMergeManger.lock();

}

public:

ShareDataSp m_charData;

ShareDocDataSp m_docData;

ShareDataMergeMangerWp m_shareDataMergeManger;

};

using LocalStyleSp = std::shared_ptr<LocalStyle>;

class Style {

public:

std::string hyperLink;

int styleId;

ShareDataSp charData;

};

class DocStyle {

public:

ShareDocDataSp docData;

int align;

};

int main(int argc, char** argv)

{

auto shareDataManger = std::make_shared<ShareDataMergeManger>();

auto shareCharData = std::make_shared<ShareData>(0);

auto shareDocData = std::make_shared<ShareDocData>();

BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);

float size = 1; //数据存在浮点精度,无法准确去重,暂时不优化

localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);

size = 2;

localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);

size = 0;

localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);

return 0;

}

perf-10万样式-同时修改1万个-5-6ms(堆内存频繁分配,合并,释放,尝试转栈)

#include <iostream>

#include <chrono>

int main(int argc, char** argv)

{

auto shareDataManger = std::make_shared<ShareDataMergeManger>();

size_t count = 100000;

std::vector<BaseStyleSp> vctStyles;

vctStyles.reserve(count);

for (int i = 0; i < count; ++i) {

auto shareCharData = std::make_shared<ShareCharData>(i);

auto shareDocData = std::make_shared<ShareDocData>();

BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);

vctStyles.push_back(localStyle);

}

// 获取当前时间点

auto start = std::chrono::high_resolution_clock::now();

float size = 50000;

auto shareCharData = std::make_shared<ShareCharData>(size);

auto shareDocData = std::make_shared<ShareDocData>();

BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);

for (int i = 40000; i < 50000; ++i) {

size = i + 1;

vctStyles.at(i)->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);

}

// 获取代码执行后的时间点

auto end = std::chrono::high_resolution_clock::now();

// 计算代码执行的时间差

auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

// 输出运行时间

std::cout << "代码执行时间: " << duration << " 微秒" << std::endl;

return 0;

}


创作不易,小小的支持一下吧!

相关推荐
沫璃染墨1 分钟前
《Qt从零入门系列(十四):QThread多线程详解——从线程创建到客户端阻塞处理》
开发语言·c++·笔记·qt·ui·交互·线程
草莓熊Lotso3 分钟前
【C++ 基于微服务的即时通讯系统】Elasticsearch 从安装到 C++ 客户端二次封装全落地
linux·网络·数据库·c++·elasticsearch·微服务
Samson Bruce3 分钟前
【数学之美】
线性代数·算法·概率论
hixiong12314 分钟前
C# 使用 ZXingCpp.Angle 进行条码、二维码识别
开发语言·c#·扫码
CHPCWWHSU15 分钟前
FreeCAD 源码解读:从 Property 到 Command,看一套 CAD 内核的完整闭环
c++·cad
云和数据.ChenGuang16 分钟前
AI 工程师相关就业岗位(细分,偏工程落地,由底层到上层)
服务器·开发语言·人工智能·python
爱读书的小胖26 分钟前
Codewars:Last digit of a large number(C)解题分析
c语言·开发语言·r语言
代钦塔拉33 分钟前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
Mister Leon34 分钟前
Nvidia Orin AGX实战之从量化到蒸馏:在 Orin 上落地的大模型压缩实战
人工智能·算法·机器学习
aqiu11111136 分钟前
蓝桥杯真题复盘:Fibonacci 数列与黄金分割(C++ 算法详解)
c++·算法·蓝桥杯