From 9ddfa4f9c86dbc7bf50abd72a9026956d47c5288 Mon Sep 17 00:00:00 2001
From: Leonid Yuriev <leo@yuriev.ru>
Date: Tue, 27 Aug 2019 23:27:36 +0300
Subject: [PATCH] mdbx-windows: use PrefetchVirtualMemory().

---
 src/lck-windows.c | 22 ++++++++--------------
 src/mdbx.c        |  8 ++++++++
 src/osal.h        | 15 ++++++++++++---
 3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/src/lck-windows.c b/src/lck-windows.c
index fa2d684c..34a6e5a5 100644
--- a/src/lck-windows.c
+++ b/src/lck-windows.c
@@ -667,6 +667,7 @@ MDBX_GetFileInformationByHandleEx mdbx_GetFileInformationByHandleEx;
 MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW;
 MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW;
 MDBX_SetFileInformationByHandle mdbx_SetFileInformationByHandle;
+MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory;
 MDBX_NtFsControlFile mdbx_NtFsControlFile;
 
 static void mdbx_winnt_import(void) {
@@ -691,21 +692,14 @@ static void mdbx_winnt_import(void) {
     mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive;
   }
 
-  mdbx_GetFileInformationByHandleEx =
-      (MDBX_GetFileInformationByHandleEx)GetProcAddress(
-          hKernel32dll, "GetFileInformationByHandleEx");
+#define GET_KERNEL32_PROC(ENTRY)                                               \
+  mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(hKernel32dll, #ENTRY)
 
-  mdbx_GetVolumeInformationByHandleW =
-      (MDBX_GetVolumeInformationByHandleW)GetProcAddress(
-          hKernel32dll, "GetVolumeInformationByHandleW");
-
-  mdbx_GetFinalPathNameByHandleW =
-      (MDBX_GetFinalPathNameByHandleW)GetProcAddress(
-          hKernel32dll, "GetFinalPathNameByHandleW");
-
-  mdbx_SetFileInformationByHandle =
-      (MDBX_SetFileInformationByHandle)GetProcAddress(
-          hKernel32dll, "SetFileInformationByHandle");
+  GET_KERNEL32_PROC(GetFileInformationByHandleEx);
+  GET_KERNEL32_PROC(GetVolumeInformationByHandleW);
+  GET_KERNEL32_PROC(GetFinalPathNameByHandleW);
+  GET_KERNEL32_PROC(SetFileInformationByHandle);
+  GET_KERNEL32_PROC(PrefetchVirtualMemory);
 
   const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll");
   mdbx_NtFsControlFile =
diff --git a/src/mdbx.c b/src/mdbx.c
index 3d9cfb6c..6aa00d65 100644
--- a/src/mdbx.c
+++ b/src/mdbx.c
@@ -5819,6 +5819,14 @@ static int __cold mdbx_env_map(MDBX_env *env, const int is_exclusive,
     if (unlikely(rc != 0))
       return errno;
 #endif
+#if defined(_WIN32) || defined(_WIN64)
+    if (mdbx_PrefetchVirtualMemory) {
+      WIN32_MEMORY_RANGE_ENTRY hint;
+      hint.VirtualAddress = env->me_map;
+      hint.NumberOfBytes = usedsize;
+      (void)mdbx_PrefetchVirtualMemory(GetCurrentProcess(), 1, &hint, 0);
+    }
+#endif /* Windows */
   }
 
 #ifdef USE_VALGRIND
diff --git a/src/osal.h b/src/osal.h
index 80b5b0d7..4cf2695c 100644
--- a/src/osal.h
+++ b/src/osal.h
@@ -732,7 +732,6 @@ typedef BOOL(WINAPI *MDBX_GetVolumeInformationByHandleW)(
     _Out_opt_ LPDWORD lpMaximumComponentLength,
     _Out_opt_ LPDWORD lpFileSystemFlags,
     _Out_opt_ LPWSTR lpFileSystemNameBuffer, _In_ DWORD nFileSystemNameSize);
-
 extern MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW;
 
 typedef DWORD(WINAPI *MDBX_GetFinalPathNameByHandleW)(_In_ HANDLE hFile,
@@ -744,7 +743,6 @@ extern MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW;
 typedef BOOL(WINAPI *MDBX_SetFileInformationByHandle)(
     _In_ HANDLE hFile, _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
     _Out_ LPVOID lpFileInformation, _In_ DWORD dwBufferSize);
-
 extern MDBX_SetFileInformationByHandle mdbx_SetFileInformationByHandle;
 
 typedef NTSTATUS(NTAPI *MDBX_NtFsControlFile)(
@@ -753,9 +751,20 @@ typedef NTSTATUS(NTAPI *MDBX_NtFsControlFile)(
     OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FsControlCode,
     IN OUT PVOID InputBuffer, IN ULONG InputBufferLength,
     OUT OPTIONAL PVOID OutputBuffer, IN ULONG OutputBufferLength);
-
 extern MDBX_NtFsControlFile mdbx_NtFsControlFile;
 
+#ifndef _WIN32_WINNT_WIN8
+typedef struct _WIN32_MEMORY_RANGE_ENTRY {
+  PVOID VirtualAddress;
+  SIZE_T NumberOfBytes;
+} WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY;
+#endif
+
+typedef BOOL(WINAPI *MDBX_PrefetchVirtualMemory)(
+    HANDLE hProcess, ULONG_PTR NumberOfEntries,
+    PWIN32_MEMORY_RANGE_ENTRY VirtualAddresses, ULONG Flags);
+extern MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory;
+
 #endif /* Windows */
 
 /*----------------------------------------------------------------------------*/