From 3b2a21067e9e519e57f6b760c5d3fe2cb14eca19 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Tue, 7 May 2019 11:07:19 +0100 Subject: [PATCH] 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 --- src/lib/eina/eina_file_win32.c | 64 ++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/src/lib/eina/eina_file_win32.c b/src/lib/eina/eina_file_win32.c index 7ed6d03..e10a8f5 100644 --- a/src/lib/eina/eina_file_win32.c +++ b/src/lib/eina/eina_file_win32.c @@ -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; -- 2.7.4