Лучший способ расчета ETA операции?

Я ищу лучший способ вычисления ETA операции (загрузка IE: файл) с использованием информации о линейном ходе.

Давайте скажем, что у меня есть следующий метод, который вызывается:

void ReportProgress(double position, double total)
{
    ...
}

У меня есть пара идей:

  • рассчитать прогресс в заданное время (например, последние 10 секунд) и использовать эту скорость как среднюю скорость для операции
  • сохранить набор последних x progresses, о которых сообщалось, рассчитать скорость каждого приращения и использовать средний

Ответы

Ответ 1

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

В первую очередь не учитывается ситуация, когда операция действительно ускоряется, она говорит, что там 10 минут, и я возвращаюсь после 3, и она закончилась.

Второе не учитывает, что операция становится медленнее - я думаю, что Windows Explorer должен использовать этот метод, поскольку он всегда, кажется, занимает 90% времени, копируя 90% файлов, а затем еще 90% времени копирует последние 10% файлов: -).

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

Ответ 2

Что-то вроде этого должно сделать трюк:

void ReportProgress(double position, double total)
{
    static TimeType startTime;

    if (position == 0)
    {
        startTime = GetTime();
        return; // to avoid a divide-by-zero error
    }

    TimeType elapsedTime = GetTime() - startTime;
    TimeType estimatedRemaining = elapsedTime * total / position;
    TimeType estimatedEndTime = GetTime() + estimatedRemaining;

    // Print the results here
}

Оценка приближается к истине, поскольку прогресс приближается к 100%

Ответ 3

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

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

  • Количество файлов
  • Размер файлов

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

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

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

Your download will complete in 6 minutes, if the download speed stays at 50k/s

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

Ответ 4

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

Некоторые релевантные ссылки:

Ответ 5

Если вы хотите ETA, а не "индикатор выполнения", можете ли вы предоставить более одной цифры?

Рассчитайте среднюю скорость загрузки в течение заданного периода времени (в зависимости от того, как долго длится полная загрузка, если вы смотрите на 10+ минут, то каждые 5 или около того будет нормально) и сохраните запись средние значения.

Затем вы можете указать две цифры, верхнюю и нижнюю оценки.

Если вы уверены, что средние показатели будут хорошим показателем общего времени для загрузки, тогда вы можете отобразить 40-й процентиль и 60-е - если среднее время загрузки сильно варьируется, тогда 10 и 90-е могут быть лучше.

Я бы предпочел увидеть стадион "21 -30 минут", и это было бы точно, если бы было сказано 29 минут 35,2 секунды, и это было далеко, и дико варьировалось от одного обновления к другому.

Ответ 6

В Python:

>>> done=0.3; duration=10; "time left: %i" % (duration/done-duration)
'time left: 23'

Ответ 7

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

Изменить: Если операция несовместима с предыдущими запусками, а также несовместима с начала до конца, тогда у вас есть проблема с неразрешимостью. Прогнозировать непредсказуемое всегда весело:)

Вы можете решить заблаговременно, если хотите недооценивать или переоценивать, и добавить к расчету коэффициент вымывания. Например, если вы хотите переоценить, а первые 10% занимают 6 секунд, вы можете экстраполировать до 60 секунд, а затем умножить на 1,5, чтобы получить общую оценку в 90 секунд. По мере того, как процентное соотношение возрастает, уменьшайте коэффициент вымывания до 100% и становитесь 1.0.

Ответ 8

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

Затем время в списке усредняется, и полученное время умножается на количество оставшихся партий.

number of batches = N
size of batch = x
past computations length = l (t0,t1,...,tl)
avg time per batch = (t0 + t1 + ... + tl) / l = t
computed batches = n

ETA = t * (N - n)

Обратите внимание, что список имеет фиксированную длину, которая должна быть достаточно длинной, чтобы процесс оценки "помнил" и настраивался на возможные пики при вычислении, но он также должен быть достаточно коротким, чтобы быстро адаптироваться к изменениям скорости вычислений (например, больше времени вычисления конец конкурирующей задачи/большая пропускная способность)