如何让命令平均每秒运行5次?

如何让命令平均每秒运行5次?

我有一个命令行脚本,它执行 API 调用并使用结果更新数据库。

我对 API 提供程序设置了每秒 5 次 API 调用的限制。该脚本的执行时间超过 0.2 秒。

  • 如果我按顺序运行该命令,它将运行得不够快,并且我每秒只会进行 1 或 2 次 API 调用。
  • 如果我按顺序但同时从多个终端运行该命令,则可能会超过每秒 5 次调用的限制。

是否有办法编排线程,以便我的命令行脚本几乎每秒执行 5 次?

例如,某个程序将使用 5 或 10 个线程运行,并且如果前一个线程在不到 200 毫秒前执行了该脚本,则没有线程会执行该脚本。

答案1

在 GNU 系统上,如果你有pv,你可以这样做:

cmd='
   that command | to execute &&
     as shell code'

yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh

最多同时-P20执行20个。$cmd

-L10将速率限制为每秒 10 字节,即每秒 5 行。

如果您的$cmds 变慢并导致达到 20 限制,则将xargs停止读取,直到$cmd至少有一个实例返回。pv仍会以相同的速率继续写入管道,直到管道变满(在默认管道大小为 64KiB 的 Linux 上,这将花费近 2 小时)。

到那时,pv就会停止写作。但即便如此,当xargs恢复阅读时,pv也会尝试尽快赶上并发送所有应该早先发送的行,以保持总体平均每秒 5 行。

这意味着只要 20 个进程能够满足平均每秒运行 5 次的要求,它就能做到。但是,当达到限制时,启动新进程的速率将不再由 pv 的计时器驱动,而是由较早的 cmd 实例返回的速率驱动。例如,如果当前有 20 个正在运行,并且已经运行了 10 秒,其中 10 个决定同时完成所有任务,那么将立即启动 10 个新的。

例子:

$ cmd='date +%T.%N; exec sleep 2'
$ yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
09:49:23.347013486
09:49:23.527446830
09:49:23.707591664
09:49:23.888182485
09:49:24.068257018
09:49:24.338570865
09:49:24.518963491
09:49:24.699206647
09:49:24.879722328
09:49:25.149988152
09:49:25.330095169

平均而言,即使两次运行之间的延迟并不总是恰好为 0.2 秒,它也会每秒 5 次。

使用ksh93(或使用,zsh如果您的sleep命令支持小数秒):

typeset -F SECONDS=0
n=0; while true; do
  your-command &
  sleep "$((++n * 0.2 - SECONDS))"
done

但这对并发数没有限制your-command

答案2

简单地说,如果您的命令持续时间少于 1 秒,您每秒只需启动 5 个命令。显然,这是非常突发的。

while sleep 1
do    for i in {1..5}
      do mycmd &
      done
done

如果您的命令可能需要超过 1 秒并且您想分散命令,您可以尝试

while :
do    for i in {0..4}
      do  sleep .$((i*2))
          mycmd &
      done
      sleep 1 &
      wait
done

或者,您可以有 5 个独立运行的单独循环,最短时间为 1 秒。

for i in {1..5}
do    while :
      do   sleep 1 &
           mycmd &
           wait
      done &
      sleep .2
done

答案3

通过 C 程序,

例如,您可以使用一个休眠 0.2 秒的线程

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid;

void* doSomeThing() {
    While(1){
         //execute my command
         sleep(0.2)
     } 
}

int main(void)
{
    int i = 0;
    int err;


    err = pthread_create(&(tid), NULL, &doSomeThing, NULL);
    if (err != 0)
        printf("\ncan't create thread :[%s]", strerror(err));
    else
        printf("\n Thread created successfully\n");



    return 0;
}

用它来了解如何创建线程:创建一个线程(这是我用来粘贴此代码的链接)

答案4

我已经使用 Stéphane Chazelas 的pv解决方案一段时间了,但发现它在一段时间后(从几分钟到几个小时)随机(并且无声地)退出。 --编辑:原因是我的 PHP 脚本偶尔会因为超出最大执行时间而死掉,并以状态 255 退出。

所以我决定写一个简单的命令行工具这正是我所需要的。

实现我最初的目标很简单:

./parallel.phar 5 20 ./my-command-line-script

它几乎每秒启动 5 个命令,除非已经有 20 个并发进程,在这种情况下,它会跳过下一个执行,直到有一个槽可用。

此工具对状态 255 退出不敏感。

相关内容