[commit] r1107 - trunk/GME/Core

GMESRC Repository Notifications gme-commit at list.isis.vanderbilt.edu
Wed Dec 22 16:19:42 CST 2010


Author: ksmyth
Date: Wed Dec 22 16:19:42 2010
New Revision: 1107

Log:
Memory map input file instead of slow double-buffered ifstream. Speedup of 44% for Open()ing a 25MB file. TODO: Save()

Modified:
   trunk/GME/Core/CoreBinFile.cpp
   trunk/GME/Core/CoreBinFile.h

Modified: trunk/GME/Core/CoreBinFile.cpp
==============================================================================
--- trunk/GME/Core/CoreBinFile.cpp	Fri Dec  3 10:19:00 2010	(r1106)
+++ trunk/GME/Core/CoreBinFile.cpp	Wed Dec 22 16:19:42 2010	(r1107)
@@ -52,6 +52,7 @@
 		HR_THROW(E_METAPROJECT);
 	}
 
+	// FIXME: can't take this if branch (is nothrow new intended?)
 	if( binattr == NULL )
 		HR_THROW(E_OUTOFMEMORY);
 
@@ -524,12 +525,9 @@
 
 void CCoreBinFile::read(bindata &b)
 {
-	ASSERT( ifs.is_open() );
-
 	int len;
 	
 	read(len);
-	if(ifs.eof()) COMTHROW(E_FILEOPEN);
 	ASSERT( len >= 0 );
 
 	try {
@@ -538,14 +536,17 @@
 		// KMS: could get here if the project is corrupt and len is incorrect
 		COMTHROW(E_OUTOFMEMORY);
 	}
-	if( len > 0 )
-		ifs.read( (char *) &b[0], len);
+	if( len > 0 ) {
+		if (len > cifs_eof - cifs) {
+			HR_THROW(E_FILEOPEN);
+		}
+		memcpy(&b[0], cifs, len);
+		cifs += len;
+	}
 }
 
 void CCoreBinFile::read(CComBstrObj &ss)
 {
-	ASSERT( ifs.is_open() );
-
 	std::string s;
 
 	int len;
@@ -554,8 +555,14 @@
 	ASSERT( len >= 0 );
 
 	s.resize(len);
-	if( len > 0 )
-		ifs.read( (char *) &s[0], len);
+	if( len > 0 ) {
+		if (len > cifs_eof - cifs) {
+			HR_THROW(E_FILEOPEN);
+		}
+		memcpy(&s[0], cifs, len);
+		cifs += len;
+	}
+
 
 	CopyTo(s, ss);
 }
@@ -769,8 +776,8 @@
 {
 	CloseMetaObject();
 
-	if( ifs.is_open() )
-		ifs.close();
+	cifs = 0;
+	cifs_eof = 0;
 
 	if( ofs.is_open() )
 		ofs.close();
@@ -833,9 +840,13 @@
 {
 	InitMaxObjIDs();
 
-	ifs.open(filename.c_str(), std::ios::in | std::ios::binary);//previously ios::nocreate had been used but no file is created if opened for read only
-	if( ifs.fail() )
-		HR_THROW(E_FILEOPEN);
+	{
+	membuf file_buffer;
+	if (file_buffer.open(filename.c_str()) != 0) {
+		HR_THROW(HRESULT_FROM_WIN32(GetLastError()));
+	}
+	cifs = file_buffer.getBegin();
+	cifs_eof = file_buffer.getEnd();
 
 	bindata guid;
 	read(guid);
@@ -915,8 +926,8 @@
 
 	isEmpty = true;
 	resolvelist.clear();
+	}
 
-	ifs.close();
 	ofs.clear();
 	ofs.open(filename.c_str(), std::ios::app | std::ios::binary);
 	read_only = false;

Modified: trunk/GME/Core/CoreBinFile.h
==============================================================================
--- trunk/GME/Core/CoreBinFile.h	Fri Dec  3 10:19:00 2010	(r1106)
+++ trunk/GME/Core/CoreBinFile.h	Wed Dec 22 16:19:42 2010	(r1107)
@@ -8,6 +8,56 @@
 #include <vector>
 #include <algorithm>
 
+#include "windows.h"
+class membuf
+{
+	public:
+	membuf() : 
+		begin(0), end(0), hFile(INVALID_HANDLE_VALUE), hFileMappingObject(INVALID_HANDLE_VALUE)
+		{ }
+	
+	int open(const char* filename) {
+		hFile = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+		if (hFile == INVALID_HANDLE_VALUE) {
+			return 1;
+		}
+		hFileMappingObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+		if (hFileMappingObject == INVALID_HANDLE_VALUE) {
+			return 1;
+		}
+		begin = (char*)MapViewOfFile(hFileMappingObject, FILE_MAP_READ, 0, 0, 0);
+		if (begin == 0) {
+			return 1;
+		}
+		DWORD filesize = GetFileSize(hFile, NULL);
+		if (filesize == INVALID_FILE_SIZE) {
+			return 1;
+		}
+		end = begin + filesize;
+		return 0;
+	}
+
+	~membuf() {
+		UnmapViewOfFile(begin);
+		CloseHandle(hFileMappingObject);
+		CloseHandle(hFile);
+	}
+
+	char* getBegin() const {
+		return begin;
+	}
+	char* getEnd() const {
+		return end;
+	}
+
+	private:
+		membuf(const membuf&);
+		membuf& operator=(const membuf&);
+
+		HANDLE hFile,hFileMappingObject;
+		char* begin, * end;
+};
+
 class CCoreBinFile;
 
 // --------------------------- BinAttr
@@ -143,15 +193,18 @@
 // ------- Ios
 
 public:
-	std::ifstream ifs;
+	char* cifs;
+	char* cifs_eof;
+
 	std::ofstream ofs;
 
 public:
-	void read(unsigned char &a) { ifs.read((char*)&a, sizeof(char)); }
-	void read(short &a) { ifs.read((char*)&a, sizeof(short)); }
-	void read(int &a) { ifs.read((char*)&a, sizeof(int)); }
-	void read(long &a)  { ifs.read((char*)&a, sizeof(long)); }
-	void read(double &a)  { ifs.read((char*)&a, sizeof(double)); }
+#define CoreBinFile_read(a, size) if (size > cifs_eof - cifs) HR_THROW(E_FILEOPEN); memcpy(&a, cifs, size); cifs += size;
+	void read(unsigned char &a) { CoreBinFile_read(a, sizeof(unsigned char)); }
+	void read(short &a) { CoreBinFile_read(a, sizeof(short)); }
+	void read(int &a) { CoreBinFile_read(a, sizeof(int)); }
+	void read(long &a)  { CoreBinFile_read(a, sizeof(long)); }
+	void read(double &a)  { CoreBinFile_read(a, sizeof(double)); }
 	void read(CComBstrObj &a);
 	void read(bindata &a);
 


More information about the gme-commit mailing list