Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to force windows to cache a file?

Is there like batch command or something that will force windows to cache that file? I am trying to create a game preloader that loads certain game files into cache before starting the game. Is there any way I can do this?

updated int main code:

int main(int argc, const char** argv)
{
if(argc >= 2) for(int i = 1; argv[i]; ++i) pf("C:\\Games\World_of_Tanks\res\packages\gui.pkg"[i]);
return 0;
}
like image 861
user1808010 Avatar asked Nov 07 '13 00:11

user1808010


People also ask

How do I enable automatic caching?

Right-click the drive on which you want to turn disk write caching on or off, and then click Properties. Click the Policies tab. Click to select or clear the Enable write caching on the disk check box as appropriate. Click OK.

Does Windows have a file cache?

By default, Windows caches file data that is read from disks and written to disks. This implies that read operations read file data from an area in system memory known as the system file cache, rather than from the physical disk.

Does Windows cache files in RAM?

The system file cache consumes most of the physical RAM.

How do I run a cache file?

Go to Settings > System > Storage > Configure Storage Sense or run it now > Clean. Where are my Windows app cache files? Most temporary files are stored in the Windows Temp folder. Although the location varies by computer and even by user, you can access it using the Run dialog.


1 Answers

All you need to do is load the files, either using ReadFile or by memory mapping the files and touching every page (in fact, due to allocation granularity every 16th page suffices, but in theory you should be touching every page).
Memory mapping is faster and more cache-friendly, since you do not need to allocate extra memory to hold the data (which you aren't going to use for anything useful!). The OS will reuse the same physical memory for the cache and for the virtual memory that your process can see.

Several mainstream applications, including Microsoft Office and Adobe Reader do exactly that to launch faster. It's those "delayed start" services that keep your harddisk light flashing for a dozen seconds after you log in.

Do note, however, that while you can force Windows1 to cache files that way, but you cannot force it to keep the files in the cache indefinitively. If there is not enough physical RAM available, the system will throw away cache contents in order to satisfy application demands.

EDIT: Minimum working example implementation using filemapping:

#include <windows.h>
#include <cstdio>

void pf(const char* name)
{
    HANDLE file = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(file == INVALID_HANDLE_VALUE) { printf("couldn't open %s\n", name); return; };

    unsigned int len  = GetFileSize(file, 0);

    HANDLE mapping  = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
    if(mapping == 0) { printf("couldn't map %s\n", name); return; }

    const char* data = (const char*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);

    if(data)
    {
        printf("prefetching %s... ", name);

        // need volatile or need to use result - compiler will otherwise optimize out whole loop
        volatile unsigned int touch = 0;

        for(unsigned int i = 0; i < len; i += 4096)
            touch += data[i];
    }
    else
        printf("couldn't create view of %s\n", name);

    UnmapViewOfFile(data);
    CloseHandle(mapping);
    CloseHandle(file);
}

int main(int argc, const char** argv)
{
    if(argc >= 2) for(int i = 1; argv[i]; ++i) pf(argv[i]);
    return 0;
}

The program will try to prefetch any filename given on the commandline.
The code isn't overly pretty but it works. It uses ANSI filenames, and leaks a file handle in case opening succeeds but mapping fails (but bleh... it's not really a problem, the OS will clean up after the program exits -- if that annoys you, wrap the handles in RAII). It's also limited to ca. 1.8GiB file size due to address space in a 32-bit build, otherwise limited to 4GiB due to GetFileSize, but that's also trivial to fix if you really need that big a file.
Instead of volatile one might want to return or otherwise consume the "result", but either way works (volatile does not truly have a measurable impact on performance, compared to a disk access!).


1Truth being told, you actually can't force Windows, but it incidentially always works that way unless you explicitly request unbuffered I/O.
In theory, you could force the OS to read pages into memory and even force it to keep them in RAM by locking the memory, but your working set quota (wich is very small, and you need aministrative rights to modify it) will not normally let you do this. That's a good thing though, since locking large amounts of memory is a very bad idea.
like image 79
Damon Avatar answered Oct 21 '22 03:10

Damon