Isso é causado pela contabilização em pv
, o que efetivamente significa que sua limitação de taxa é limitada por leitura em vez de limitada por gravação. Observando o código-fonte mostra que o limite de taxa é impulsionado por um "alvo", que é o montante restante para enviar. Se a limitação de taxa estiver ativada, uma vez por ciclo de avaliação do limite de taxa, a meta será aumentada, embora devamos enviar de acordo com o limite de taxa; o alvo é então diminuído, por mais que seja realmente escrito. Isso significa que, se você definir o limite de taxa para um valor maior que a capacidade real de gravação, o alvo continuará subindo; A redução do limite de taxa não terá efeito algum até que pv
alcance sua meta (incluindo o que é permitido gravar de acordo com o novo limite de taxa).
Para ver isso em ação, inicie um% básicopv
:
pv /dev/zero /dev/null
Em seguida, controle isso:
pv -R 32605 -L 1M; sleep 10; pv -R 32605 -L 1G; sleep 1; pv -R 32605 -L 1M
Você verá o impacto dos cálculos do alvo variando a duração do segundo sono ...
Devido à limitação de gravação, isso só causa um problema quando você define o limite de taxa para um valor maior que a capacidade de gravação.
Com um pouco mais de detalhes, veja como a contabilidade funciona com um fluxo inicialmente limitado a 1M, depois para 1G por 5s e, em seguida, de volta para 1M, em uma conexão capaz de transmitir 400M:
Time Rate Target Sent Remaining
1 1M 1M 1M 0
2 1G 1G 400M 600M
3 1G 1.6G 400M 1.2G
4 1G 2.2G 400M 1.8G
5 1G 2.8G 400M 2.4G
6 1G 3.4G 400M 3G
7 1M 3001M 400M 2601M
8 1M 2602M 400M 2202M
9 1M 2203M 400M 1803M
10 1M 1804M 400M 1404M
11 1M 1405M 400M 1005M
12 1M 1006M 400M 606M
13 1M 607M 400M 207M
14 1M 208M 208M 0
15 1M 1M 1M 0
São necessários 7 segundos para que o limite de taxa seja aplicado novamente. Quanto maior o tempo gasto com um limite de taxa alta, mais tempo será necessário para que o limite de taxa reduzida seja aplicado ...
A correção para isso é bastante simples, se você puder recompilar pv
: em loop.c
, altere a linha 154 para target =
(de target +=
), resultando em
|| (cur_time.tv_sec == next_ratecheck.tv_sec
&& cur_time.tv_usec >=
next_ratecheck.tv_usec)) {
target =
((long double) (state->rate_limit)) /
(long double) (1000000 /
RATE_GRANULARITY);
Uma vez feito isso, as reduções de limite de taxa são aplicadas imediatamente (bem, dentro de um ciclo de limite de taxa).