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;

}


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

相关推荐
小白学大数据几秒前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
海绵波波1071 分钟前
Webserver(4.9)本地套接字的通信
c++
Python大数据分析@3 分钟前
python操作CSV和excel,如何来做?
开发语言·python·excel
@小博的博客7 分钟前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
上海_彭彭29 分钟前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
无尽的大道31 分钟前
Java反射原理及其性能优化
jvm·性能优化
3345543237 分钟前
element动态表头合并表格
开发语言·javascript·ecmascript
沈询-阿里41 分钟前
java-智能识别车牌号_基于spring ai和开源国产大模型_qwen vl
java·开发语言
南宫生1 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
残月只会敲键盘1 小时前
面相小白的php反序列化漏洞原理剖析
开发语言·php