Win32: Drastically improve load times with unpacked planet/

C4Group::SearchNextEntry would waste lots of cycles looking up file
attributes that were never inspected afterwards. Since all we want is
the file size, and we already get that for free from FindFirstFile and
FindNextFile, store it with the directory iterator instead of querying
it at every iteration.

This reduces load times on my machine by almost half, tested across
several different scenarios.
qteditor
Nicolas Hake 2016-06-19 16:28:29 +02:00
parent 0ad8e15c8a
commit e490428f29
3 changed files with 21 additions and 6 deletions

View File

@ -422,7 +422,7 @@ void C4GroupEntry::Set(const DirectoryIterator &iter, const char * path)
SCopy(GetFilename(*iter),FileName,_MAX_FNAME);
SCopy(*iter, DiskPath, _MAX_PATH-1);
Size = FileSize(*iter);
Size = iter.GetFileSize();
Status=C4GRES_OnDisk;
Packed=false;
ChildGroup=false;

View File

@ -989,7 +989,10 @@ void DirectoryIterator::Read(const char *dirname)
// ...unless they're . or ..
if (file.cFileName[0] == '.' && (file.cFileName[1] == '\0' || (file.cFileName[1] == '.' && file.cFileName[2] == '\0')))
continue;
p->files.push_back(StdStrBuf(file.cFileName).getData());
size_t size = (file.nFileSizeHigh * (size_t(MAXDWORD) + 1)) + file.nFileSizeLow;
p->files.emplace_back(StdStrBuf(file.cFileName).getData(), size);
}
while (FindNextFileW(fh, &file));
FindClose(fh);
@ -1016,14 +1019,14 @@ void DirectoryIterator::Read(const char *dirname)
// ...unless they're . or ..
if (file->d_name[0] == '.' && (file->d_name[1] == '\0' || (file->d_name[1] == '.' && file->d_name[2] == '\0')))
continue;
p->files.push_back(file->d_name);
p->files.emplace_back(file->d_name, 0);
}
closedir(fh);
#endif
// Sort list
std::sort(p->files.begin(), p->files.end());
for (FileList::iterator it = p->files.begin(); it != p->files.end(); ++it)
it->insert(0, search_path); // prepend path to all file entries
it->first.insert(0, search_path); // prepend path to all file entries
iter = p->files.begin();
p->directory = dirname;
}
@ -1039,7 +1042,7 @@ const char * DirectoryIterator::operator*() const
{
if (iter == p->files.end())
return NULL;
return iter->c_str();
return iter->first.c_str();
}
DirectoryIterator DirectoryIterator::operator++(int)
{
@ -1048,6 +1051,15 @@ DirectoryIterator DirectoryIterator::operator++(int)
return tmp;
}
size_t DirectoryIterator::GetFileSize() const
{
#ifdef _WIN32
return iter->second;
#else
return FileSize(iter->first.c_str());
#endif
}
int ForEachFile(const char *szDirName, bool (*fnCallback)(const char *))
{
if (!szDirName || !fnCallback)

View File

@ -94,6 +94,9 @@ public:
~DirectoryIterator();
const char * operator * () const;
const char *GetName() const { return **this; }
size_t GetFileSize() const;
DirectoryIterator& operator ++ ();
DirectoryIterator operator ++ (int);
void Clear(); // put iterator into empty state and clear any cached directory listing
@ -102,7 +105,7 @@ public:
private:
void Read(const char *dirname);
friend struct DirectoryIteratorP;
typedef std::vector<std::string> FileList;
typedef std::vector<std::pair<std::string, size_t>> FileList;
DirectoryIteratorP *p;
FileList::iterator iter;
};