[✔️]cocos2dx Tiledmap性能优化分析:layer data建议使用压缩格式gzip/zlib

简介: [✔️]cocos2dx Tiledmap性能优化分析:layer data建议使用压缩格式gzip/zlib

项目中有一个tmx文件,16M,加载这个tiledmap的时候,非常慢非常慢,在VisualStudio中通过性能探查器,进行了一波分析:


image.png


从饼状图中可以看到性能压力集中在文件IO上,追查到性能热点代码,是在解析csv数据:


unsigned char *buffer;
TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
tmxMapInfo->setStoringCharacters(false);
std::string currentString = tmxMapInfo->getCurrentString();
vector<string> gidTokens;
istringstream filestr(currentString);
string sRow;
// 因为地图是1000*1000,好在csv数据只有一行,所以这里只会执行一次
while(getline(filestr, sRow, '\n')) {
    string sGID;
    istringstream rowstr(sRow);
    // 但是因为csv是通过,分割,所以间接导致gidTokens会非常的大
    // 性能热点函数getline
    while (getline(rowstr, sGID, ',')) {
        gidTokens.push_back(sGID);
    }
}
// 32-bits per gid
buffer = (unsigned char*)malloc(gidTokens.size() * 4);
if (!buffer)
{
    CCLOG("cocos2d: TiledMap: CSV buffer not allocated.");
    return;
}
uint32_t* bufferPtr = reinterpret_cast<uint32_t*>(buffer);
// 这里是百万次以上循环,有一定的性能压力
for(auto gidToken : gidTokens) {
    auto tileGid = (uint32_t)strtoul(gidToken.c_str(), nullptr, 10);
    *bufferPtr = tileGid;
    bufferPtr++;
}
layer->_tiles = reinterpret_cast<uint32_t*>(buffer);
tmxMapInfo->setCurrentString("");


getline 是 C++ 标准库中的一个函数,其作用是从输入流中读取一行数据并存储到指定的字符串对象中。


std::istream& getline(std::istream& is, std::string& str, char delim);


其中,is 表示输入流对象,str 表示要存储读取结果的字符串对象,delim 表示分隔符(默认为换行符 \n)。当遇到分隔符时,getline 函数会停止读取并返回流对象。该函数会忽略分隔符本身,并将其从输入流缓冲区中删除。


getline 函数在输入流中读取一行数据时,需要逐个字符地读取,并检查每个字符是否为分隔符。由于字符的读取和检查是严格按照顺序进行的,因此这种方法会导致在处理大量数据时的性能问题。


不同encoding对比


encoding 第1次/第2次 size
csv 21812ms/21508ms 16.2M
base64 1670ms /610ms 42.1M
zlib 1183ms/105ms 471K
gzip 1189ms/130ms 472k


以上是测试超大tiledmap地图的加载性能报告,观察到一个非常有趣的现象,zlib的第1次加载和第2次加载耗费的时间差距有点大,初步猜测是因为加载纹理导致的


  • 第1次加载时,可以看到在addImage上花费了大量时间


image.png


  • 第2次加载时,在xml解析上花费了大量时间:


image.png


这个结果是符合我们的猜测,所以如果要加快tmx的创建,可以预加载tmx所使用的纹理图片。


结论


超大地图,尽量保存采用zlib、gzip的方式保存数据,会降低IO操作,提高tiledmap的性能,同时减少tmx文件大小,理论上这个问题在cocos creator中也会遇到。


目录
相关文章
|
3月前
gstreamer的I420转jpeg格式数据产生耗时
gstreamer的I420转jpeg格式数据产生耗时
|
编解码 编译器 C语言
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(一)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(一)
1914 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(一)
|
Web App开发 算法 前端开发
JavaWeb - 简单聊聊 GZIP 的压缩原理与日常应用
JavaWeb - 简单聊聊 GZIP 的压缩原理与日常应用
292 0
JavaWeb - 简单聊聊 GZIP 的压缩原理与日常应用
|
Linux C语言 Windows
Qt开发笔记之编码x264码流并封装mp4(二):windows平台x264添加mp4支持,gpac库的介绍与编译
Qt开发笔记之编码x264码流并封装mp4(二):windows平台x264添加mp4支持,gpac库的介绍与编译
Qt开发笔记之编码x264码流并封装mp4(二):windows平台x264添加mp4支持,gpac库的介绍与编译
|
存储 JSON 前端开发
Nginx网络压缩 CSS压缩 图片压缩 JSON压缩
使用Nginx作为web应用服务时,会代理如下常见文件:`js`、`css`、`JSON`、`图片`等,本文提供基于Nginx内置的压缩技术,提供网络请求响应速度的解决方案。 网络压缩的原理是消耗CPU资源,减少文件在公网传输的大小,提高响应速度。相比于CPU的计算资源,网络带宽通常较为昂贵,因此通过CPU资源置换网络带宽资源在实际生产中是可行的操作方案。
Nginx网络压缩 CSS压缩 图片压缩 JSON压缩
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(二)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(二)
242 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(二)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
467 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
|
编解码
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(五)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(五)
477 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(五)
|
内存技术
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(三)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(三)
283 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(三)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(四)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(四)
229 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(四)