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

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

Корреспондент прокомментировал мне, что использование канала для netcat может означать, что канал может быть ограничивающим фактором. Таким образом, более надежно писать прямо в сокет с той скоростью, которую вы ищете.

Chris Jester-Young 28.10.2008 14:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
1
2 165
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

хорошая идея - что-то вроде «while [true]; do echo -n« 1234567890 »; usleep 10000; done» уже работает.

oliver 28.10.2008 13:16

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

Я написал быструю программу, которая принимает один аргумент, сколько символов 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);
    }
}

В последней версии теперь вы можете указать 0 в качестве скорости. Технически это не ждет «вечно» (как и должно быть математически); скорее, он ждет до конца time_t (январь 2038 года, на платформах с 32-битным time_t). Однако ждать еще довольно долго. :-D

Chris Jester-Young 28.10.2008 13:58

Хороший материал - спасибо! Как насчет того, чтобы разместить его на каком-нибудь сайте контроля версий (github, launchpad, sourceforge ...), чтобы люди могли добавлять изменения? Кроме того, я думаю, что для повышения производительности было бы полезно написать () сразу целый блок данных.

oliver 28.10.2008 14:06

Я намеренно использовал write () без буферизации, чтобы данные гарантированно поступали с постоянной скоростью. Чтобы использовать буферизацию, измените вызов write () на putchar (* argv [2]). :-) Я посмотрю, что я могу сделать с общедоступным контролем версий ....

Chris Jester-Young 28.10.2008 14:08

Кроме того, если вы используете что-то маленькое для скорости, например 100 (как в исходном вопросе), большую часть времени займет сон, а не запись. Я написал функцию sleeptill () специально, чтобы избежать "задержки времени" из-за затраченного времени, например, на запись.

Chris Jester-Young 28.10.2008 14:11

Хорошо, это не github или что-то в этом роде, но, надеюсь, поможет: refactormycode.com/codes/…

Chris Jester-Young 28.10.2008 14:36
Ответ принят как подходящий

Думаю, это то, что вам действительно нужно: Просмотрщик труб

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

Другие вопросы по теме