Development Tip

남은 다운로드 시간을 정확히 추정하는 방법은 무엇입니까?

yourdevel 2020. 12. 14. 20:55
반응형

남은 다운로드 시간을 정확히 추정하는 방법은 무엇입니까?


물론 나머지 파일 크기를 현재 다운로드 속도로 나눌 수는 있지만 다운로드 속도가 변하면 (그리고 그럴 경우) 좋은 결과를 얻지 못합니다. 더 부드러운 카운트 다운을 생성하는 더 나은 알고리즘은 무엇입니까?


저는 현재 처리량이 미리 정의 된 범위를 벗어날 때 재설정과 함께 이동 평균을 사용하는 디스크 이미징 및 멀티 캐스팅 프로그램의 남은 시간을 예측하기 위해 몇 년 전에 알고리즘을 작성했습니다. 급격한 일이 일어나지 않는 한 상황을 매끄럽게 유지 한 다음 빠르게 조정 한 다음 다시 이동 평균으로 돌아갑니다. 여기에서 예제 차트를 참조하십시오.

여기에 이미지 설명 입력

이 예제 차트의 두꺼운 파란색 선은 시간 경과에 따른 실제 처리량입니다. 전송 전반에 걸쳐 낮은 처리량을 확인한 다음 후반에 급격히 증가합니다. 주황색 선은 전체 평균입니다. 완료하는 데 걸리는 시간을 정확하게 예측할 수있을만큼 충분히 조정되지 않습니다. 회색 선은 이동 평균입니다 (즉, 마지막 N 데이터 포인트의 평균-이 그래프에서 N은 5이지만 실제로는 충분히 부드럽게하려면 N이 더 커야 할 수 있습니다). 더 빨리 회복되지만 조정하는 데 여전히 시간이 걸립니다. N이 클수록 시간이 더 걸립니다. 따라서 데이터가 상당히 시끄러 우면 N이 더 커야하고 복구 시간이 더 길어집니다.

초록색 선은 제가 사용한 알고리즘입니다. 이동 평균처럼 진행되지만 데이터가 미리 정의 된 범위 (밝은 얇은 파란색 및 노란색 선으로 지정됨)를 벗어나면 이동 평균을 재설정하고 즉시 점프합니다. 미리 정의 된 범위는 표준 편차를 기반으로 할 수도 있으므로 데이터가 자동으로 얼마나 노이즈가 있는지 조정할 수 있습니다. 이 답변에 대한 다이어그램을 만들기 위해이 값을 Excel에 넣었으므로 완벽하지는 않지만 아이디어를 얻었습니다.

데이터는이 알고리즘이 남은 시간을 잘 예측하지 못하도록 만들 수 있습니다. 결론은 데이터가 어떻게 작동할지 예상하고 그에 따라 알고리즘을 선택하는 방법에 대한 일반적인 아이디어가 필요하다는 것입니다. 내 알고리즘은 내가 본 데이터 세트에서 잘 작동했기 때문에 계속 사용했습니다.

또 다른 중요한 팁은 일반적으로 개발자가 진행률 표시 줄과 시간 추정 계산에서 설정 및 해체 시간을 무시한다는 것입니다. 이로 인해 오랜 시간 동안 (캐시가 플러시되거나 다른 정리 작업이 진행되는 동안) 영구적 인 99 % 또는 100 % 진행률 표시 줄이 나타나거나 디렉터리 스캔 또는 기타 설정 작업이 발생하면 시간이 발생하는 초기 예상치가 나타납니다. 그러나 진행률이 전혀 발생하지 않아 모든 것이 실패합니다. 설정 및 해체 시간을 포함하는 여러 테스트를 실행하고 해당 시간이 평균 또는 작업 크기에 따라 예상되는 시간을 계산하고 해당 시간을 진행률 표시 줄에 추가 할 수 있습니다. 예를 들어 작업의 처음 5 %는 설정 작업이고 마지막 10 %는 분해 작업이고 중간에있는 85 %는 다운로드 또는 추적이 반복되는 프로세스입니다.


지수 이동 평균은 이에 좋은 곳입니다. 새 샘플을 추가 할 때마다 이전 샘플이 전체 평균에서 점점 더 중요해 지도록 평균을 평활화하는 방법을 제공합니다. 그것들은 여전히 ​​고려되고 있지만 그 중요성은 기하 급수적으로 떨어집니다. 그리고 이것은 "움직이는"평균이기 때문에 하나의 숫자 만 유지하면됩니다.

다운로드 속도 측정의 맥락에서 공식은 다음과 같습니다.

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

SMOOTHING_FACTOR0과 1 사이의 숫자입니다.이 숫자가 클수록 더 빠른 오래된 샘플이 폐기됩니다. 공식에서 볼 수 있듯이 SMOOTHING_FACTOR1 일 때 마지막 관찰 값을 사용하는 것입니다. SMOOTHING_FACTOR0으로 averageSpeed변경되지 않습니다. 따라서 중간에 무언가를 원하고 일반적으로 적절한 스무딩을 얻으려면 낮은 값을 원합니다. 0.005가 평균 다운로드 속도에 대해 꽤 좋은 평활 값을 제공한다는 것을 발견했습니다.

lastSpeed마지막으로 측정 된 다운로드 속도입니다. 이 값은 매초마다 타이머를 실행하여 마지막으로 실행 한 이후 다운로드 한 바이트 수를 계산하여 얻을 수 있습니다.

averageSpeed분명히 남은 예상 시간을 계산하는 데 사용하려는 숫자입니다. 이를 첫 번째 lastSpeed측정으로 초기화하십시오 .


speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2

가장 좋은 방법은 남은 파일 크기를 평균 다운로드 속도 (지금까지 다운로드 한 시간을 다운로드 한 시간으로 나눈 값)로 나누는 것입니다. 시작하는 데 약간의 변동이 있지만 다운로드 시간이 길수록 더 안정적입니다.


Ben Dolman의 답변에 대한 확장으로 알고리즘 내에서 변동을 계산할 수도 있습니다. 더 부드럽지만 평균 속도도 예측합니다.

이 같은:

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;

변동 여부에 관계없이 예측 및 depencySpeed에 대한 올바른 값을 사용하여 다른 것만 큼 안정적입니다. 인터넷 속도에 따라 조금씩 플레이해야합니다. 이 설정은 600kB / s의 평균 속도에 적합하며 0MB에서 1MB까지 변동합니다.


Ben Dolman의 답변이 매우 도움이되었지만 수학을 잘 못하는 저와 같은 사람에게는 이것을 내 코드에 완전히 구현하는 데 약 1 시간이 걸렸습니다. 부정확 한 것이 있으면 알려주지 만 내 테스트에서는 매우 잘 작동하는 경우 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("--")

참고 URL : https://stackoverflow.com/questions/2779600/how-to-estimate-download-time-remaining-accurately

반응형