Как лучше всего рассчитать оставшееся время загрузки? - PullRequest
14 голосов
/ 28 апреля 2009

Допустим, вы хотите рассчитать оставшееся время загрузки, и у вас есть вся необходимая информация, а именно: размер файла, размер dl, оставшийся размер, прошедшее время, мгновенная скорость dl и т. Д. '. Как бы вы рассчитали оставшееся время дл?

Конечно, прямой путь может быть либо: размер влево / мгновенная скорость dl, либо: (размер прошедшего времени / длина) * размер влево. Только то, что первое будет подвержено отклонениям в мгновенной скорости, а второе не будет хорошо адаптироваться к изменяющимся скоростям.

Должен быть какой-то умный способ сделать это, верно? Посмотрите на пиратское программное обеспечение и музыку, которую вы сейчас загружаете с помощью uTorrent. Легко заметить, что он делает больше, чем простой расчет, упомянутый ранее. На самом деле, я замечаю, что иногда, когда скорость dl падает, оставшееся время также падает на пару мгновений, пока не будет перенастроено.

Ответы [ 7 ]

12 голосов
/ 28 апреля 2009

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

Подумайте, начну ли я загружать файл одновременно с 9 другими. Я получаю только 10% от моей нормальной скорости, но в середине файла, остальные 9 финишируют. Теперь я загружаю в 10 раз больше скорости, с которой я начал. Моя первоначальная скорость 10% не должна быть фактором, определяющим, «сколько времени осталось?» расчет больше.

Лично я, вероятно, взял бы среднее значение за последние 30 секунд или около того, и использовал бы это. Это должны делать расчеты, основанные на недавней скорости, без колебаний. 30 секунд, возможно, не правильное количество, чтобы выяснить хорошее количество, потребуются некоторые эксперименты.

Другим вариантом было бы установить своего рода «порог флуктуации», при котором вы не производите никакого пересчета, пока скорость не изменится более чем на этот порог. Например (случайное число, опять же, потребует экспериментов), вы можете установить порог в 10%. Затем, если вы загружаете со скоростью 100 Кбит / с, вы не пересчитываете оставшееся время до тех пор, пока скорость загрузки не изменится ниже 90 Кбит / с или 110 Кбит / с. Если происходит одно из этих изменений, время пересчитывается и устанавливается новый порог.

10 голосов
/ 28 апреля 2009

Вы можете использовать алгоритм усреднения, при котором старые значения затухают линейно. Если S_n - это скорость в момент времени n, а A_ {n-1} - это среднее значение в момент времени n-1, определите свою среднюю скорость следующим образом.

A_1 = S_1
A_2 = (S_1 + S_2) / 2
A_n = S_n / (n-1) + A_ {n-1} (1-1 / (n-1))

В английском это означает, что чем дольше в прошлом проводилось измерение, тем меньше оно имеет значение, потому что его важность упала.

Сравните это с обычным алгоритмом усреднения: A_n = S_n / n + A_ {n-1} (1-1 / n)

Вы также можете получить геометрическое затухание, которое очень сильно отразится на последних скоростях: A_n = S_n / 2 + A_ {n-1} / 2

Если скорости 4,3,5,6, то A_4 = 4,5 (простое среднее)
A_4 = 4,75 (линейный распад)
A_4 = 5,125 (геометрический распад)

Пример на PHP

Обратите внимание, что $n+1 (не $n) - это число текущих точек данных из-за того, что массивы PHP индексируются с нулевым индексом. Чтобы соответствовать приведенному выше примеру, установите n == $n+1 или n-1 == $n

<?php

$s = [4,3,5,6];

// average
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];
    else
    {
        // $n+1 = number of data points so far
        $weight = 1/($n+1);

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);


// linear decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];

    elseif ($n == 1)
        $a[$n] = ($s[$n] + $s[$n-1]) / 2;

    else
    {
        // $n = number of data points so far - 1
        $weight = 1/($n);

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);


// geometric decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];
    else
    {
        $weight = 1/2;

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);

выход

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4
  3 => float 4.5

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4.25
  3 => float 4.8333333333333

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4.25
  3 => float 5.125
7 голосов
/ 28 апреля 2009

Очевидный путь - что-то среднее, вам нужна «скользящая средняя» скорости загрузки.

2 голосов
/ 28 апреля 2009

Я думаю, что это просто алгоритм усреднения. Усредняет скорость за несколько секунд.

1 голос
/ 28 апреля 2009

То, что вы могли бы сделать, также отслеживать свою среднюю скорость и показывать ее расчет.

0 голосов
/ 16 марта 2011

Для всех, кто заинтересовался, я написал библиотеку с открытым исходным кодом на C # под названием Progression , которая имеет реализацию "скользящего среднего": ETACalculator.cs .

Библиотека Progression определяет простую в использовании структуру для сообщения о нескольких типах прогресса. Он также легко обрабатывает вложенный прогресс для очень плавного отчета о прогрессе.

0 голосов
/ 28 апреля 2009

РЕДАКТИРОВАТЬ: Вот что я, наконец, предлагаю, я попробовал, и это дает вполне удовлетворительные результаты:

У меня нулевой инициализированный массив для каждой скорости загрузки от 0 до 500 кБ / с (может быть выше, если вы ожидаете такие скорости) с шагом 1 кБ / с. Я мгновенно определяю скорость загрузки (каждая секунда - хороший интервал) и увеличиваю элемент массива, отвечающий за ядро, на единицу. Теперь я знаю, сколько секунд я потратил на загрузку файла на каждой скорости. Сумма всех этих значений представляет собой прошедшее время (в секундах). Сумма этих значений, умноженная на соответствующую скорость, является размером, загруженным до сих пор. Если я возьму соотношение между каждым значением в массиве и истекшее время, предполагая, что шаблон изменения скорости стабилизируется, я могу сформировать формулу для прогнозирования времени, которое займет каждый размер. Этот размер в данном случае является оставшимся размером. Это то, чем я занимаюсь: Я беру сумму каждого значения элемента массива, умноженную на соответствующую скорость (индекс) и разделенную на прошедшее время. Затем я делю размер, оставленный этим значением, и это оставшееся время.

Занимает несколько секунд, чтобы стабилизироваться, а затем работает чертовски хорошо.

Обратите внимание, что это "сложное" среднее, поэтому метод отбрасывания старых значений (скользящее среднее) может улучшить его еще больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...