tags:

views:

171

answers:

4

I have noticed a huge performance hit in one of my projects when logging is enabled for the first time. But when the log file limit is reached and the program starts writing to the beginning of the file again, the logging speed is much faster (about 50% faster). It's normal to set the log file size to hundreds of MBs.

Most download managers allocate dummy file with the required size before starting to download the file. This makes the writing more effecient because the whole chunk is allocated at once.

What is the best way to reserve disk space efficiently, by some fixed size, when my program starts for the first time?

+1  A: 

Why can't you just create an empty log using any size you want?

wRAR
That's exactly what I need. My questions is how to do it. What is the most efficient way to create that empty log file with some size on disk?
haggag
+3  A: 

wRAR is correct. Open a new file using your favourite library, then seek to the penultimate byte and write a 0 there. That should allocate all the required disk space.

Ali Lown
Is is true? I always thought that NTFS supports file holes, but I cannot find a source for that right now.
dmeister
"Most applications are not aware of sparse files and will not create sparse files. The fact that an application is reading a sparse file is transparent to the application. An application that is aware of sparse-files should determine whether its data set is suitable to be kept in a sparse file. After that determination is made, the application must explicitly declare a file as sparse, using the FSCTL_SET_SPARSE control code."
wRAR
As wRAR implies, NTFS supports file holes, but you have to create the explicitly with FSCTL_SET_SPARSE or by setting the file to be compressed.
Gabe
+2  A: 
void ReserveSpace(LONG spaceLow, LONG spaceHigh, HANDLE hFile)
{
    DWORD err = ::SetFilePointer(hFile, spaceLow, &spaceHigh, FILE_BEGIN);

    if (err == INVALID_SET_FILE_POINTER) {
        err = GetLastError();
        // handle error
    }
    if (!::SetEndOfFile(hFile)) {
        err = GetLastError();
        // handle error
    }
    err = ::SetFilePointer(hFile, 0, 0, FILE_BEGIN); // reset
}
plinth
Thanks. That's exactly what I wanted.
haggag
A: 

Here's a simple function that will work for files of any size:

void SetFileSize(HANDLE hFile, LARGE_INTEGER size)
{
    SetFilePointer(hFile, size, NULL, FILE_BEGIN);
    SetEndOfFile(hFile);
}
Gabe