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 小时前
二进制与十进制互转的方法
c++
远瞻。3 小时前
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
论文阅读·算法
shykevin5 小时前
python开发Streamable HTTP MCP应用
开发语言·网络·python·网络协议·http
我不是程序猿儿5 小时前
【C#】 lock 关键字
java·开发语言·c#
漫路在线5 小时前
JS逆向-某易云音乐下载器
开发语言·javascript·爬虫·python
先做个垃圾出来………6 小时前
哈夫曼树(Huffman Tree)
数据结构·算法
小辉懂编程6 小时前
C语言:51单片机实现数码管依次循环显示【1~F】课堂练习
c语言·开发语言·51单片机
醍醐三叶7 小时前
C++类与对象--2 对象的初始化和清理
开发语言·c++
phoenix@Capricornus7 小时前
反向传播算法——矩阵形式递推公式——ReLU传递函数
算法·机器学习·矩阵
Magnum Lehar8 小时前
3d游戏引擎EngineTest的系统实现3
java·开发语言·游戏引擎