0

curlを使用してftpからファイルをダウンロードする小さなプログラムがあります。そして、CURLOPT_PROGRESSFUNCTIONで渡された関数で、ダウンロード速度を知るために計算を行います。問題は、ダウンロード速度が2mbpsインターネット接続で512kbpsから8mbpsに至る所でジャンプすることです。そして、私はここで何が悪いのかを判断できませんでした。

編集:読み取り値を平均化するようにコードを変更しました。curlダウンロードの問題は、TraceProgress関数がいつ呼び出されるかを予測できないことです。1秒以内に再度呼び出すことができるため、プログラムは5回の反復を待機します。 TraceProgress関数が等間隔で呼び出されることを保証できないため、読み取り値を下げ、平均化する前にそのような読み取り値を6つ取得します。また、最後の読み取り値が取得されてから経過した時間(秒)も考慮しました。

今は良く見えるかどうか教えてください。

コードは次のとおりです。

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;
}
4

1 に答える 1

2

サンプリング ウィンドウと指数関数的減衰またはその他の適切なものを使用する必要があります。

車が 30 分ごとに組み立てラインから出てきて、たった 1 つのサンプルを採取しただけでも、恐ろしいことが起こる可能性があります。たとえば、車が線路を離れた直後にサンプリングし、20 分後に再度サンプリングすると、20 分間で車が 0 台、つまり 1 時間あたりの車が 0 台の割合で表示されます。車が線路を離れる直前にサンプリングし、31 分後にもう一度サンプリングすると、31 分間に 2 台の車が表示され、1 時間あたり 3.9 台の速度になります。

以下は単純なアルゴリズムの 1 つです。

  1. 単一のカウントと単一の平均速度を維持します。どちらもゼロから始めてください。

  2. 毎秒更新します。

  3. 1 秒ごとに、まず前の 1 秒間に受信したバイト数をカウントに追加します。

  4. カウントを追加した後、カウントからカウントの 1/8 を減算します。count -= (count/8);

  5. 平滑化された平均速度 (ビット /秒) を現在のカウントに更新します。bits_per_sec = count;.

このアルゴリズムが機能する理由を確認するには、カウントが一定であると仮定します。つまり、カウントに加算される量は、減算される量と等しくなければなりません。つまり、カウントは毎秒追加されるバイト数の 8 倍である必要があり、1 秒あたりの受信ビット数になります。

于 2012-12-21T06:34:41.653 に答える