7

I am wondering which option is basically quicker.

What interests me the most is the mechanism of redirection. I suspect the file is opened at the start of the program ./program > file and is closed at the end. Hence every time a program outputs something it should be just written to a file, as simple as it sounds. Is it so? Then I guess both options should be comparable when it comes to speed.

Or maybe it is more complicated process since the operating system has to perform more operations?

thim
  • 585
  • 1
  • 3
  • 16
  • 2
    The shell opens the file for writing before it even starts the program in question. – Etan Reisner Apr 17 '15 at 13:24
  • Right. I wasn't precise on that. – thim Apr 17 '15 at 13:25
  • I think these things are _completely different_. If you're writing a program in C, you'll use `fprintf`. When you're using pure shell and a tool that prints something, you'll be redirecting the output. Moreover, what if you don't have any BASH? Then you'll certainly use `fprintf`. – ForceBru Apr 17 '15 at 13:26
  • 1
    I would say that the performance difference between redirected `stdout` or writing directly to a file would be negligible and unmeasurable. And for the operating systems point of view, there's literally no difference. – Some programmer dude Apr 17 '15 at 13:28

3 Answers3

5

There is no much difference between that options (except making file as a strict option reduces flexibility of your program). To compare both approaches, let's check, what stays behind a magical entity FILE*:

So in both cases we have a FILE* object, a file descriptor fd - a gateway to an OS kernel and in-kernel infrastructure that provides access to files or user terminals, which should (unless libc has some special initializer for stdout or kernel specially handles files with fd = 1).

How does bash redirection work in compare with fopen()?

When bash redirects file:

fork()                      // new process is created
fd = open("file", ...)      // open new file
close(1)                    // get rid of fd=1 pointing to /dev/pts device
dup2(fd, 1)                 // make fd=1 point to opened file
close(fd)                   // get rid of redundant fd
execve("a")                 // now "a" will have file as its stdout
// in a
stdout = fdopen(1, ...)

When you open file on your own:

fork()                           // new process is created
execve("a")                      // now "a" will have file as its stdout
stdout = fdopen(1, ...)         
my_file = fopen("file", ...)     
    fd = open("file", ...)
    my_file = fdopen(fd, ...)

So as you can see, the main bash difference is twiddling with file descriptors.

myaut
  • 11,174
  • 2
  • 30
  • 62
  • This is the answer I was looking for. I suspected it is just a substitution of file descriptors but I didn't know on what level it is performed. Thank you for your answer, my knowledge hunger is satisfied ;) – thim Apr 17 '15 at 21:14
3

Yes, you are right. The speed will be identical. The only difference in the two cases is which program opens and closes the file. When you redirect it using shell, it is the shell that opens the file and makes the handle available as stdout to the program. When the program opens the file, well, the program opens the file. After that, the handle is a file handle in both the cases, so there should be absolutely no difference in speed.

As a side remark, the program which writes to stdout can be used in more general ways. You can for example say

./program | ssh remotehost bash -c "cat > file"

which will cause the output of the program to be written to file on remotehost. Of course in this case there is no comparison like one you are making in the question.

Abhay
  • 768
  • 4
  • 13
2

stdout is a FILE handle, fprintf writes to a file handle, so the speed will be very similar in both cases. In fact printf("Some string") is equivalent to fprintf(stdout, "Some string"). I will say no more :)

Cristik
  • 30,989
  • 25
  • 91
  • 127
  • I was aware of that. I was curious if bash substitutes stdout handle for a file handle. Or if maybe the mechanism is completely different. – thim Apr 17 '15 at 21:07
  • Every process expects at least 3 handles: stdin, stdout, stderr. It doesn't care where that handles come from, if it can use them. For example bash/cmd/terminal send their window writing handle. – Cristik Apr 17 '15 at 21:10