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;

}


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

相关推荐
wclass-zhengge9 分钟前
数据结构篇(绪论)
java·数据结构·算法
何事驚慌10 分钟前
2024/10/5 数据结构打卡
java·数据结构·算法
结衣结衣.10 分钟前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
学习使我变快乐12 分钟前
C++:静态成员
开发语言·c++
TJKFYY12 分钟前
Java.数据结构.HashSet
java·开发语言·数据结构
心怀花木14 分钟前
【C++】多态
c++·多态
风清扬_jd18 分钟前
Chromium 添加书签功能浅析c++
c++·chrome
吃椰子不吐壳18 分钟前
c++类与对象二
c++
杰哥在此21 分钟前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
小白学大数据22 分钟前
User-Agent在WebMagic爬虫中的重要性
开发语言·爬虫·http