From e9f0a1256a3e1850f5a19bf33f44fafb05caa4e2 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 3 Mar 2015 03:39:12 +0100
Subject: ntdll: Reuse old async fileio structures if possible.

This should speed up apps which heavily rely on async io stuff. Some
tests (using the kernel and ntdll wine tests) show that it is very
often possible to reuse old fileio structures.
---
 dlls/ntdll/file.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index b07e5f9..7b6c2b9 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -332,6 +332,7 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
 struct async_fileio
 {
     struct async_fileio *next;
+    DWORD                size;
     HANDLE               handle;
     PIO_APC_ROUTINE      apc;
     void                *apc_arg;
@@ -370,17 +371,28 @@ static struct async_fileio *alloc_fileio( DWORD size, HANDLE handle, PIO_APC_ROU
 {
     /* first free remaining previous fileinfos */
 
-    struct async_fileio *io = interlocked_xchg_ptr( (void **)&fileio_freelist, NULL );
+    struct async_fileio *old_io = interlocked_xchg_ptr( (void **)&fileio_freelist, NULL );
+    struct async_fileio *io = NULL;
 
-    while (io)
+    while (old_io)
     {
-        struct async_fileio *next = io->next;
-        RtlFreeHeap( GetProcessHeap(), 0, io );
-        io = next;
+        if (!io && old_io->size >= size && old_io->size <= max(4096, 4 * size))
+        {
+            io     = old_io;
+            size   = old_io->size;
+            old_io = old_io->next;
+        }
+        else
+        {
+            struct async_fileio *next = old_io->next;
+            RtlFreeHeap( GetProcessHeap(), 0, old_io );
+            old_io = next;
+        }
     }
 
-    if ((io = RtlAllocateHeap( GetProcessHeap(), 0, size )))
+    if (io || (io = RtlAllocateHeap( GetProcessHeap(), 0, size )))
     {
+        io->size    = size;
         io->handle  = handle;
         io->apc     = apc;
         io->apc_arg = arg;
-- 
2.3.0

