Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will printf still have a cost even if I redirect output to /dev/null?

We have a daemon that contains a lot of print messages. Since we are working on an embedded device with a weak CPU and other constraint hardware, we want to minimize any kinds of costs (IO, CPU, etc..) of printf messages in our final version. (Users don't have a console)

My teammate and I have a disagreement. He thinks we can just redirect everything to /dev/null. It won't cost any IO so affections will be minimal. But I think it will still cost CPU and we better define a macro for printf so we can rewrite "printf" (maybe just return).

So I need some opinions about who is right. Will Linux be smart enough to optimize printf? I really doubt it.

like image 476
Michael Avatar asked Jan 15 '19 09:01

Michael


People also ask

How do I redirect all output to Dev Null?

You can send output to /dev/null, by using command >/dev/null syntax. However, this will not work when command will use the standard error (FD # 2). So you need to modify >/dev/null as follows to redirect both output and errors to /dev/null.

What is redirect Dev Null?

Redirect All Output to /dev/null The string >/dev/null means “send stdout to /dev/null,” and the second part, 2>&1 , means send stderr to stdout. In this case you have to refer to stdout as “&1” instead of simply “1.” Writing “2>1” would just redirect stdout to a file named “1.”

What happens when printf is executed?

Most of the compilers takes each parameter of printf() from right to left. So in the first printf() statement, the last parameter is x++, so this will be executed first, it will print 20, after that increase the value from 20 to 21. Now print the second last argument, and show 21.

What can I use instead of printf in C?

puts() The function puts() is used to print the string on the output stream with the additional new line character '\n'. It moves the cursor to the next line. Implementation of puts() is easier than printf().


3 Answers

Pretty much.

When you redirect the stdout of the program to /dev/null, any call to printf(3) will still evaluate all the arguments, and the string formatting process will still take place before calling write(2), which writes the full formatted string to the standard output of the process. It's at the kernel level that the data isn't written to disk, but discarded by the handler associated with the special device /dev/null.

So at the very best, you won't bypass or evade the overhead of evaluating the arguments and passing them to printf, the string formatting job behind printf, and at least one system call to actually write the data, just by redirecting stdout to /dev/null. Well, that's a true difference on Linux. The implementation just returns the number of bytes you wanted to write (specified by the 3rd argument of your call to write(2)) and ignores everything else (see this answer). Depending on the amount of data you're writing, and the speed of the target device (disk or terminal), the difference in performance may vary a lot. On embedded systems, generally speaking, cutting off the disk write by redirecting to /dev/null can save quite some system resources for a non-trivial amount of written data.

Although in theory, the program could detect /dev/null and perform some optimizations within the restrictions of standards they comply to (ISO C and POSIX), based on general understanding of common implementations, they practically don't (i.e. I am unaware of any Unix or Linux system doing so).

The POSIX standard mandates writing to the standard output for any call to printf(3), so it's not standard-conforming to suppress the call to write(2) depending on the associated file descriptors. For more details about POSIX requirements, you can read Damon's answer. Oh, and a quick note: All Linux distros are practically POSIX-compliant, despite not being certified to be so.

Be aware that if you replace printf completely, some side effects may go wrong, for example printf("%d%n", a++, &b). If you really need to suppress the output depending on the program execution environment, consider setting a global flag and wrap up printf to check the flag before printing — it isn't going to slow down the program to an extent where the performance loss is visible, as a single condition check is much faster than calling printf and doing all the string formatting.

like image 95
iBug Avatar answered Oct 09 '22 11:10

iBug


The printf function will write to stdout. It is not conforming to optimize for /dev/null. Therefore, you will have the overhead of parsing the format string and evaluating any necessary arguments, and you will have at least one syscall, plus you will copy a buffer to kernel address space (which, compared to the cost of the syscall is neglegible).

This answer is based on the specific documentation of POSIX.

System Interfaces
dprintf, fprintf, printf, snprintf, sprintf - print formatted output

The fprintf() function shall place output on the named output stream. The printf() function shall place output on the standard output stream stdout. The sprintf() function shall place output followed by the null byte, '\0', in consecutive bytes starting at *s; it is the user's responsibility to ensure that enough space is available.

Base Definitions
shall
For an implementation that conforms to POSIX.1-2017, describes a feature or behavior that is mandatory. An application can rely on the existence of the feature or behavior.

like image 41
Damon Avatar answered Oct 09 '22 11:10

Damon


The printf function writes to stdout. If the file descriptor connected to stdout is redirected to /dev/null then no output will be written anywhere (but it will still be written), but the call to printf itself and the formatting it does will still happen.

like image 11
Some programmer dude Avatar answered Oct 09 '22 10:10

Some programmer dude