Click here to Skip to main content
Click here to Skip to main content

Tagged as

Improve responsiveness in Windows with the FILE_FLAG_NO_BUFFERING wrapper

, 9 Mar 2010 Public Domain
Rate this:
Please Sign up or sign in to vote.
Avoid swapping out valuable file system cache of other applications when accessing large files that you know are not accessed again later.

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 Smile | :)

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:

// #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

Share

About the Author

rlasse
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 Pinmembertoddma6-Dec-12 4:32 
QuestionWill this work in C++ in Visual Studio 10? (unicode) [modified] Pinmembertoddma9-Nov-12 6:18 
Question[My vote of 1] Icky Code PinmemberMember 799059123-Apr-12 13:00 
GeneralSome remarks [modified] Pinmemberyarp9-Mar-10 20:41 
GeneralOdd file sizes Pinmembersupercat99-Mar-10 10:22 
GeneralRe: Odd file sizes Pinmemberyarp9-Mar-10 20:27 
GeneralNew version Pinmemberrlasse9-Mar-10 9:48 
GeneralSystem memory leak PinmemberMember 40209953-Mar-10 5:03 
GeneralRe: System memory leak Pinmemberrlasse3-Mar-10 6:17 
GeneralQuestions Pinmemberhector santos23-Jan-10 1:38 
GeneralRe: Questions Pinmemberrlasse23-Jan-10 2:54 
GeneralRe: Questions Pinmemberhector santos23-Jan-10 4:28 
GeneralRe: Questions Pinmemberrlasse23-Jan-10 9:22 
GeneralRe: Questions Pinmemberhector santos25-Jan-10 14:21 
GeneralRe: Questions Pinmemberrprep12-Aug-11 9:52 
GeneralBug [modified] Pinmemberrlasse13-Jan-10 10:33 
GeneralRe: Bug Pinmemberkonikula18-Jan-10 21:56 
GeneralSparse files Pinmemberyafan12-Jan-10 4:24 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.1 | Last Updated 9 Mar 2010
Article Copyright 2010 by rlasse
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid