【编程之旅】关于传输剩余时间估算那些事儿

关于输剩余时间进行估算,我开始思考起了这个有趣的话题,在信息数据程指数级暴增的今天,传输剩余时间这个词我们似乎已经司空见惯,当我们随意复制粘贴,上传下载一个哪怕是一堆文件时,其实我们在干的事情也就是数据传输,而在这个过程中产生的一个很有趣的现象就是,人们总是很迫切地需要知道传输的进度或者是结果,如果在这一过程中一切变得不可知,人们的内心就会变得焦躁或者是迷茫,接下来要发生的事情就是或许这样一件正在进行着的事情将会被毫无理由地抛弃,因为你让使用者感到迷茫和无奈了,所以我们可以认为,这是我们让用户“呆”了。

对于我们让用户呆了的这个事情,我想我们是不愿意看到的,因此我们有必要在这里边温柔地做一些“防呆设计”,也就是较为准确地去估算传输的剩余时间,然后通过一定的方式反馈给使用者,关于“防呆设计”这个理念,纵观这些年许多我们熟知的软件,就会发现其实它早已深入其中,就比如这些年一些安装程序更趋于一键安装(或者有直观体现当前进度的提示),一些安全防护软件或者系统优化增强软件更趋于一键安全防护或者一键清理优化,还有提示使用者如何操作的便利贴式提醒标识等等,都是“防呆设计”理念的直观体现。由于许多的软件设计慢慢地考虑到了用户感受和用户体验,设计更趋于人性化,这样设计出来的软件其实是更温暖更贴心的,我们不妨说是“得人心者得天下”。

说了这么多,我们不妨回到之前思考的问题,如何对传输剩余时间进行合理准确地估算,,从而使用户得到一个满意的时间反馈,说到这我们都会知道影响传输剩余时间挂钩的直接影响要素是传输总量,剩余传输量,传输速度,由于传输速度是一个变化较为不稳定的因素,我们就要合理地对它进行一定的均衡,使得传输剩余时间的显示是较为稳定的,这样一来我们就取 一定时间内的传输变化量除以该时间间隔 得到的值作为这段时间内的传输速度,再用这段时间内的平均传输速度作为之后的传输速度预测,以此来得到剩余的传输时间,但是值得我们注意的是取时间间隔均衡后的传输速度依然有可能会有较为明显地波动,因此我们还需要做一些剩余时间预测条件限制,也就是当我们预测到的剩余时间与上一阶段预测到的剩余时间相比是在某一系数范围内,我们就保持上一阶段预测到的剩余时间继续递减,反之我们就使用新预测到的剩余时间作为当前剩余时间反馈给用户,这就是我对传输剩余时间估算的一个基本思想。

我将上述基本思想写成了一个 时间助手CTimerHelper类,代码如下:

#pragma once/*************************************************************************– CTimeHelper Designed by SEVEN –E-mail: 304407324@qq.com**************************************************************************/ #ifndef __CTIMEHELPER_H__#define __CTIMEHELPER_H__class CTimeHelper{public:CTimeHelper(__int64 nTotal = 0, float fRatio = 1, DWORD dwValue = 5000){SIGMA = 0.872; //传输剩余时间合理变化范围系数Init(nTotal, fRatio, dwValue);}~CTimeHelper(void){}public:void Init(__int64 nTotal = 0, float fRatio = 1, DWORD dwValue = 5000)//初识化 nTotal:传输数据总量(字节) fRatio:实际时间比率 dwValue:估算间隔(毫秒){SetTotalValue(nTotal);SetTimeRatio(fRatio);SetInterval(dwValue);dwSecTime = 0;dwIntTime = 0;dwSpeTime = 0;dwRemainTime = 0;nSpeOldValue = 0;nNowValue = 0;nOldValue = 0;}void SetTimeRatio(float fRatio) //设置实际时间比率{dwTimeRatio = (DWORD)(fRatio*1000);}void SetInterval(DWORD dwValue) //设置估算间隔(毫秒){dwInterval = dwValue;}void SetTotalValue(__int64 nValue) //设置总的传输量(字节){nTotalValue = nValue;}void Update(__int64 nCurrentValue) //更新内部时间 nCurrentValue:当前传输的总量(字节){dwSecTime += dwTimeRatio;dwIntTime += dwTimeRatio;dwSpeTime += dwTimeRatio;nNowValue = nCurrentValue;}DWORD GetRemainTime() //获取剩余传输时间(秒){if(nNowValue <= nOldValue){return -1;}if(nNowValue == nTotalValue){return 0;}if(dwSecTime>=1000) //当时间间隔大于1000毫秒计算新的剩余时间{if(dwRemainTime<(DWORD)-1) dwRemainTime -= dwSecTime/1000;dwSecTime = 0;}if(dwIntTime>=dwInterval) //当时间间隔大于设定的时间间隔则对剩余时间进行一次新的估算{DWORD dwNewTime = (DWORD)((nTotalValue-nNowValue)/((nNowValue – nOldValue)/(dwIntTime*1.0/1000)));if(dwRemainTime*(10*(1-SIGMA))>dwNewTime || dwRemainTime*(10*SIGMA)<dwNewTime) dwRemainTime = dwNewTime + 1;nOldValue = nNowValue;dwIntTime = 0;}return dwRemainTime;}float GetAverageSpeed() //获取时间间隔内平均传输速度(字节/秒){float fSpeed = ((nNowValue – nSpeOldValue)/(dwSpeTime*1.0/1000));nSpeOldValue = nNowValue;dwSpeTime = 0;return fSpeed;}private:float SIGMA;DWORD dwTimeRatio;DWORD dwSecTime;DWORD dwIntTime;DWORD dwSpeTime;DWORD dwInterval;DWORD dwRemainTime;__int64 nSpeOldValue;__int64 nTotalValue;__int64 nNowValue;__int64 nOldValue;};#endif

PS. 由于使用了与系统无关的代码设计,因此该代码可以较为方便地移植到其它的平台上使用,关于传输剩余时间的估算,上述代码还有值得修改优化的地方,您可以根据需要进行相应地修改,请保留原作者的相关注释。

关于上述代码的使用,请见下例代码:

#include <windows.h>void main(){srand(unsigned int(time(NULL)));DWORD dwSize = (rand()%1024+1)*(rand()%1024+1)*1024; //随机得到一个要传输数据的总大小DWORD dwNowSize = 0;DWORD dwSpeed = 0;DWORD dwTime = 0;DWORD dwRemTime = -1;DWORD dwOldSize = 0;CTimeHelper hpTime(dwSize, (float)100/1000); //初始化时间助手类, 总大小为dwSize, 时间比率为 100ms/1000ms(1s)while(dwNowSize<dwSize){dwSpeed = (rand()%1024)*1024; //随机生成传输速度(字节/100毫秒)dwNowSize += dwSpeed; //得出当前接收到的数据大小if(dwNowSize>dwSize) dwNowSize = dwSize;UINT16 uProg = (UINT16)((dwNowSize*1.0/dwSize)*100); //计算传输进度hpTime.Update(dwNowSize); //更新当前传数据输大小if(dwTime>1){if(dwTime%10 == 0) //每1000毫取计算一次平均传输速度{hpTime.GetAverageSpeed(); //获取时间间隔内的平均传输速度}hpTime.GetRemainTime(); //获取剩余传输时间}Sleep(100); //模拟间隔100毫秒dwTime++; //累加间隔次数}}

欢迎评论和转载,转载请注明文章出处,我对此表示最真诚的敬意!

旅行是一种病,当你把身边的人都传染了,

【编程之旅】关于传输剩余时间估算那些事儿

相关文章:

你感兴趣的文章:

标签云: