Рассчитать расчетное время для задания с использованием операций C #, SQL и операций с электронными таблицами [дубликат]

В веб-приложении каждая задача выполняется в виде запроса и ответа.

Программирование на стороне клиента - это HTML-код с Java-скриптом и его фреймворками, библиотеки выполняются в Internet Explorer, Mozilla, Chrome-браузерах. В сценарии Java-сценария серверные сервлеты программирования выполняются в Tomcat, web-логике, j боссе, WebSphere severs

46
задан Aaron Smith 23 January 2009 в 16:43
поделиться

15 ответов

Почему бы и нет?

(linesProcessed / TimeTaken) (timetaken / linesProcessed) * LinesLeft = TimeLeft

TimeLeft будет выражаться в любой единице времени timeTaken.

Edit:

Спасибо за комментарий, который вы правы, это должно быть:

(TimeTaken / linesProcessed) * linesLeft = timeLeft

, поэтому мы имеем

(10 / 100) * 200 = 20 секунд сейчас 10 секунды идут мимо (20 / 100) * 200 = 40 секунд осталось еще 10 секунд, и мы обрабатываем еще 100 строк (30 / 200) * 100 = 15 секунд, и теперь мы все видим, почему диалог копирования файла перескакивает с 3 часов до 30 минут :-)

53
ответ дан Jack Allen 25 August 2018 в 02:31
поделиться
  • 1
    Может быть, я что-то упустил. Скажем, мы обработали 100 строк за 10 секунд, оставив 200 строк. Это дает нам (100/10) * 200 = осталось 2000 секунд. Теперь прохождение 10 секунд не обрабатывается больше. Теперь осталось время (100/20) * 200 = осталось 1000 секунд, даже если больше не произошло обработки. – 17 of 26 23 January 2009 в 17:05
  • 2
    выражение должно быть (TimeTaken / linesProcessed) * linesLeft – Pete Kirkham 23 January 2009 в 17:13
  • 3
    Да, выражение было неправильным ;-) Но это было правильно в духе вещей! – JoshBerke 23 January 2009 в 17:17
  • 4
    Иногда, когда ваш мозг отключается, приятно находить того, кто указал на очевидный ответ (только не столь очевидный после долгого хакера). Благодарю. – Lucas 10 February 2013 в 23:36
  • 5
    Может быть, вам стоит принять во внимание то, что в первом комментарии. Исправление того, что он говорит: Скажем, мы обработали 100 строк за 10 секунд, оставив 200 строк. Это дает нам (10/100) * 200 = 20 секунд. Теперь прохождение 10 секунд не обрабатывается больше. Теперь оставшееся время (20/100) * 200 = 40 секунд осталось, даже если больше обработки не произошло. С моей точки зрения, нужно пересчитать время, оставшееся на каждой итерации, принимая во внимание не всю историю программы, а последние N времени / записей. KR – Andrés 8 October 2015 в 14:02

Как насчет этого ....

Я использовал это, чтобы пройти через набор записей (строки в файле Excel в одном случае)

L - текущая строка число X - это общее количество строк, для которых dat_Start имеет значение Now (), когда начинается процедура

Debug.Print Format((L / X), "percent") & vbTab & "Time to go:" & vbTab & Format((DateDiff("n", dat_Start, Now) / L) * (X - L), "00") & ":" & Format(((DateDiff("s", dat_Start, Now) / L) * (X - L)) Mod 60, "00")
0
ответ дан Brian Battles 25 August 2018 в 02:31
поделиться

Как правило, во время обработки вы знаете три вещи:

  1. Сколько единиц / кусков / элементов было обработано до этого момента времени (A).
  2. Сколько времени прошло для обработки этих элементов (B).
  3. Число оставшихся элементов (C).

С учетом этих элементов оценка (если время обработки элемента не будет постоянным) оставшегося времени будет

B * C / A

3
ответ дан casperOne 25 August 2018 в 02:31
поделиться
  • 1
    Какое время для обработки никогда не может быть постоянным? разница может быть незначительной, особенно на небольших партиях, но вы не можете контролировать систему за пределами своего собственного приложения, плюс это не будет постоянным. – JoshBerke 23 January 2009 в 16:52
  • 2
    Проблема с аппаратным изменением не имеет значения, так как вы выполняете CURRENT для этого уравнения, и, по-видимому, аппаратное обеспечение не меняется слишком сильно между строками 10 и 11. – GWLlosa 23 January 2009 в 17:11

Не воскрешать мертвый вопрос, но я продолжал возвращаться к ссылке на эту страницу. Вы можете создать метод расширения в классе «Секундомер», чтобы получить функциональные возможности, которые позволят получить ожидаемый оставшийся промежуток времени.

static class StopWatchUtils
{
    /// <summary>
    /// Gets estimated time on compleation. 
    /// </summary>
    /// <param name="sw"></param>
    /// <param name="counter"></param>
    /// <param name="counterGoal"></param>
    /// <returns></returns>
    public static TimeSpan GetEta(this Stopwatch sw, int counter, int counterGoal)
    {
        /* this is based off of:
         * (TimeTaken / linesProcessed) * linesLeft=timeLeft
         * so we have
         * (10/100) * 200 = 20 Seconds now 10 seconds go past
         * (20/100) * 200 = 40 Seconds left now 10 more seconds and we process 100 more lines
         * (30/200) * 100 = 15 Seconds and now we all see why the copy file dialog jumps from 3 hours to 30 minutes :-)
         * 
         * pulled from http://stackoverflow.com/questions/473355/calculate-time-remaining/473369#473369
         */
        if (counter == 0) return TimeSpan.Zero;
        float elapsedMin = ((float)sw.ElapsedMilliseconds / 1000) / 60;
        float minLeft = (elapsedMin / counter) * (counterGoal - counter); //see comment a
        TimeSpan ret = TimeSpan.FromMinutes(minLeft);
        return ret;
    }
}

Пример:

int y = 500;
Stopwatch sw = new Stopwatch();
sw.Start();
for(int x = 0 ; x < y ; x++ )
{
    //do something
    Console.WriteLine("{0} time remaining",sw.GetEta(x,y).ToString());
}

Надеюсь, это будет полезно для кого-то.

EDIT: Следует отметить, что это наиболее точно, когда каждый цикл принимает одинаковое количество времени. Редактирование 2: вместо подкласса я создал метод расширения.

8
ответ дан Chad Carisch 25 August 2018 в 02:31
поделиться

Это действительно зависит от того, что делается ... строк недостаточно, если каждая отдельная строка не принимает одинаковое количество времени.

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

0
ответ дан chills42 25 August 2018 в 02:31
поделиться
  • 1
    Вероятно, они не займут столько же времени, но я просто хочу оценить оставшееся время. Я знаю, что он не будет на 100% точным. – Aaron Smith 23 January 2009 в 16:46

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

    /// <summary>
    /// Calculates the eta.
    /// </summary>
    /// <param name="processStarted">When the process started</param>
    /// <param name="totalElements">How many items are being processed</param>
    /// <param name="processedElements">How many items are done</param>
    /// <returns>A string representing the time left</returns>
    private string CalculateEta(DateTime processStarted, int totalElements, int processedElements)
    {
        int itemsPerSecond = processedElements / (int)(processStarted - DateTime.Now).TotalSeconds;
        int secondsRemaining = (totalElements - processedElements) / itemsPerSecond;

        return new TimeSpan(0, 0, secondsRemaining).ToString();
    }

Вам потребуется инициализировать переменную DateTime при запуске обработки и отправить ее методу на каждой итерации.

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

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

Если вы используете консольное приложение, то вам не должно быть проблем с отображением вывода строка за строкой.

Надеюсь, что это кому-то поможет.

3
ответ дан Community 25 August 2018 в 02:31
поделиться
  • 1
    Я получаю деленное на ноль в itemsPerSecond = ... Мой процесс начинается 23:53:26, а мой DateTime.Now - 23:53:28. Почему деление на ноль? – Daniel Brunner 25 August 2014 в 22:55
  • 2
    Привет, Даниэль, TimeSpan (результат добавления или вычитания объектов DateTime), вероятно, имеет значение «Zero». секунд. В соответствии с вашими значениями оно должно быть «2». секунд .. пожалуйста, проверьте значение "Ticks" для обеспечения того, что он отличается от «processStarted», и DateTime.Now – coloboxp 26 August 2014 в 13:07
  • 3
    Я использовал двойники вместо целых чисел, и все сработало! – Daniel Brunner 26 August 2014 в 13:31

нет стандартного алгоритма, о котором я знаю, мой sugestion был бы следующим:

  • Создать переменную для сохранения%
  • Рассчитать сложность задачи, которую вы хотите трек (или его оценка)
  • Время от времени добавляйте приращения к%.

Вероятно, вы видели программы, в которых load bar работает намного быстрее в одной точке, чем в другой. Ну, это в значительной степени, потому что так они и делают. (хотя они, вероятно, просто помещают инкременты с регулярными интервалами в основную оболочку)

1
ответ дан fmsf 25 August 2018 в 02:31
поделиться

Если вы знаете, что процент завершен, и вы можете просто предположить, что линейная шкала времени линейна, может работать что-то вроде

timeLeft = timeSoFar * (1 / Percentage)

.

0
ответ дан GWLlosa 25 August 2018 в 02:31
поделиться

Я удивлен, что никто не ответил на этот вопрос кодом!

Простой способ рассчитать время, как ответил @JoshBerke, можно закодировать следующим образом:

DateTime startTime = DateTime.Now;
for (int index = 0, count = lines.Count; index < count; index++) {
    // Do the processing
    ...

    // Calculate the time remaining:
    TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (count - (index+1)) / (index+1));

    // Display the progress to the user
    ...
}

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

Например, когда вы загружаете большой файл, скорость загрузки может легко меняться. Чтобы вычислить наиболее точный «ETA», хорошим алгоритмом было бы только рассмотрение последних 10 секунд прогресса. Выполните ETACalculator.cs для реализации этого алгоритма!

ETACalculator.cs из Progression - библиотека с открытым исходным кодом, которую я написал. Он определяет очень простую в использовании структуру для всех видов «расчета прогресса». Это позволяет легко вставлять шаги, сообщающие о разных типах прогресса. Если вы обеспокоены восприятием производительности (как предложил @JoshBerke), это очень поможет вам.

24
ответ дан JoshBerke 25 August 2018 в 02:31
поделиться
  • 1
    Мне нравится «за последние 10 секунд прогресса». часть... – Alexander 28 September 2015 в 11:57
  • 2
    Спасибо, ваш ETACalculator работает очень хорошо! – SsjCosty 23 August 2016 в 13:56
  • 3
    На самом деле это довольно хорошая библиотека. Я думаю, что если вы создадите для него пакет NuGet, он может стать популярным. – Ahmed Abdelhameed 22 March 2018 в 06:29

Убедитесь, что вы воспринимаете производительность .

Хотя все тестовые бары занимали ровно столько же времени в тесте, две характеристики заставили пользователей думать о процессе был быстрее, даже если это не было:

  1. индикаторы выполнения, которые плавно продвигались к завершению
  2. индикаторы выполнения, которые ускорялись к концу
16
ответ дан KingPin 25 August 2018 в 02:31
поделиться
  • 1
    Да, я прочитал этот пост. И я почувствовал последствия того, о чем он говорил. Копирование ощутимо ДЕЙСТВИТЕЛЬНО медленное в Vista, но, видимо, из-за индикатора прогресса, а не фактического времени, которое потребовалось. – Aaron Smith 23 January 2009 в 16:56
  • 2
    Нет. Копирование в [Vista] очень медленное . И удаление, и un / sharing ... – DisgruntledGoat 6 August 2009 в 12:49
  • 3
    Я согласен с недовольством. Это намного лучше в Windows 7, как и все остальное в Windows 7. – Aaron Smith 3 November 2009 в 21:49

Это сильно зависит от того, что такое «что-то». Если вы можете предположить, что время обработки каждой строки аналогично, вы можете сделать простой расчет:

TimePerLine = Elapsed / LinesProcessed
TotalTime = TimePerLine * TotalLines
TimeRemaining = TotalTime - LinesRemaining * TimePerLine
2
ответ дан Michael Meadows 25 August 2018 в 02:31
поделиться
  • 1
    Просто немного Редактировать: TimeRemaining = (TotalTime - LinesRemaining) * TimePerLine – RayOldProf 11 April 2013 в 12:28

Существует 2 способа отображения времени

  1. . Истекшее время и время, оставшееся в целом: так что истекшее будет увеличиваться, но остальное будет, вероятно, стабильным общим временем (если в секунду стабильно)
  2. Истекшее время и время влево: так что Время влево = Общее необходимое - Истекшее

Моя идея / формула более вероятна:

Обработано - обновлено с текущий поток от 0 до Total

У меня есть таймер с интервалом 1000 мс, который вычисляет обрабатываемые в секунду:

processedPerSecond = Processed - lastTickProcessed;
lastTickProcessed = Processed;  //store state from past call

обработаноPerSecond и lastTickProcessed - глобальные переменные из метода таймера

Теперь, если мы хотим получить сколько секунд потребуется для завершения обработки (в идеальном постоянном предположении) totalSecondsNeeded = TotalLines / PerSecond

, но мы хотим показать случай 2. TimeLeft так TimeLeftSeconds = (TotalLines - Обработано) / PerSecond

TimeSpan remaining = new TimeSpan(0, 0, (transactions.Count - Processed) / processedPerSecond);
labelTimeRemaining.Text = remaining.ToString(@"hh\:mm\:ss");

Конечно, TimeLeftSeconds будет «прыгать», если PerSecond перепрыгивает, поэтому, если прошлое PerSecond было 10, а затем 30, а затем назад до 10, пользователь увидит его.

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

int perSecond = (int)Math.Ceiling((processed / (decimal)timeElapsed.TotalSeconds));  //average not in past second

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

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

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

0
ответ дан Pawel Cioch 25 August 2018 в 02:31
поделиться

Где time$("ms") представляет текущее время в миллисекундах с 00:00 до 00:00, а lof представляет собой итоговые строки для обработки, а x представляет текущую строку:

if Ln>0 then
    Tn=Tn+time$("ms")-Ln   'grand total of all laps
    Rn=Tn*(lof-x)/x^2      'estimated time remaining in seconds
end if
Ln=time$("ms")             'start lap time (current time)
1
ответ дан radu florescu 25 August 2018 в 02:31
поделиться

Я уже знал, что процент завершен & amp; время от времени, так что это помогло мне:

TimeElapsed * ((100%%) /% завершено) = TimeRemaining

Затем я обновлял это значение каждый раз, когда% полностью изменилось, постоянный изменяющийся ETA.

0
ответ дан Schrodo_Baggins 25 August 2018 в 02:31
поделиться

Функция PowerShell

function CalculateEta([datetime]$processStarted, [long]$totalElements, [long]$processedElements) {
    $itemsPerSecond = $processedElements / [DateTime]::Now.Subtract($processStarted).TotalSeconds
    $secondsRemaining = ($totalElements - $processedElements) / $itemsPerSecond

    return [TimeSpan]::FromSeconds($secondsRemaining)
}
0
ответ дан Vladislav Sorokin 25 August 2018 в 02:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: