是否有批处理命令或强制Windows缓存该文件的东西?我正在尝试创建一个游戏预加载器,在开始游戏之前将某些游戏文件加载到缓存中。我有什么方法可以做到这一点吗?
更新了主要代码:
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;
}
答案 0 :(得分:12)
您需要做的就是加载文件,使用ReadFile
或通过内存映射文件并触摸每个页面(事实上,由于每16页的分配粒度就足够了,但理论上你应该触摸每一页)
内存映射速度更快,对缓存更友好,因为您不需要分配额外的内存来保存数据(您不会将其用于任何有用的内容!)。操作系统将为缓存和进程可以看到的虚拟内存重用相同的物理内存。
包括Microsoft Office和Adobe Reader在内的几个主流应用程序正好能够更快地启动。这是“延迟启动”服务,让您的硬盘在登录后闪烁十几秒钟。
请注意,虽然您可以强制Windows 1 以这种方式缓存文件,但无法强制保持缓存中的文件不确定。如果没有足够的可用物理RAM,系统将丢弃缓存内容以满足应用程序需求。
编辑:使用文件映射的最低工作示例实现:
#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;
}
程序将尝试预取命令行上给出的任何文件名
代码不是很漂亮,但它的工作原理。它使用ANSI文件名,泄漏文件句柄以防打开成功但映射失败(但是......它不是真的一个问题,操作系统将在程序退出后清理 - 如果这令人烦恼你,用RAII包裹把手)。它也仅限于ca. 1.8GiB文件大小是由于32位版本中的地址空间造成的,否则由于GetFileSize
而限制为4GiB,但如果您确实需要那么大的文件,这也很容易修复。
而不是volatile
可能想要返回或以其他方式使用“结果”,但两种方式都有效(volatile
与磁盘访问相比,对性能没有真正的可测量影响!)。
<小时/> 1 说实话,你实际上无法强制使用Windows,但除非你明确要求无缓冲的I / O,否则它总是以这种方式工作。 从理论上讲,你可以迫使操作系统将页面读入内存,甚至通过锁定内存强制它将它们保存在RAM中,但是你的工作集配额(非常小,你需要管理权限)修改它)通常不会让你这样做。这是一件好事,因为锁定大量内存是一个非常糟糕的主意。