2

The following code executes and prints a statement ~20 times a second.

    while (1) {
        TX(port, "j1");
        usleep(30000);
        printf("\nPosition:\t%s",  (*RX(port)).data);
    }

Rather than constant new lines, I wish to have a single line printed, with the string that follows Position: updated as quickly as possible. To do so, I've replaced the new line with a carriage return:

    while (1) {
        TX(port, "j1");
        usleep(30000);
        printf("\rPosition:\t%s",  (*RX(port)).data);
    }

It is producing the exact format I want, but now I only get a print every ~6 seconds. Can anyone explain why and offer a solution?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Jim
  • 21
  • 2
  • Let's start by adding the OS you are using, the hardware you are using and where/what you are reading from. In what you have posted, there is no rhyme or reason why `'\r'` should take longer to output than `'\n` as a general matter it shouldn't. – David C. Rankin Feb 13 '20 at 08:26
  • 1
    My guess is that it's a [buffering issue](https://stackoverflow.com/q/1716296/694733), and `\r` is not counted as newline for flushing the stream. – user694733 Feb 13 '20 at 08:27

2 Answers2

3

On many systems, the amount of time required to output M chunks of data totaling N bytes is proportional to some multiple of M plus some multiple of N. To avoid wasting lots of time on small output operations, many versions of the Standard library will attempt to aggregate chunks of data to be output, so as to reduce the number of chunks involved. Sending a newline to stdout is interpreted as a hint that the system should immediately output everything prior to that, without waiting for more data to come, but that only works if data has newlines. If sending returns without newlines, it may be necessary to use fflush(stdout). to force the system to send data without waiting for more.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Further info: this may be controllable by [setvbuf](https://en.cppreference.com/w/c/io/setvbuf) – M.M Feb 13 '20 at 19:32
0

The reason the output does not update immediately is probably a buffering issue:

  • stdout is typically line buffered when directed to the terminal.
  • the \n in the first loop causes the pending output to be flushed at every iteration.
  • The default buffer size varies from one system to another, typical sizes are 512, 1024, 2048 and 4096 bytes.
  • each output has about a dozen bytes and occurs every 30 milliseconds or more: it takes about 6 seconds to produce 2 kilobytes, consistent with a 2KB buffer.
  • when the buffer is full, it is flushed in one step and the terminal displays about 200 samples very quickly, leaving only the last one to show.
  • flushing the output with fflush() or setting stdout as unbuffered at the beginning of the program will solve this issue (see https://stackoverflow.com/a/60202813/4593267 ).
  • note however that shorter output strings will leave trailing characters from previous output visible at the end of the terminal line. You should output an escape sequence \033[K to clear the end of line if the terminal supports it (linux and MacOS terminals do, Windows' might not). Alternately, you can add trailing spaces to try and erase previous characters, but it is only a partial solution.

Here is a modified loop:

    for (;;) {
        TX(port, "j1");
        usleep(30000);
        printf("\rPosition:\t%s     ",  (*RX(port)).data);
        fflush(stdout);
    }
chqrlie
  • 131,814
  • 10
  • 121
  • 189