MDEV-32228 speedup opening tablespaces on Windows

is_file_on_ssd() is more expensive than it should be.
It caches the results by volume name, but still calls GetVolumePathName()
every time, which, as procmon shows, opens multiple directories in
filesystem hierarchy (db directory, datadir, and all ancestors)

The fix is to cache SSD status by volume serial ID, which is cheap to
retrieve with GetFileInformationByHandleEx()
This commit is contained in:
Vladislav Vaintroub 2023-09-22 12:11:57 +02:00
parent 89a493d64c
commit 1ee0d09a2b

View File

@ -7358,36 +7358,40 @@ static bool is_volume_on_ssd(const char *volume_mount_point)
} }
#include <unordered_map> #include <unordered_map>
static bool is_file_on_ssd(char *file_path) static bool is_path_on_ssd(char *file_path)
{ {
/* Cache of volume_path => volume_info, protected by rwlock.*/
static std::unordered_map<std::string, bool> cache;
static SRWLOCK lock= SRWLOCK_INIT;
/* Preset result, in case something fails, e.g we're on network drive.*/ /* Preset result, in case something fails, e.g we're on network drive.*/
char volume_path[MAX_PATH]; char volume_path[MAX_PATH];
if (!GetVolumePathName(file_path, volume_path, array_elements(volume_path))) if (!GetVolumePathName(file_path, volume_path, array_elements(volume_path)))
return false; return false;
return is_volume_on_ssd(volume_path);
}
/* Try cached volume info first.*/ static bool is_file_on_ssd(HANDLE handle, char *file_path)
std::string volume_path_str(volume_path); {
ULONGLONG volume_serial_number;
FILE_ID_INFO info;
if(!GetFileInformationByHandleEx(handle, FileIdInfo, &info, sizeof(info)))
return false;
volume_serial_number= info.VolumeSerialNumber;
static std::unordered_map<ULONGLONG, bool> cache;
static SRWLOCK lock= SRWLOCK_INIT;
bool found; bool found;
bool result; bool result;
AcquireSRWLockShared(&lock); AcquireSRWLockShared(&lock);
auto e= cache.find(volume_path_str); auto e= cache.find(volume_serial_number);
if ((found= e != cache.end())) if ((found= e != cache.end()))
result= e->second; result= e->second;
ReleaseSRWLockShared(&lock); ReleaseSRWLockShared(&lock);
if (!found)
if (found) {
return result; result= is_path_on_ssd(file_path);
/* Update cache */
result= is_volume_on_ssd(volume_path); AcquireSRWLockExclusive(&lock);
cache[volume_serial_number]= result;
/* Update cache */ ReleaseSRWLockExclusive(&lock);
AcquireSRWLockExclusive(&lock); }
cache[volume_path_str]= result;
ReleaseSRWLockExclusive(&lock);
return result; return result;
} }
@ -7427,7 +7431,7 @@ void fil_node_t::find_metadata(os_file_t file
space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT; || space->purpose == FIL_TYPE_IMPORT;
#ifdef _WIN32 #ifdef _WIN32
on_ssd = is_file_on_ssd(name); on_ssd = is_file_on_ssd(file, name);
FILE_STORAGE_INFO info; FILE_STORAGE_INFO info;
if (GetFileInformationByHandleEx( if (GetFileInformationByHandleEx(
file, FileStorageInfo, &info, sizeof(info))) { file, FileStorageInfo, &info, sizeof(info))) {