Как оценить оставшееся время загрузки (точно)? - PullRequest
57 голосов
/ 06 мая 2010

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

Ответы [ 6 ]

114 голосов
/ 01 октября 2010

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

В контексте измерения скорости загрузки формула будет выглядеть так:

averageSpeed = SMOOTHING_FACTOR * lastSpeed + (1-SMOOTHING_FACTOR) * averageSpeed;

SMOOTHING_FACTOR - это число от 0 до 1. Чем выше это число, тем быстрее старые выборки отбрасываются. Как видно из формулы, когда SMOOTHING_FACTOR равен 1, вы просто используете значение вашего последнего наблюдения. Когда SMOOTHING_FACTOR равен 0 averageSpeed никогда не меняется. Итак, вы хотите что-то промежуточное, и обычно низкое значение, чтобы получить приличное сглаживание. Я обнаружил, что 0,005 обеспечивает довольно хорошее значение сглаживания для средней скорости загрузки.

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

averageSpeed - это, очевидно, число, которое вы хотите использовать для расчета вашего предполагаемого оставшегося времени. Инициализируйте это для первого lastSpeed измерения, которое вы получите.

7 голосов
/ 16 июня 2017

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

enter image description here

Толстая синяя линия в этом примере диаграммы - это фактическая пропускная способность во времени. Обратите внимание на низкую пропускную способность в течение первой половины передачи, а затем она резко возрастает во второй половине. Оранжевая линия - это общее среднее значение. Обратите внимание, что он никогда не настраивается достаточно далеко, чтобы когда-либо дать точный прогноз того, сколько времени потребуется, чтобы закончить. Серая линия - это скользящее среднее (т. Е. Среднее из последних N точек данных - на этом графике N равно 5, но на самом деле N может потребоваться увеличить для достаточного сглаживания). Это восстанавливается быстрее, но все еще требуется время, чтобы приспособиться. Это займет больше времени, чем больше N. Так что если ваши данные довольно шумные, то N должно быть больше, а время восстановления будет больше.

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

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

Еще один важный совет: разработчики обычно игнорируют время настройки и завершения в своих индикаторах выполнения и расчетах оценки времени. Это приводит к вечному индикатору выполнения на 99% или 100%, который просто сидит там в течение длительного времени (во время очистки кэшей или выполнения другой работы по очистке), или к предварительным оценкам, когда происходит сканирование каталогов или другая работа по настройке, накапливается время. но не получая никакого процента прогресса, который отбрасывает все. Вы можете запустить несколько тестов, которые включают в себя время установки и разборки, и оценить, сколько времени в среднем это время или на основе размера задания, и добавить это время в индикатор выполнения. Например, первые 5% работы - это работа по настройке, а последние 10% - это работа по разборке, а затем 85% в середине - это загрузка или повторяющийся процесс отслеживания. Это тоже может очень помочь.

7 голосов
/ 06 мая 2010
speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2
5 голосов
/ 06 мая 2010

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

2 голосов
/ 11 марта 2013

В дополнение к ответу Бена Долмана, вы также можете рассчитать колебания в алгоритме. Он будет более плавным, но также будет предсказывать среднюю скорость.

Примерно так:

prediction = 50;
depencySpeed = 200;
stableFactor = .5;
smoothFactor = median(0, abs(lastSpeed - averageSpeed), depencySpeed);
smoothFactor /= (depencySpeed - prediction * (smoothFactor / depencySpeed));
smoothFactor = smoothFactor * (1 - stableFactor) + stableFactor;
averageSpeed = smoothFactor * lastSpeed + (1 - smoothFactor) * averageSpeed;

Колебание или нет, оно будет таким же стабильным, как и другие, с правильными значениями для прогнозирования и зависимость от скорости; Вы должны немного поиграть с ним в зависимости от скорости вашего интернета. Эти настройки идеально подходят для средней скорости 600 кБ / с, когда она колеблется от 0 до 1 МБ.

1 голос
/ 19 января 2019

Я нашел ответ Бена Долмана очень полезным, но для такого, как я, который не настолько склонен к математике, мне потребовалось около часа, чтобы полностью внедрить это в мой код. Вот более простой способ сказать то же самое в python, если есть какие-либо неточности, дайте мне знать, но в моем тестировании это работает очень хорошо:

def exponential_moving_average(data, samples=0, smoothing=0.02):
    '''
    data: an array of all values.
    samples: how many previous data samples are avraged. Set to 0 to average all data points.
    smoothing: a value between 0-1, 1 being a linear average (no falloff).
    '''

    if len(data) == 1:
        return data[0]

    if samples == 0 or samples > len(data):
        samples = len(data)

    average = sum(data[-samples:]) / samples
    last_speed = data[-1]
    return (smoothing * last_speed) + ((1 - smoothing) * average)

input_data = [4.5, 8.21, 8.7, 5.8, 3.8, 2.7, 2.5, 7.1, 9.3, 2.1, 3.1, 9.7, 5.1, 6.1, 9.1, 5.0, 1.6, 6.7, 5.5, 3.2] # this would be a constant stream of download speeds as you go, pre-defined here for illustration

data = []
ema_data = []

for sample in input_data:
    data.append(sample)
    average_value = exponential_moving_average(data)
    ema_data.append(average_value)

# print it out for visualization
for i in range(len(data)):
    print("REAL: ", data[i])
    print("EMA:  ", ema_data[i])
    print("--")
...