DOS drive cache: Fix directory listing performance issues by deferring filename sort until after all entries have been added. [https://github.com/joncampbell123/dosbox-x/issues/5039]

This commit is contained in:
Jonathan Campbell 2024-06-16 22:35:55 -07:00
parent 0f38f55b18
commit 3ff38b6bfe
3 changed files with 11 additions and 5 deletions

View File

@ -1,4 +1,7 @@
Next:
- DOS drive cache: When listing a directory, defer the filename sort until
the entire list is built. This improves directory listing performance
in directories with many files. (joncampbell123).
- INT 10h, if instructed, will now use the video parameter table to set
standard VGA modes instead of internal logic. (joncampbell123).
- Removed erroneous VGA display compensation code for certain EGA/VGA

View File

@ -270,7 +270,7 @@ private:
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
bool RemoveSpaces (char* str);
bool OpenDir (CFileInfo* dir, const char* expand, uint16_t& id);
char* CreateEntry (CFileInfo* dir, const char* name, const char* sname, bool is_directory);
char* CreateEntry (CFileInfo* dir, const char* name, const char* sname, bool is_directory, bool skipSort=false);
void CopyEntry (CFileInfo* dir, CFileInfo* from);
uint16_t GetFreeID (CFileInfo* dir);
void Clear (void);

View File

@ -824,7 +824,7 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, uint16_t& id)
return false;
}
char* DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, const char* sname, bool is_directory) {
char* DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, const char* sname, bool is_directory, bool skipSort) {
CFileInfo* info = new CFileInfo;
strcpy(info->shortname, sname);
strcpy(info->orgname, name);
@ -835,7 +835,7 @@ char* DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, const char*
if (sname[0]==0) CreateShortName(dir, info);
// keep list sorted (so GetLongName works correctly, used by CreateShortName in this routine)
if (dir->fileList.size()>0) {
if (dir->fileList.size()>0 && !skipSort) {
if (!(strcmp(info->shortname,dir->fileList.back()->shortname)<0)) {
// append at end of list
dir->fileList.push_back(info);
@ -891,12 +891,15 @@ bool DOS_Drive_Cache::ReadDir(uint16_t id, char* &result, char * &lresult) {
char dir_name[CROSS_LEN], dir_sname[DOS_NAMELENGTH+1];
bool is_directory;
if (drive->read_directory_first(dirp, dir_name, dir_sname, is_directory)) {
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory);
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory, /*skip search*/true);
while (drive->read_directory_next(dirp, dir_name, dir_sname, is_directory)) {
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory);
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory, /*skip search*/true);
}
}
// Insertion skipped sorting, now sort in one go, which should be faster when faced with many files
std::sort(dirSearch[id]->fileList.begin(), dirSearch[id]->fileList.end(), SortByName);
// close dir
drive->closedir(dirp);