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;

}


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

相关推荐
liulun27 分钟前
Windows注册鼠标钩子,获取用户选中的文本
c++·windows·qt
Aerkui30 分钟前
Python高阶函数-eval深入解析
开发语言·python
小诸葛的博客1 小时前
client-go如何监听自定义资源
开发语言·后端·golang
入 梦皆星河1 小时前
go原理刨析之channel
开发语言·后端·golang
Pandaconda1 小时前
【新人系列】Golang 入门(十二):指针和结构体 - 上
开发语言·后端·golang·go·指针·结构体·后端开发
6<71 小时前
【go】类型断言
开发语言·后端·golang
旷野本野2 小时前
【Java】Maven
java·开发语言·maven
我自纵横20232 小时前
事件处理程序
开发语言·前端·javascript·css·json·ecmascript
坊钰2 小时前
【MySQL 数据库】数据类型
java·开发语言·前端·数据库·学习·mysql·html
柃歌2 小时前
【LeetCode Solutions】LeetCode 136 ~ 140 题解
数据结构·算法·leetcode