Eu tenho um script de linha de comando que executa uma chamada de API e atualiza um banco de dados com os resultados.
Eu tenho um limite de 5 chamadas de API por segundo com o provedor de API. O script leva mais de 0,2 segundos para ser executado.
- Se eu executar o comando sequencialmente, ele não será executado rápido o suficiente e só farei 1 ou 2 chamadas de API por segundo.
- Se eu executar o comando seqüencialmente, mas simultaneamente em vários terminais, posso exceder o limite de 5 chamadas / segundo.
Existe uma maneira de orquestrar threads para que meu script de linha de comando seja executado quase exatamente 5 vezes por segundo?
Por exemplo, algo que seria executado com 5 ou 10 threads, e nenhum thread executaria o script se um thread anterior o executasse há menos de 200 ms.
command-line
multithreading
Benjamin
fonte
fonte
Respostas:
Em um sistema GNU e, se houver
pv
, você pode fazer:O
-P20
é executar no máximo 20$cmd
ao mesmo tempo.-L10
limita a taxa a 10 bytes por segundo, portanto, 5 linhas por segundo.Se seus
$cmd
s se tornarem lentos e fizer com que o limite de 20 seja atingido, axargs
leitura será interrompida até que$cmd
pelo menos uma instância retorne.pv
ainda continuará gravando no pipe na mesma taxa, até que o pipe fique cheio (o que no Linux com um tamanho de pipe padrão de 64KiB levará quase 2 horas).Nesse ponto,
pv
parará de escrever. Mas mesmo assim, quandoxargs
retomar a leitura,pv
tentará recuperar e enviar todas as linhas que deveria ter enviado mais cedo o mais rápido possível, para manter uma média geral de 5 linhas por segundo.O que isso significa é que, contanto que seja possível, com 20 processos, atender a 5 rodadas por segundo no requisito médio, isso será feito. No entanto, quando o limite é atingido, a taxa na qual novos processos são iniciados não será conduzida pelo timer do pv, mas pela taxa na qual as instâncias anteriores do cmd retornam. Por exemplo, se 20 estão em execução no momento e duram 10 segundos, e 10 deles decidem terminar todos ao mesmo tempo, 10 novos serão iniciados ao mesmo tempo.
Exemplo:
Em média, será 5 vezes por segundo, mesmo que o atraso entre duas execuções nem sempre seja exatamente de 0,2 segundos.
Com
ksh93
(ouzsh
se o seusleep
comando suportar segundos fracionários):Isso não vincula o número de
your-command
s concorrentes .fonte
pv
comando parece ser exatamente o que eu estava procurando, não poderia esperar melhor! Apenas nesta linhayes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
:, não é o últimosh
redundante?sh
é para o$0
seu$cmd
script. Também é usado em mensagens de erro pelo shell. Sem ele,$0
seriay
deyes
, assim que você receber mensagens de erro comoy: cannot execute cmd
... Você também pode fazeryes sh | pv -qL15 | xargs -n1 -P20 sh -c "$cmd"
sh
; e nos meus testes, quando o removo, não vejo diferença!$cmd
usar$0
(por que usaria?) E para mensagens de erro. Tente, por exemplo, comcmd=/
; sem o segundosh
, você veria algo como, emy: 1: y: /: Permission denied
vez desh: 1: sh: /: Permission denied
De maneira simplista, se o seu comando durar menos de 1 segundo, você poderá iniciar 5 comandos por segundo. Obviamente, isso é muito explosivo.
Se o seu comando demorar mais de 1 segundo e você desejar espalhar os comandos, tente
Como alternativa, você pode ter 5 loops separados que são executados de forma independente, com um mínimo de 1 segundo.
fonte
Com um programa C,
Você pode, por exemplo, usar um fio que dorme por 0,2 segundos em um tempo
use-o para saber como criar um tópico: crie um tópico (este é o link que usei para colar este código)
fonte
cc
é uma ferramenta Unix existente, e isso não é muito código!Usando o node.js, é possível iniciar um único encadeamento que executa o script bash a cada 200 milissegundos, não importa quanto tempo a resposta leve para voltar, porque a resposta vem de uma função de retorno de chamada .
Esse javascript é executado a cada 200 milissegundos e a resposta é obtida através da função de retorno de chamada
function (error, stdout, stderr)
.Dessa forma, você pode controlar que ele nunca exceda as 5 chamadas por segundo, independentemente de quão lenta ou rápida é a execução do comando ou de quanto ele precisa esperar por uma resposta.
fonte
Eu uso a
pv
solução baseada em Stéphane Chazelas há algum tempo, mas descobri que ela saiu aleatoriamente (e silenciosamente) após algum tempo, de alguns minutos a algumas horas. - Editar: o motivo foi que meu script PHP ocasionalmente morria devido a um tempo máximo de execução excedido, saindo com o status 255.Então, decidi escrever uma ferramenta simples de linha de comando que faz exatamente o que eu preciso.
Atingir meu objetivo original é tão simples quanto:
Inicia quase exatamente 5 comandos por segundo, a menos que já existam 20 processos simultâneos; nesse caso, pula as próximas execuções até que um slot fique disponível.
Esta ferramenta não é sensível a uma saída de status 255.
fonte