搜索引擎之内存映射快速索引文件

来源:互联网 发布:杭州php学费多少 编辑:程序博客网 时间:2024/06/05 01:13

搜索引擎之利用内存映射快速索引文件


 
 用户在通过关键字检索信息时,如果反馈的内容在3S之内是适度范围,如果10s了一般用户就会感觉难以忍受了,所以如何提高对用户

的反馈速度就成了搜索引擎技术中一个瓶颈.

 每天都会有成千上万的网页产生并且背爬虫程序下载到服务器中存储起来,并建立了反向索引,可以想象这个索引表是一个多么大的

数据文件,用户查询时,对这么大的一个文件做搜索,并且同时可能还有N多个用户也一同在搜索同一个关键字,比如"艳照门",这样就算开辟多

个线程,有足够的多的CPU并发处理,这仍然是个难解决的问题,但Google,百度恰恰就是突破了我们这些凡人的想象,在这方面做的非常出色,

我在搜索时觉得比使用桌面搜索都要快很多.
 这里我们探讨一下该问题的解决方法,第一利用反向索引表找到多个相关文件时,要把文件中相关行用Highlight的方式显示给用户,

对于多个文件我们不可能是顺序操作,所以这里要为每一个相关文件开一个线程,这是多线程;第二索引到该文件时要去打开该文件去获取其

中关键字所在的行,这里涉及到了文件的I/O操作,但I/O操作是对硬盘的操作,是非常慢的一种方式,那么我们不能采用该方法,不打开文件直

接将文件读入内存,注意不是缓冲区,由操作系统提议管理文件缓存,不要分配任何存储,也不要将文件装入任何存储,这样才能达到速度最大

化;第三当关键字同时被多个用户所检索时,不要都去做相同的操作,而是查询当前内存中是否有相同的信息直接做内存共享,供同时刻所有用

户使用.(注:其实百度,google还使用了分页显示的方法来提高速度,这里我就不论述了)

 到这里实现快速检索的方法已经无它,唯见"多线程+存储映射"了,针对每一个文件建立一个线程将其读入内存,实现多个实例可以共

享该文件,通过反向索引表获得关键字所在的行,通过文件指针定位得到该行信息,输出,关闭该存储映射.

//All right revsered by yoki2009
//mailto:imj040144@tom.com
//Welcome to my blog:    http://blog.csdn.net/yoki2009

#include "stdafx.h"
#include "three.h"
#include "DirSearcher.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only application object


CWinApp theApp;

using namespace std;

unsigned __stdcall processFile(void* pArg)
{
 HANDLE hFile,hFileMap;
 LPVOID lpvFile;
 LPSTR lpchContent;
 DWORD dwFileSize;

 STARTUPINFO si = {0};
 /*针对多CPU使用FILE_FLAG_OVERLAPPED标志位,实现异步读文件,提高文件效率*/
 hFile = CreateFile((char *)pArg,GENERIC_ALL,0,NULL,OPEN_EXISTING,
  FILE_FLAG_OVERLAPPED,NULL);

 dwFileSize = GetFileSize(hFile,NULL);
 hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,dwFileSize,"FileMappingObject");

 if (hFileMap == NULL || hFileMap == INVALID_HANDLE_VALUE)
 {
  cout<<"Could not create file mapping object"<<GetLastError();
  return -1;
 }

 lpvFile = MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,0);
 if (NULL == lpvFile)
 {
  cout<<"Could not map view of file "<<GetLastError();
  return -1;
 }
 lpchContent = (LPSTR)lpvFile;
 lpchContent[dwFileSize] = 0;
 //print content of file
 cout<<lpvFile<<"  "<<dwFileSize<<"  "<<(char*)pArg<<endl<<lpchContent;

 UnmapViewOfFile(lpvFile);
 CloseHandle(hFileMap);

 CloseHandle(hFile);
 _endthreadex(0);
 return 0;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;

 // initialize MFC and print and error on failure
 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
  // TODO: change error code to suit your needs
  _tprintf(_T("Fatal Error: MFC initialization failed/n"));
  nRetCode = 1;
 }
 else
 {
  // TODO: code your application's behavior here.
 }
 /*
 这里应该使用从反向索引表中获得的文件,这里我用文件扫描模拟
 */
 DirSearcher *pDirSearch = DirSearcher::getInstance();
 
 pDirSearch->setDirPath("c://vs");
 pDirSearch->DoDirSearch();
 vector<CString>::iterator pos ;
 for (pos = pDirSearch->_filepath.begin(); pos != pDirSearch->_filepath.end(); ++pos)
 {
  //begin a thread
  HANDLE hThread;
  unsigned threadID;
  CString tmpName(*pos);
  hThread = (HANDLE)_beginthreadex(NULL,0,&processFile,tmpName.GetBuffer(),0,&threadID);
  WaitForSingleObject(hThread,INFINITE);
  CloseHandle(hThread);
  cout<<"/n*************************************************"<<endl;
  //end
 }


 system("PAUSE");
 return nRetCode;
}

原创粉丝点击