4

I tried to create around 4 GB file using c++ fopen, fwrite and fflush and fclose functions on Linux machine, but I observed that fclose() function is taking very long time to close the file, taking around (40-50 seconds). I checked different forum to find the reason for this slowness, changed the code as suggested in forums, Used setvbuf() function to make unbuffered I/O as like write() function. but still could not resolve the issue.

        totalBytes = 4294967296 // 4GB file
        buffersize = 2000;    
        while ( size <= totalBytes )
        {
            len = fwrite(buffer, 1, bufferSize, fp);
            if ( len != bufferSize ) {
                cout<<"ERROR (Internal): in calling ACE_OS::fwrite() "<<endl;
                ret = -1;
            }
            size = size + len;
        }
        ...
        ...
        ...
        fflush(fp);
        flcose(fp);

Any solution to the above problem would be very helpful.

thanks, Ramesh

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Ramesh
  • 49
  • 1
  • 2
  • 1
    Are you sure a) `fclose` is the slow one, not `fflush` and b) `fflush` is flushing and not `fclose` (if `fclose` is the slower)? It seems highly unusual that close would be slower than a 4GB flush... – ssube Aug 22 '12 at 18:12
  • Anything else you can tell us ? How do you measure it's fclose() that's the culprit ? Which platform are you on ? Anything special about the file you're writing, is it on a network share ? Is the drive nearly full ? etc. – nos Aug 22 '12 at 18:12

4 Answers4

5

The operating system is deferring actual writing to the disk and may not actually write the data to the disk at any writing operation or even at fflush().

I looked at the man page of fflush() and saw the following note:

Note that fflush() only flushes the user space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too, for example, with sync(2) or fsync(2).

(there's a similar note for fclose() as well, although behaviour on your Linux system seems different)

Lol4t0
  • 12,444
  • 4
  • 29
  • 65
Mikko Juola
  • 111
  • 2
4

It will take a long time to write that much data to the disk, and there's no way around that fact.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • True of course, but I think he's wondering why, even after trying hard to flush everything prior to the close, there's still lots of work to be done on the close itself. – GManNickG Aug 22 '12 at 18:04
  • 1
    I guess it's related to virtual memory and swap area management if he is working on x86. – Seçkin Savaşçı Aug 22 '12 at 18:06
  • fclose() is still not waiting data to be flushed to the disk from virtual memory on modern operating systems, though you can sometimes see close delays on NFS mounts or similar (for other reasons usually). – nos Aug 22 '12 at 18:11
  • @nos could you demonstrate some references for your reasoning? – Seçkin Savaşçı Aug 22 '12 at 18:14
  • flush only flushes into an OS buffer, I believe that the OS still buffers it itself. Precisely because it can't squeeze the data on to the disk anything like as fast as he can attempt to write it. – Puppy Aug 22 '12 at 18:16
  • @Seçkin Savaşçı Peek in the linux kernel for the close() syscall, and the glibc source for fclose() if you really want the details. Though it's common knowledge that writing/closing files does not wait until the data is on the disk, that's what fsync(), fdatasync() is for, or if you want to bypass OS caching altogether the O_SYNC/O_DIRECT flag to open(). (also, read the manpage for close() which specifically mentions there is no guarantee data has reached the disk) – nos Aug 22 '12 at 18:16
  • @nos thanks for useful information, I didn't know some of them. Greatly appreciated. – Seçkin Savaşçı Aug 22 '12 at 18:19
1

fopen/fwrite/fclose are C standard wrappers around the low level open/write/close. All fflush is doing is making sure all the 'write' calls have been made for something buffered. There is no "synchronization point" at the fflush. The operating system is flushing the write buffer before it allows 'close' to return.

doug65536
  • 6,562
  • 3
  • 43
  • 53
1

Yeah, the time taken by fclose() is part of the time taken by the OS to write your data to the disk.
Look at fsync for achieving what you probably wanted with fflush. If you want to display some progress and the time used by fclose() is making it inaccurate, you could do a fsync() every 100 Mbytes written, or something like that.

Torp
  • 7,924
  • 1
  • 20
  • 18