views:

256

answers:

3

For a load test of my application (under Linux), I'm looking for a tool that outputs data on stdout at a specific rate (like 100 bytes/s), so that I can pipe the output to netcat which sends it to my application. Some option for dd would be ideal, but I didn't find anything so far. It doesn't really matter what kind of data is printed (NUL bytes are OK). Any hints?

+2  A: 

If you're fine with getting all hundred bytes at a time, you could do a loop with sleep and plain old echo in the shell as a first attempt at least.

unwind
good idea - something like "while [ true ]; do echo -n "1234567890"; usleep 10000; done" already works.
oliver
A: 

Well, I'm now using nuttcp to do "real" load tests instead. It seems to have quite low overhead, so the test system is not too much disturbed.

oliver
+3  A: 

I wrote a quick program that takes one argument, how many A characters to print to standard output per second (negative argument means no rate limiting). Hope this helps! :-) (On GNU libc, you will need to link your program with -lrt.)

Edit: revised to print dot by default, unless a second argument is specified, in which case the first character of that is used. (And that means, if you want to print the NUL character, just specify an empty string as the second argument. :-))

#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);
    }
}
Chris Jester-Young
With the latest revision, you can now specify 0 as the rate. Technically, it doesn't wait "forever" (as it should, mathematically); rather, it waits until the end of time_t (January 2038, on platforms with a 32-bit time_t). That's still quite a while to wait, though. :-D
Chris Jester-Young
Nice stuff - thanks! How about putting it up on some revision control site (github, launchpad, sourceforge...) so people can add changes?Also, I think for performance it would be useful to write() a whole block of data at once.
oliver
I deliberately used write() with no buffering so the data is guaranteed to come at a constant rate. To use buffering, change the write() call to putchar(*argv[2]). :-) I'll see what I can do about public revision control....
Chris Jester-Young
Also, if you're using something small for the rate like 100 (as in your original question), most of the time will be taken by the sleep, not by the write. I wrote the sleeptill() function expressly to avoid "time slippage" due to the time taken, such as by the write.
Chris Jester-Young
Okay, this isn't github or anything like it, however it'll hopefully do the trick: http://refactormycode.com/codes/566-writing-characters-to-stdout-at-a-specified-rate
Chris Jester-Young