Na maioria das vezes, é verdade que o algoritmo de origem sabe o que precisa fazer antes do tempo. No entanto, fixar o tempo que levará para executar cada etapa é uma tarefa muito difícil, se não virtualmente impossível.
Todas as tarefas não são criadas iguais
A maneira mais simples de implementar uma barra de progresso é usar uma representação gráfica do contador de tarefas. Onde a porcentagem completa é calculada simplesmente como Tarefas Completas / Número Total de Tarefas. Enquanto isso faz sentido lógico no primeiro pensamento, é importante lembrar que (obviamente) algumas tarefas demoram mais para serem concluídas.
Considere as seguintes tarefas executadas por um instalador:
- Crie uma estrutura de pastas.
- Descompacte e copie arquivos no valor de 1 GB.
- Crie entradas de registro.
- Crie entradas do menu iniciar.
Neste exemplo, as etapas 1, 3 e 4 seriam concluídas rapidamente, enquanto a etapa 2 levaria algum tempo. Assim, uma barra de progresso trabalhando em uma contagem simples saltaria para 25% muito rapidamente, pararia um pouco enquanto a etapa 2 estivesse funcionando e, em seguida, passaria para 100% quase imediatamente.
Esse tipo de implementação é bastante comum entre as barras de progresso porque, como dito acima, é fácil de implementar. No entanto, como você pode ver, está sujeito a tarefas desproporcionais que distorcem real percentual de progresso em relação ao tempo restante.
Para contornar isso, algumas barras de progresso podem usar implementações em que as etapas são ponderadas. Considere as etapas acima em que um peso relativo é atribuído a cada etapa:
- Crie uma estrutura de pastas. [Peso = 1]
- Descompacte e copie arquivos no valor de 1 GB. [Peso = 7]
- Crie entradas de registro. [Peso = 1]
- Crie entradas do menu iniciar. [Peso = 1]
Usando esse método, a barra de progresso se moveria em incrementos de 10% (como o peso total é 10) com as etapas 1, 3 e 4 movendo a barra 10% na conclusão e a etapa 2 movendo-a em 70%. Embora certamente não seja perfeito, métodos como esse são uma maneira simples de adicionar um pouco mais de precisão à porcentagem da barra de progresso.
Resultados anteriores não garantem o desempenho futuro
Considere um exemplo simples de eu pedir para você contar até 50 enquanto uso um cronômetro para marcar seu tempo. Digamos que você conte até 25 em 10 segundos. Seria razoável supor que você contará os números restantes em mais 10 segundos, portanto, uma barra de progresso que rastreia isso mostrará 50% concluída com 10 segundos restantes.
Uma vez que sua contagem chega a 25, no entanto, eu começo a jogar bolas de tênis em você. Provavelmente, isso irá quebrar seu ritmo à medida que sua concentração passar de contar os números estritamente para evitar as bolas jogadas em seu caminho. Assumindo que você é capaz de continuar contando, seu ritmo certamente diminuiu um pouco. Então agora a barra de progresso ainda está se movendo, mas a um ritmo muito mais lento, com o tempo estimado permanecendo parado ou subindo mais alto.
Para um exemplo mais prático disso, considere um download de arquivo. Você está atualmente baixando um arquivo de 100 MB a uma taxa de 1 MB / s. Isso é muito fácil de determinar o tempo estimado de conclusão. Mas 75% do caminho, alguns congestionamentos na rede e sua taxa de download cai para 500 KB / s.
Dependendo de como o navegador calcula o tempo restante, seu ETA pode passar instantaneamente de 25 segundos para 50 segundos (usando somente o estado atual: Tamanho restante / velocidade de download) ou, muito provavelmente, o navegador usa um algoritmo de média móvel que ajusta as flutuações na velocidade de transferência sem exibir saltos dramáticos para o usuário.
Um exemplo de um algoritmo de rolagem com relação ao download de um arquivo pode funcionar assim:
- A velocidade de transferência para os 60 segundos anteriores é lembrada com o valor mais novo substituindo o mais antigo (por exemplo, o 61º valor substitui o primeiro).
- A taxa de transferência efetiva para fins de cálculo é a média dessas medições.
- O tempo restante é calculado como: Tamanho restante / velocidade de download efetiva
Então, usando o nosso cenário acima (por questão de simplicidade, usaremos 1 MB = 1.000 KB):
- Com 75 segundos de download, nossos 60 valores lembrados seriam 1.000 KB. A taxa de transferência efetiva é de 1.000 KB (60.000 KB / 60), o que resulta em um tempo restante de 25 segundos (25.000 KB / 1.000 KB).
- Em 76 segundos (onde a velocidade de transferência cai para 500 KB), a velocidade de download efetiva se torna ~ 992 KB (59.500 KB / 60), o que resulta em um tempo restante de ~ 24,7 segundos (24.500 KB / 992 KB).
- Em 77 segundos: Velocidade efetiva = ~ 983 KB (59.000 KB / 60), resultando em tempo restante de ~ 24,4 segundos (24.000 KB / 983 KB).
- Aos 78 segundos: Velocidade efetiva = 975 KB (58.500 KB / 60), resultando em tempo restante de ~ 24,1 segundos (23,500 KB / 975 KB).
Você pode ver o padrão emergindo aqui à medida que o mergulho na velocidade de download é lentamente incorporado à média usada para estimar o tempo restante. Sob esse método, se a imersão durasse apenas 10 segundos e depois retornasse a 1 MB / s, é improvável que o usuário notasse a diferença (exceto por uma pequena parada na contagem de tempo estimada).
Chegar às armadilhas de metal - esta é simplesmente uma metodologia para transmitir informações ao usuário final para a causa subjacente real…
Você não pode determinar com precisão algo que não é determinista
Em última análise, a imprecisão da barra de progresso se resume ao fato de que está tentando determinar um tempo para algo não determinístico. Como os computadores processam tarefas tanto sob demanda quanto em segundo plano, é quase impossível saber quais recursos do sistema estarão disponíveis em qualquer ponto no futuro - e é a disponibilidade de recursos do sistema que é necessária para qualquer tarefa ser concluída.
Usando outro exemplo, suponha que você esteja executando uma atualização de programa em um servidor que executa uma atualização de banco de dados bastante intensiva. Durante esse processo de atualização, um usuário envia uma solicitação exigente para outro banco de dados em execução nesse sistema. Agora, os recursos do servidor, especificamente para o banco de dados, estão tendo que processar solicitações para a atualização, bem como a consulta iniciada pelo usuário - um cenário que certamente será mutuamente prejudicial para o tempo de execução. Como alternativa, um usuário poderia iniciar uma solicitação de transferência de arquivos grande que taxaria a taxa de transferência de armazenamento, o que também prejudicaria o desempenho. Ou uma tarefa agendada pode ser iniciada, executando um processo intensivo de memória. Você entendeu a ideia.
Como, talvez, uma instância mais realista para um usuário comum - considere executar o Windows Update ou uma verificação de vírus. Ambas as operações executam operações intensivas de recursos em segundo plano. Como resultado, o progresso que cada um faz depende do que o usuário está fazendo no momento. Se você estiver lendo seu e-mail durante a execução, provavelmente a demanda por recursos do sistema será baixa e a barra de progresso será movida consistentemente. Por outro lado, se você estiver fazendo edição de gráficos, sua demanda por recursos do sistema será muito maior, o que fará com que o movimento da barra de progresso seja esquizofrênico.
No geral, é simplesmente que não há bola de cristal. Nem mesmo o próprio sistema sabe em que carga ele estará em algum momento no futuro.
Em última análise, isso realmente não importa
A intenção da barra de progresso é, bem, indicar que o progresso está realmente sendo feito e o respectivo processo não está suspenso. É bom quando o indicador de progresso é preciso, mas normalmente é apenas um pequeno aborrecimento quando não é. Na maior parte, os desenvolvedores não vão dedicar muito tempo e esforço aos algoritmos de barra de progresso porque, francamente, há tarefas muito mais importantes para gastar tempo.
Claro, você tem todo o direito de ficar aborrecido quando uma barra de progresso pula para 99% completa instantaneamente e então faz você esperar 5 minutos pelo 1% restante. Mas se o respectivo programa funcionar bem no geral, lembre-se de que o desenvolvedor tinha suas prioridades.