eina_file: speed up listing of directories on Windows

Summary:
forbid the creation of short name (legacy of DOS)

Without optimisation

1. using only Win32 API, just iterating over directories (in micro seconds) :
  10 files : 47
  1000 files : 270
  100000 files : 73227
2. using eina_file_dir_list() with a callback which does nothing :
  10 files : 53
  1000 files : 265
  100000 files : 69624

usually there is a small overhead for eina API, which is normal

With optimisation

1. using only Win32 API, just iterating over directories (in micro seconds) :
  10 files : 51
  1000 files : 256
  100000 files : 33345
2. using eina_file_dir_list() with a callback which does nothing :
  10 files : 53
  1000 files : 251
  100000 files : 33832

speed up with 1000 files and more. Twice faster with 100000 files

Test Plan: benchmark program

Reviewers: raster, cedric, zmike

Subscribers: #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D8842
This commit is contained in:
Vincent Torri 2019-05-07 11:07:19 +01:00 committed by Carsten Haitzler (Rasterman)
parent 6d78454142
commit 770cede2bf
1 changed files with 21 additions and 43 deletions

View File

@ -117,39 +117,32 @@ _eina_file_win32_is_dir(const char *dir)
return EINA_TRUE;
}
static char *
_eina_file_win32_dir_new(const char *dir)
{
char *new_dir;
size_t length;
length = strlen(dir);
new_dir = (char *)malloc(sizeof(char) * length + 5);
if (!new_dir)
return NULL;
memcpy(new_dir, dir, length);
memcpy(new_dir + length, "\\*.*", 5);
return new_dir;
}
static HANDLE
_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd)
{
HANDLE h;
char buf[4096];
HANDLE h;
size_t l = strlen(dir);
#ifdef UNICODE
wchar_t *wdir = NULL;
#endif
wdir = evil_char_to_wchar(dir);
l = strlen(dir);
if ((l + 5) > sizeof(buf))
return INVALID_HANDLE_VALUE;
memcpy(buf, dir, l);
memcpy(buf + l, "\\*.*", 5);
#ifdef UNICODE
wdir = evil_char_to_wchar(buf);
if (!wdir)
return INVALID_HANDLE_VALUE;
h = FindFirstFile(wdir, fd);
h = FindFirstFileEx(wdir, FindExInfoBasic, fd, FindExSearchNameMatch, NULL, 0);
free(wdir);
#else
h = FindFirstFile(dir, fd);
h = FindFirstFileEx(buf, FindExInfoBasic, fd, FindExSearchNameMatch, NULL, 0);
#endif
if (!h)
@ -469,7 +462,6 @@ eina_file_dir_list(const char *dir,
{
WIN32_FIND_DATA file;
HANDLE h;
char *new_dir;
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE);
@ -478,11 +470,7 @@ eina_file_dir_list(const char *dir,
if (!_eina_file_win32_is_dir(dir))
return EINA_FALSE;
new_dir = _eina_file_win32_dir_new(dir);
if (!new_dir)
return EINA_FALSE;
h = _eina_file_win32_first_file(new_dir, &file);
h = _eina_file_win32_first_file(dir, &file);
if (h == INVALID_HANDLE_VALUE)
return EINA_FALSE;
@ -496,7 +484,9 @@ eina_file_dir_list(const char *dir,
# else
filename = file.cFileName;
# endif /* ! UNICODE */
if (!strcmp(filename, ".") || !strcmp(filename, ".."))
if ((filename[0] == '.') &&
((filename[1] == '\0') ||
((filename[1] == '.') && (filename[2] == '\0'))))
continue;
cb(filename, dir, data);
@ -563,7 +553,6 @@ EAPI Eina_Iterator *
eina_file_ls(const char *dir)
{
Eina_File_Iterator *it;
char *new_dir;
size_t length;
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
@ -582,12 +571,7 @@ eina_file_ls(const char *dir)
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
new_dir = _eina_file_win32_dir_new(dir);
if (!new_dir)
goto free_it;
it->handle = _eina_file_win32_first_file(new_dir, &it->data);
free(new_dir);
it->handle = _eina_file_win32_first_file(dir, &it->data);
if ((it->handle == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_NO_MORE_FILES))
goto free_it;
@ -614,7 +598,6 @@ EAPI Eina_Iterator *
eina_file_direct_ls(const char *dir)
{
Eina_File_Direct_Iterator *it;
char *new_dir;
size_t length;
EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
@ -633,12 +616,7 @@ eina_file_direct_ls(const char *dir)
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
new_dir = _eina_file_win32_dir_new(dir);
if (!new_dir)
goto free_it;
it->handle = _eina_file_win32_first_file(new_dir, &it->data);
free(new_dir);
it->handle = _eina_file_win32_first_file(dir, &it->data);
if ((it->handle == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_NO_MORE_FILES))
goto free_it;