Рассчитать проблему скорости передачи загрузки - PullRequest
4 голосов
/ 09 ноября 2009

Я реализовал калькулятор скорости передачи файлов, чтобы отображать кБ / с для процесса загрузки, происходящего в моем приложении, однако с помощью следующего кода мне кажется, что я получаю «пачки» в моих показаниях в килобайтах сразу после того, как файл начинает загрузить.

Это часть моего потокового кода, которая передает файл в 1024 чанках на сервер, используя httpWebRequest:

using (Stream httpWebRequestStream = httpWebRequest.GetRequestStream())
{
    if (request.DataStream != null)
    {
        byte[] buffer = new byte[1024];
        int bytesRead = 0;

        Debug.WriteLine("File Start");
        var duration = new Stopwatch();
        duration.Start();
        while (true)
        {
            bytesRead = request.DataStream.Read(buffer, 0, buffer.Length);
            if (bytesRead == 0)
                break;

            httpWebRequestStream.Write(buffer, 0, bytesRead);
            totalBytes += bytesRead;


            double bytesPerSecond = 0;
            if (duration.Elapsed.TotalSeconds > 0)
                bytesPerSecond = (totalBytes / duration.Elapsed.TotalSeconds);

            Debug.WriteLine(((long)bytesPerSecond).FormatAsFileSize());
        }
        duration.Stop();
        Debug.WriteLine("File End");
        request.DataStream.Close();
    }
}

Теперь выходной журнал процесса загрузки и связанные показания в килобайтах выглядят следующим образом: (Вы заметите, что новый файл начинается и оканчивается на «Начало файла» и «Конец файла»)

File Start
5.19 MB
7.89 MB
9.35 MB
11.12 MB
12.2 MB
13.13 MB
13.84 MB
14.42 MB
41.97 kB
37.44 kB
41.17 kB
37.68 kB
40.81 kB
40.21 kB
33.8 kB
34.68 kB
33.34 kB
35.3 kB
33.92 kB
35.7 kB
34.36 kB
35.99 kB
34.7 kB
34.85 kB
File End

File Start
11.32 MB
14.7 MB
15.98 MB
17.82 MB
18.02 MB
18.88 MB
18.93 MB
19.44 MB
40.76 kB
36.53 kB
40.17 kB
36.99 kB
40.07 kB
37.27 kB
39.92 kB
37.44 kB
39.77 kB
36.49 kB
34.81 kB
36.63 kB
35.15 kB
36.82 kB
35.51 kB
37.04 kB
35.71 kB
37.13 kB
34.66 kB
33.6 kB
34.8 kB
33.96 kB
35.09 kB
34.1 kB
35.17 kB
34.34 kB
35.35 kB
34.28 kB
File End

Моя проблема, как вы заметите, «всплеск», о котором я говорю, начинается в начале каждого нового файла, достигает максимума в МБ, а затем выравнивается должным образом. это нормально для загрузки, чтобы лопнуть, как это? Моя скорость загрузки, как правило, не будет превышать 40 к / с здесь, поэтому она не может быть правильной.

Это реальная проблема, когда я беру в среднем последние 5–10 секунд для отображения на экране, это действительно выдает результаты, дающие результат около ~ 3 МБ / с!

Есть идеи, если я подхожу к этой проблеме наилучшим образом? и что мне делать? : S

Graham

Также: Почему я не могу сделать 'bytesPerSecond = (bytesRead / duration.Elapsed.TotalSeconds)' и переместить duration.Start &uration.Stop в цикл while и получить точные результаты? Я бы подумал, что это будет точнее? Каждая скорость читается как 900 байт / с, 800 байт / с и т. Д.

Ответы [ 3 ]

3 голосов
/ 09 ноября 2009

Как я это делаю: Сохраните все байты, переданные в long.

Затем каждую 1 секунду я проверяю, сколько было передано. Так что я в основном запускаю код для сохранения скорости раз в секунду. Ваш цикл while будет циклически повторять циклы maaaaaaaaaaaany раз в секунду в быстрой сети.

В зависимости от скорости вашей сети вам может понадобиться проверить байты, переданные в отдельном потоке или функции. Я предпочитаю делать это с таймером, чтобы я мог легко обновить пользовательский интерфейс

EDIT: Судя по вашему взгляду на код, я догадываюсь, что вы делаете неправильно: вы не учитываете, что один цикл в то время как (true) не равен 1 секунде

EDIT2: Еще одно преимущество, которое заключается в том, что проверка скорости выполняется только раз в секунду, заключается в том, что все пойдет гораздо быстрее. В подобных случаях обновление пользовательского интерфейса может быть самым медленным, что вы делаете, поэтому, если вы попытаетесь обновить пользовательский интерфейс каждый цикл, это, скорее всего, ваша самая медленная точка, и она будет создавать не отвечающий пользовательский интерфейс.

Вы также правильно, что вы должны сгладить значения, чтобы вы не получили ошибок microsoft minutes . Обычно я делаю это в функции Timer, выполняя что-то вроде этого:

//Global variables
long gTotalDownloadedBytes;
long gCurrentDownloaded; // Where you add up from the download/upload untill the speedcheck is done.
int gTotalDownloadSpeedChecks;


//Inside function that does speedcheck    
gTotalDownloadedBytes += gCurrentDownloaded;
gTotalDownloadSpeedChecks++;

long AvgDwnSpeed = gTotalDownloadedBytes / gTotalDownloadSpeedChecks; // Assumes 1 speedcheck pr second.
2 голосов
/ 09 ноября 2009

Существует много уровней программного и аппаратного обеспечения между вами и системой, в которую вы отправляете, и несколько из этих слоев имеют определенный объем доступного буферного пространства.

Когда вы впервые начинаете отправку, вы можете довольно быстро выкачивать данные до тех пор, пока не заполните эти буферы - хотя на самом деле это не так быстро доходит до другого конца! После того, как вы заполните буферы отправки, вы ограничены тем, что будете помещать в них больше данных с той же скоростью, с которой они истощаются, поэтому скорость, которую вы видите, снизится до базовой скорости отправки по сети.

0 голосов
/ 09 ноября 2009

Все, я думаю, что я исправил свою проблему, настроив переменную усреднения 5 - 10, чтобы ждать одну секунду, чтобы учесть всплеск, не самый лучший, но позволит интернету разобраться самому и позволить мне захватить плавную передачу .

Судя по всему моему сетевому трафику, он разрывается, поэтому в коде нет ничего, что я мог бы сделать иначе, чтобы остановить это.

Пожалуйста, мне все еще будут интересны дополнительные ответы, прежде чем я нерешительно приму свои собственные.

...