сделать вывод stdout с определенной скоростью

Для нагрузочного теста моего приложения (под Linux) я ищу инструмент, который выводит данные на стандартный вывод с определенной скоростью (например, 100 байт/с), чтобы я мог передавать вывод в netcat, который отправляет его на мой заявление. Какой-то вариант для дд был бы идеальным, но я пока ничего не нашел. На самом деле не имеет значения, какие данные печатаются (байты NUL в порядке). Любые подсказки?


person oliver    schedule 28.10.2008    source источник
comment
Корреспондент прокомментировал мне, что использование канала для netcat может означать, что канал может быть ограничивающим фактором. Таким образом, более надежно писать напрямую в сокет с той скоростью, которую вы ищете.   -  person Chris Jester-Young    schedule 28.10.2008


Ответы (4)


Я думаю, это то, что вам действительно нужно: Pipe Viewer

Использование <fast input> | pv -qL <rate>[k|m|g|t] | <rate-limited output> ограничит канал запрошенной скоростью.

person eborisch    schedule 29.06.2012

Я написал быструю программу, которая принимает один аргумент, сколько A символов выводить на стандартный вывод в секунду (отрицательный аргумент означает отсутствие ограничения скорости). Надеюсь это поможет! :-) (В GNU libc вам нужно связать вашу программу с -lrt.)

Редактировать: изменено, чтобы печатать точку по умолчанию, если не указан второй аргумент, и в этом случае используется первый символ этого. (И это означает, что если вы хотите напечатать символ NUL, просто укажите пустую строку в качестве второго аргумента. :-))

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int
sleeptill(const struct timespec *when)
{
    struct timespec now, diff;

    clock_gettime(CLOCK_REALTIME, &now);
    diff.tv_sec = when->tv_sec - now.tv_sec;
    diff.tv_nsec = when->tv_nsec - now.tv_nsec;
    while (diff.tv_nsec < 0) {
        diff.tv_nsec += 1000000000;
        --diff.tv_sec;
    }
    if (diff.tv_sec < 0)
        return 0;
    return nanosleep(&diff, 0);
}

int
main(int argc, char **argv)
{
    double rate = 0.0;
    char *endp;
    struct timespec start;
    double offset;

    if (argc >= 2) {
        rate = strtod(argv[1], &endp);
        if (endp == argv[1] || *endp)
            rate = 0.0;
        else
            rate = 1 / rate;

        if (!argv[2])
            argv[2] = ".";
    }

    if (!rate) {
        fprintf(stderr, "usage: %s rate [char]\n", argv[0]);
        return 1;
    }

    clock_gettime(CLOCK_REALTIME, &start);
    offset = start.tv_nsec / 1000000000.0;

    while (1) {
        struct timespec till = start;
        double frac;
        double whole;

        frac = modf(offset += rate, &whole);
        till.tv_sec += whole;
        till.tv_nsec = frac * 1000000000.0;
        sleeptill(&till);
        write(STDOUT_FILENO, argv[2], 1);
    }
}
person Chris Jester-Young    schedule 28.10.2008
comment
В последней версии теперь вы можете указать 0 в качестве скорости. Технически он не ждет вечно (как и должно быть с математической точки зрения); скорее, он ждет до конца time_t (январь 2038 года, на платформах с 32-битным time_t). Впрочем, ждать еще довольно долго. :-D - person Chris Jester-Young; 28.10.2008
comment
Хороший материал - спасибо! Как насчет того, чтобы разместить его на каком-нибудь сайте контроля версий (github, launchpad, sourceforge...), чтобы люди могли добавлять изменения? Кроме того, я думаю, что для производительности было бы полезно написать() сразу целый блок данных. - person oliver; 28.10.2008
comment
Я намеренно использовал write() без буферизации, чтобы данные гарантированно поступали с постоянной скоростью. Чтобы использовать буферизацию, измените вызов write() на putchar(*argv[2]). :-) Я посмотрю, что я могу сделать с общедоступным контролем версий.... - person Chris Jester-Young; 28.10.2008
comment
Кроме того, если вы используете что-то маленькое для скорости, например 100 (как в исходном вопросе), большую часть времени будет занимать сон, а не запись. Я специально написал функцию sleeptill(), чтобы избежать проскальзывания времени из-за времени, затраченного, например, на запись. - person Chris Jester-Young; 28.10.2008
comment
Хорошо, это не github или что-то в этом роде, однако, надеюсь, это поможет: refactormycode.com/codes/ - person Chris Jester-Young; 28.10.2008

Если у вас все в порядке с получением всех сотен байтов за раз, вы можете сделать цикл с sleep и простым старым echo в оболочке, по крайней мере, в качестве первой попытки.

person unwind    schedule 28.10.2008
comment
хорошая идея — что-то вроде while [true]; сделать эхо -n 1234567890; уснуть 10000; сделано уже работает. - person oliver; 28.10.2008

Что ж, теперь я использую nuttcp для проведения «настоящих» нагрузочных тестов. Кажется, что у него довольно низкие накладные расходы, поэтому тестовая система не слишком сильно нарушена.

person oliver    schedule 28.10.2008