有一个第三方库,输入参数之一是文件名,会把输出的内容写到这个文件中。我的应用程序再从这个文件中读入内容。由于这个第三方库每次产生的输出都很大,有十几兆,连续调用会产生大量的磁盘io,拖累性能。有没有办法让这个输出文件只存在于内存中,避免产生磁盘io呢?
尝试一:使用命名管道
https://github.com/msys2/MINGW-packages/issues/5903
示例
HANDLE hpipe;
char pipename[MAX_PATH];
snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\msys_example_");
hpipe = CreateNamedPipeA(pipename, PIPE_ACCESS_INBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 1024, 1024, 0, NULL);
if (hpipe == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Failed to create named pipe\n");
return 1;
}
{ // 模拟第三方库打开并写入文件
FILE* fp;
fp = fopen(pipename, "wb");
fprintf(fp, "abcd");
fclose(fp);
}
{
char buf[16];
DWORD nBytesRead;
ReadFile(hpipe, buf, 16, &nBytesRead, NULL);
}
CloseHandle(hpipe);
不过要注意的是,往pipe调用fwrite写入数据,或者fclose的时候(之前fwrite的数据要flush)可能会卡住,如果接收端没有及时取走数据,导致pipe的buffer塞满。对于要写入大量数据的情况,需要对应用进行改造,pipe的写入和读取分开到两个线程上同时进行
类似的linux下的方案
https://www.ibm.com/docs/en/zos/2.3.0?topic=io-using-named-pipes
尝试二:使用内存临时文件
https://github.com/Snaipe/fmem/blob/b73b3d8b570c2f79df5a0b071efba392a82ddcd7/src/fmem-winapi-tmpfile.c
其中的难点是 CreateFile 时的 (dwDesiredAccess, dwShareMode) 会影响影响后续打开是否成功
https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files
特别是如果带上了 FILE_FLAG_DELETE_ON_CLOSE,则要求 dwShareMode 带上 FILE_SHARE_DELETE,后续的打开也都要带上 FILE_SHARE_DELETE。而fopen等c库函数,都是不带FILE_SHARE_DELETE的。
示例
char path[MAX_PATH];
char file[MAX_PATH];
if (!GetTempPathA(sizeof(path), path))
return NULL;
if (!GetTempFileNameA(path, "test", 0, file))
return NULL;
HANDLE handle = INVALID_HANDLE_VALUE;
handle = CreateFileA(file,
FILE_GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY,
NULL);
{ // 模拟第三方库打开并写入文件
FILE* fp;
fp = fopen(file, "wb");
fprintf(fp, "abcd");
fclose(fp);
}
{
char buf[16];
FILE* fp;
fp = fopen(file, "rb");
fread(buf, 1, 16, fp);
fclose(fp);
}
CloseHandle(handle); DeleteFileA(file);
网友评论