头疼的VC.NET的效率问题

本文讨论了在2008环境下,通过优化内存映射文件的使用和避免某些封装导致的性能损耗,成功将S-57数据解析至SENC数据结构的时间从9秒降至200毫秒,实现了显著的性能提升。重点分析了代码层面的改进策略,包括减少资源消耗和提高文件读取效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几天用2008编写了一个文件的读取过程。文件格式是S-57标准的海图数据。借用了网上现成的Parse57中的文件格式分解读取模块。然后将内容读取后记录到自己的SENC数据结构中。代码并不是很麻烦,关键是,常常屏幕中同时需要显示几幅海图,才能将屏幕填满;而且除了读取SENC海图数据外,还需要进行海图要素的显示,以及海图上层功能的显示。因此,数据处理的速度是个很重要的问题。如果速度慢,那么功能再强大,也是无法接受的。

将S-57数据解析后记录到内存的SENC数据结构的部分,在2008的debug下需要9秒,不过这个到不重要,因为海图系统运行的时候,只是从SENC中读取数据,不会直接读取S-57数据文件。形成的SENC数据,我测试了一个S-57文件大小为3.6M的形成的SENC数据,大约需要650毫秒,这还是我反复简化的结果,其中去掉了CString的使用,都是用指针和内存拷贝函数来实现文件的读取,而且用了内存映射文件。这样做,大大损失了我的数据结构的灵活性和封装性,丢失了对S-57数据协议中一部分协议的支持,而且扩展性也降低了,万一以后S-57数据的某个我目前忽略的项突然起作用了,那么可能会产生很大的影响。不过没办法,如果不这么做,那么连现在的系统都无从谈起。可650毫秒显然还是难以接受的结果。

那么, 我又在release下编译运行,经过测试,速度也在400毫秒左右,虽然有所提高,但如果需要同时读取三幅海图,那么就需要1秒左右,这个效率还是很困难。

踌躇之间,我把该模块转到VC6下运行。这个过程,我可以说是没有调整任何代码,因为模块已经封装好,外部调用函数也是一致的。测试发现,将S-57数据读取到内存SENC数据结构中,只需要4.5秒(debug下),SENC文件的读取速度与2008倒是差不多,600毫秒左右。我又用release编译运行,结果SENC文件的读取速度只需要200毫秒左右。这个速度就好多了。

为什么差距这么大呢?哪位有经验不吝赐教啊。如何才能提高2008下的速度呢?

以下是部分代码,还请大家给点建议:

//SENC读取的接口函数 BOOL CS57DataSet::LoadSENC(const CString &sSENCFilePathName) { //创建内存映射文件 HANDLE hFile = CreateFile(sSENCFilePathName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { AfxMessageBox("SENC文件打开失败。"); return NULL; } long dwFileLen = GetFileSize(hFile,NULL); if(dwFileLen < 1 || dwFileLen >= 0xFFFFFFFF) { CloseHandle(hFile); AfxMessageBox("获取SENC文件大小失败。"); return FALSE; } HANDLE hMapObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMapObject == NULL) { CloseHandle(hFile); AfxMessageBox("内存映射文件创建失败。"); return FALSE; } //得到文件起始指针 LPVOID pBase = MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0); BYTE *pBuf = (BYTE*)pBase; ////////////// //DSID m_pS57DSID = new CS57DSID; m_pS57DSID->LoadSENC(pBuf,nVer); //DSSI m_pS57DSSI = new CS57DSSI; m_pS57DSSI->LoadSENC(pBuf,nVer); //DSPM m_pS57DSPM = new CS57DSPM; m_pS57DSPM->LoadSENC(pBuf,nVer); //读取特征记录 BYTE chField[4]; memcpy(chField,pBuf,4); pBuf += 4; while(memcmp(chField,"DLLS",4) != 0) { if(memcmp(chField,"SOBJ",4) == 0) { long nSize = *((long*)pBuf); pBuf += 4; // int nIdx = 0; while(nIdx < nSize) { CS57Spatial *pS57Spatial = new CS57Spatial; pS57Spatial->LoadSENC(pBuf,nVer); if(pS57Spatial->m_S57VRID.RCNM == 110) m_mapS57SpatialVI.SetAt(pS57Spatial->m_S57VRID.RCID,pS57Spatial); else if(pS57Spatial->m_S57VRID.RCNM == 120) m_mapS57SpatialVC.SetAt(pS57Spatial->m_S57VRID.RCID,pS57Spatial); else if(pS57Spatial->m_S57VRID.RCNM == 130) m_mapS57SpatialVE.SetAt(pS57Spatial->m_S57VRID.RCID,pS57Spatial); nIdx++; } } ...... =================================================== //特征对象从SENC中读取其数据 void CS57Spatial::LoadSENC(BYTE *&pBuf,int nVer) { int i=0; //VRID LoadBYTE(m_S57VRID.RCNM,pBuf); LoadLong(m_S57VRID.RCID,pBuf); LoadShort(m_S57VRID.RVER,pBuf); LoadBYTE(m_S57VRID.RUIN,pBuf); //ATTV BYTE nATTVSize; LoadBYTE(nATTVSize,pBuf); // for(i=0; i<nATTVSize; i++) { S57_ATTR S57ATTV; LoadShort(S57ATTV.ATTL,pBuf); LoadBYTE(S57ATTV.nATVL,pBuf); if(S57ATTV.nATVL > 0) { S57ATTV.pATVL = new BYTE[S57ATTV.nATVL]; LoadBYTEs(S57ATTV.pATVL,S57ATTV.nATVL,pBuf); } m_arS57ATTV.Add(S57ATTV); } ...... =================================================== //以下按数据类型从文件中读取数据 //这些函数即使不封装,直接在上一个函数中写语句,效率也没有什么提高 void CS57DataStu::LoadBYTE(BYTE &nVal,BYTE *&pBuf) { nVal = *pBuf; pBuf++; } void CS57DataStu::LoadShort(short &nVal,BYTE *&pBuf) { nVal = *((short*)pBuf); pBuf += 2; } void CS57DataStu::LoadLong(long &nVal,BYTE *&pBuf) { nVal = *((long*)pBuf); pBuf += 4; } void CS57DataStu::LoadBYTEs(BYTE *pVal,BYTE nLen,BYTE *&pBuf) { memcpy(pVal,pBuf,nLen); pBuf += nLen; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值