Click here to Skip to main content
15,868,070 members
Articles / Programming Languages / C++

Improve responsiveness in Windows with the FILE_FLAG_NO_BUFFERING wrapper

Rate me:
Please Sign up or sign in to vote.
4.61/5 (12 votes)
9 Mar 2010Public Domain3 min read 62K   1.1K   22   18
Avoid swapping out valuable file system cache of other applications when accessing large files that you know are not accessed again later.

Image 1

Introduction

When you read or write large files, valuable file system cache from other applications is being swapped out. This is not wanted if you know that your files are not going to be accessed again afterwards.

As a result, most people have experienced copying a large file where after all applications feel slow and unresponsive for a period of time until they have recached. Especially on servers that need low latency, this can be a really large problem.

Start a trend and use this wrapper to improve the all-over responsiveness of Windows :-)

This Library

The only method to prevent swapping out cache is to open files with the FILE_FLAG_NO_BUFFERING flag. This, however, requires disk I/O requests to have sizes divisible by sector size (512 to 4096 bytes), which would require large rewrites of most applications that rely on being able to request different sizes.

This project contains a drop-in wrapper that offers the CreateFile_NB(), ReadFile_NB(), WriteFile_NB(), and CloseHandle_NB() functions that take care of queuing and adjusting the file size when closing a file opened for writing.

Note that the FILE_FLAG_WRITE_THROUGH and FILE_FLAG_SEQUENTIAL_SCAN flags would not solve the above mentioned problem; while data is committed immediately, a cached copy is still kept in memory.

Experiment

To illustrate the problem, start your Task Manager (the one at Ctrl + Alt + Del) and watch the Cached value in the Physical Memory area. Before our experiments, we need to invalidate as much cache as possible. Unfortunately, this is not easy on Windows. While the famous sfc /purgecache command commits all cache, it does not invalidate it. Do the following:

  1. Disable the ReadyBoost, SuperFetch, Readydrive, and SearchIndexer services. Especially SuperFetch is important because it fills up the cache at boot.
  2. Restart the computer. Simply logging off and on does not invalidate the cache and is not enough.

You should now see something like the image at the top of the article - the cache value is 14 MB, which is low and good.

Now, load the io.sln Visual Studio 2008 project. You will see the following lines in demo.c:

C++
// #define NORMAL // Comment away this to make it use unbuffered disk I/O
_TCHAR large_file[] = _T("d:\\database.mdf");

Let large_file point to a file which is larger than your physical memory, leave the comment at the #define NORMAL flag as it is, and run the program. It reads the file into memory in chunks. Observe that the Cached value does not increase while running.

Now, uncomment the #define NORMAL flag and run it again. Observe that the Cached value increases. The same would happen if you had copied files on the command line or simply used the computer normally for a period of time.

Using the Code

Simply #include unbuf.h and unbuf.c in your project and append _UB to the function names of CreateFile(), ReadFile(), WriteFile(), and CloseHandle().

Do this for file accesses that have a significant amount of data and that you know are not accessed later by the user or by the application. This wrapper has certain limitations:

  • Files cannot be opened with both GENERIC_READ and GENERIC_WRITE at the same time.
  • The lpOverlapped parameter to CreateFile() is ignored.
  • Seeking (SetFilePointer()) is not yet supported.

Last but not least, it may not mimic the original functions perfectly in detail yet which could make it fail in certain applications. Please give it a good testing and let me know any compatibility issues or improvements that you may find. I will follow this forum closely the next weeks, to follow up.

History

  • 12-Jan-2010: First release.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
QuickLZ
Denmark Denmark
QuickLZ - world's fastest data compression library (really), for C, C# and Java!

qpress - world's fastest file archiver (really), for Linux, Windows, MacOS, Solaris, etc. Way too fast for your storage system!

http://www.quicklz.com

Comments and Discussions

 
QuestionSeek needed Pin
toddma6-Dec-12 4:32
toddma6-Dec-12 4:32 
QuestionWill this work in C++ in Visual Studio 10? (unicode) Pin
toddma9-Nov-12 6:18
toddma9-Nov-12 6:18 
Question[My vote of 1] Icky Code Pin
Member 799059123-Apr-12 13:00
Member 799059123-Apr-12 13:00 
GeneralSome remarks [modified] Pin
yarp9-Mar-10 20:41
yarp9-Mar-10 20:41 
GeneralOdd file sizes Pin
supercat99-Mar-10 10:22
supercat99-Mar-10 10:22 
GeneralRe: Odd file sizes Pin
yarp9-Mar-10 20:27
yarp9-Mar-10 20:27 
GeneralNew version Pin
rlasse9-Mar-10 9:48
rlasse9-Mar-10 9:48 
GeneralSystem memory leak Pin
Zoylamb3-Mar-10 5:03
Zoylamb3-Mar-10 5:03 
GeneralRe: System memory leak Pin
rlasse3-Mar-10 6:17
rlasse3-Mar-10 6:17 
GeneralQuestions Pin
hector santos23-Jan-10 1:38
hector santos23-Jan-10 1:38 
GeneralRe: Questions Pin
rlasse23-Jan-10 2:54
rlasse23-Jan-10 2:54 
GeneralRe: Questions Pin
hector santos23-Jan-10 4:28
hector santos23-Jan-10 4:28 
GeneralRe: Questions Pin
rlasse23-Jan-10 9:22
rlasse23-Jan-10 9:22 
GeneralRe: Questions Pin
hector santos25-Jan-10 14:21
hector santos25-Jan-10 14:21 
GeneralRe: Questions Pin
rprep12-Aug-11 9:52
rprep12-Aug-11 9:52 
GeneralBug [modified] Pin
rlasse13-Jan-10 10:33
rlasse13-Jan-10 10:33 
GeneralRe: Bug Pin
konikula18-Jan-10 21:56
konikula18-Jan-10 21:56 
GeneralSparse files Pin
yafan12-Jan-10 4:24
yafan12-Jan-10 4:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.