fread 및 메모리 매핑된 읽기 바이너리 파일

결론 먼저 : 두 가지 읽기 방법의 시간 소모는 거의 동일합니다.
fread를 사용하여 1.4G 바이너리 파일을 읽을 때 약 7초가 걸립니다. 동일한 데이터를 다시 읽을 때 오버헤드 시간은 1초 미만입니다. 따라서 여기에서 메모리 맵으로 읽어보고 fread 방법과 비교하십시오.
1.
fread로 읽기 fread로 바이너리 파일을 읽는 단계는 매우 간단합니다. 파일을 열고 읽으면 됩니다.
다음과 같이 구현됩니다.

FILE* pFile = fopen("D:\\0TestData\\A.dat", "rb+");
if (pFile == NULL)
{
    
    
	printf("文件不存在\n");
	return ;
}
fseek(pFile, 56, 0);
fread(m_src, file_size, 1, pFile);
fclose(pFile);

2. 메모리 매핑된 읽기
메모리 매핑을 사용하여 읽는 단계는 다음과 같습니다.

1)调用CreateFile函数打开想要映射的文件,得到文件句柄hFile。2)调用CreateFileMapping函数,并传入文件句柄hFile,为该文件创建一个内存映射内核对象,得到内存映射文件的句柄hMap。3)调用MapViewOfFile函数映射整个文件或一部分到进程的虚拟地址空间。该函数返回文件映射到内存后的起始地址。使用指向这个地址的指针就可以读取文件的内容了。4)调用UnmapViewOfFile函数来解除文件映射。5)调用CloseHandle函数关闭文件对象,必须传入内存映射文件句柄hMap6)调用CloseHandle函数关闭文件对象,必须传入文件句柄hFile。

전체 코드 구현은 다음과 같습니다.

#include <windows.h>
#include <iostream>
#include<ctime>
#pragma warning(disable:4996)
void readFile1()
{
    
    
	size_t file_size = 1513881600;
	unsigned short* m_src = (unsigned short*)::malloc(file_size);
	//16位无符号型[0,65535]
	FILE* pFile = fopen("D:\\0TestData\\A.dat", "rb+");
	if (pFile == NULL)
	{
    
    
		printf("文件不存在\n");
		return ;
	}
	fseek(pFile, 56, 0);
	fread(m_src, file_size, 1, pFile);
	fclose(pFile);
	free(m_src);
}
int readFile2()
{
    
    
	HANDLE hFile = ::CreateFile("D:\\0TestData\\A.dat",
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 1;

	do
	{
    
    

		size_t file_size = 1513881656;
		HANDLE map_file = ::CreateFileMapping(hFile,
			nullptr,
			PAGE_READONLY,
			0,
			0,
			nullptr);
		if (map_file == nullptr)
			break;

		do
		{
    
    
			LPVOID pMap = ::MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
			if (pMap == nullptr)
				break;

			unsigned short* buf = (unsigned short*)::malloc(file_size);
			if (buf)
			{
    
    
				memcpy(buf, pMap, file_size);
				//std::cout << buf[2] << std::endl;
				::free(buf);
			}

			::UnmapViewOfFile(pMap);
		} while (0);

		::CloseHandle(map_file);
	} while (0);

	::CloseHandle(hFile);
}
int main()
{
    
    
	clock_t startTime, endTime;
	//fread读取
	startTime = clock();
	readFile1();
	endTime = clock();
	std::cout << "The total run time1 is:  " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl;
	//内存映射读取
	startTime = clock();
	readFile2();
	endTime = clock();
	std::cout << "The total run time2 is:  " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl;

	system("pause");
	return 0;
}

위 프로그램을 실행한 결과는 다음과 같습니다.

The total run time1 is:  7.752s
The total run time2 is:  0.936s

이 결과를 보고 메모리 매핑의 빠른 읽기 속도라고 생각했습니다. 추가 확인을 위해 데이터 파일을 교체하여 따로 실행해 보았는데, 두 읽기 방식이 거의 동일한 것을 확인했습니다. 또한 같은 파일을 읽을 때 한 번 읽은 후에는 읽기 시간이 크게 단축되는데 이는 데이터를 캐시에 넣기 때문일 것입니다. 이와 관련하여 여러 세트의 데이터를 실행한 후 CPU의 캐시가 증가하고 있음을 확인했습니다.
여기에 이미지 설명 삽입

참고 문헌:
[1] 메모리 매핑은 파일의 빠른 읽기를 실현합니다.
[2] C++에서 메모리 매핑 기술 사용

Supongo que te gusta

Origin blog.csdn.net/qq_44924694/article/details/130075110
Recomendado
Clasificación