C++ 下载各地的速度跳跃
我有一个使用curl从ftp下载文件的小程序。在CURLOPT_PROGRESSFUNCTION中传递的函数中,我计算下载速度,问题是下载速度到处跳跃,在2mbps的互联网连接上从512kbps跳到8mbps。我无法确定这里出了什么问题 编辑:我已更改代码以平均读数,curl下载的问题是您无法预测何时将调用TraceProgress函数,它可以在不到1秒的时间内再次调用,因此程序等待5次迭代以记录读数,并在平均前获取6次此类读数,我还考虑了自上次读取以来经过的时间(秒),因为我们不能保证TraceProgress函数将以相等的间隔调用 如果现在看起来好些了,请告诉我 代码如下:C++ 下载各地的速度跳跃,c++,winapi,libcurl,C++,Winapi,Libcurl,我有一个使用curl从ftp下载文件的小程序。在CURLOPT_PROGRESSFUNCTION中传递的函数中,我计算下载速度,问题是下载速度到处跳跃,在2mbps的互联网连接上从512kbps跳到8mbps。我无法确定这里出了什么问题 编辑:我已更改代码以平均读数,curl下载的问题是您无法预测何时将调用TraceProgress函数,它可以在不到1秒的时间内再次调用,因此程序等待5次迭代以记录读数,并在平均前获取6次此类读数,我还考虑了自上次读取以来经过的时间(秒),因为我们不能保证Trac
int minorCounter = 0;
int majorCounter = 0;
int minorCycle = 4;
int majorCycle = 5;
double blockDL[6];
double blockTime[6];
int TraceProgress( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
{
if ( minorCounter == minorCycle )
{
blockDL[majorCounter] = dlnow - oldDownloadNow;
myTimer.Tick();
blockTime[majorCounter] = myTimer.GetDurationInSecs();
minorCounter = 0;
if ( majorCounter == majorCycle )
{
double dl = 0;
double tm = 0;
for ( int i = 0; i < majorCycle ; i++ )
{
dl += blockDL[i];
tm += blockTime[i];
}
dl = dl/(majorCycle+1);
tm = tm/(majorCycle+1);
double currentDownloadSpeed = dl / tm;
/* download speed - divide by 1024 to get speed in kilobytes instead of bytes */
double idownloadSpeed = currentDownloadSpeed / 1024;
string post;
if ( idownloadSpeed > 1024 )
{
idownloadSpeed = idownloadSpeed / 1024;
post = " MB/s";
}
else
{
post = " KB/s";
}
string downloadSpeed = DoubleToString( idownloadSpeed );
size_t x = downloadSpeed.find( "." );
downloadSpeed.erase( x+2 );
downSize = "Download Speed: " + downloadSpeed + post;
SendMessage( hDownloadSpeedSTATIC, WM_SETTEXT, (WPARAM)0, (LPARAM)downSize.c_str() );
majorCounter = 0;
}
else
{
majorCounter++;
}
oldDownloadNow = dlnow;
myTimer.Start();
}
else
{
minorCounter++;
}
return 0;
}
int minorCounter=0;
int majorCounter=0;
int最小循环=4;
int majorCycle=5;
双blockDL[6];
双阻塞时间[6];
int TraceProgress(void*clientp,双dltotal,双dlnow,双ultotal,双ulnow)
{
if(minorCounter==minorCycle)
{
blockDL[majorCounter]=dlnow-oldDownloadNow;
myTimer.Tick();
blockTime[MajoCounter]=myTimer.GetDurationInSecs();
最小计数=0;
如果(主循环==主循环)
{
双dl=0;
双tm=0;
for(int i=0;i1024)
{
idownloadSpeed=idownloadSpeed/1024;
post=“MB/s”;
}
其他的
{
post=“KB/s”;
}
字符串下载速度=DoubleToString(idownloadSpeed);
size\u t x=下载速度。查找(“.”);
下载速度。擦除(x+2);
downSize=“下载速度:”+downloadSpeed+post;
SendMessage(hDownloadSpeedSTATIC,WM_SETTEXT,(WPARAM)0,(LPARAM)downSize.c_str());
majorCounter=0;
}
其他的
{
MajoCounter++;
}
oldDownloadNow=dlnow;
myTimer.Start();
}
其他的
{
minorCounter++;
}
返回0;
}
您需要使用采样窗口和指数衰减或其他合理的方法
如果每30分钟就有一辆汽车从装配线上下来,而你只取一个样品,那么可怕的事情就会发生。例如,如果你在一辆车下线后取样,20分钟后再取样,你会在20分钟内看到零辆车,即每小时零辆车。如果你在一辆车下线前取样,31分钟后再取样,你会在31分钟内看到两辆车,每小时3.9辆
这里有一个简单的算法:
要了解此算法的工作原理,请假设计数为常量。这意味着加到计数上的金额必须等于减去的金额。这意味着计数必须是每秒添加的字节数的8倍,使其成为每秒接收的位数。可能测量时间太短。我猜,过去30秒左右的移动平均线会平滑变化,仍然显示合理的当前数据。@JerryCoffin是的,我真傻,没有正确理解场景,我已经更改了上面的代码,你怎么看?当然看起来更接近了。是的,鉴于调用回调的速度参差不齐,很难让事情顺利进行。@JerryCoffin有什么关于如何改进它的意见吗?我已经更改了上面的代码,你能看一看,让我知道它是否更好吗?如果你不能确保函数以相等的间隔被调用,您可以只跟踪上次执行
count-=(count/8)的时间代码>。如果过了不到一秒钟,不要这样做。如果超过两秒钟,则重复两次或更多次。