Use lookaside lists for two most common allocation sizes (mbuf and data buffer)
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/event.c
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c

Modified: trunk/reactos/drivers/lib/ip/transport/tcp/event.c
--- trunk/reactos/drivers/lib/ip/transport/tcp/event.c	2006-01-02 20:04:19 UTC (rev 20535)
+++ trunk/reactos/drivers/lib/ip/transport/tcp/event.c	2006-01-02 20:26:03 UTC (rev 20536)
@@ -108,19 +108,6 @@
     else return 0;
 }
 
-void *TCPMalloc( void *ClientData,
-		 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
-    void *v = PoolAllocateBuffer( Bytes );
-    if( v ) TrackWithTag( FOURCC('f','b','s','d'), v, (PCHAR)File, Line );
-    return v;
-}
-
-void TCPFree( void *ClientData,
-	      void *data, OSK_PCHAR File, OSK_UINT Line ) {
-    UntrackFL( (PCHAR)File, Line, data );
-    PoolFreeBuffer( data );
-}
-
 int TCPSleep( void *ClientData, void *token, int priority, char *msg,
 	      int tmio ) {
     PSLEEPING_THREAD SleepingThread;
@@ -172,3 +159,149 @@
     }
     TcpipReleaseFastMutex( &SleepingThreadsLock );
 }
+
+/* Memory management routines
+ *
+ * By far the most requests for memory are either for 128 or 2048 byte blocks,
+ * so we want to satisfy those from lookaside lists. Unfortunately, the
+ * TCPFree() function doesn't pass the size of the block to be freed, so we
+ * need to keep track of it ourselves. We do it by prepending each block with
+ * 4 bytes, indicating if this is a 'L'arge (2048), 'S'mall (128) or 'O'ther
+ * block.
+ */
+
+/* Set to some non-zero value to get a profile of memory allocation sizes */
+#define MEM_PROFILE 0
+
+#define SMALL_SIZE 128
+#define LARGE_SIZE 2048
+
+#define SIGNATURE_LARGE TAG('L','L','L','L')
+#define SIGNATURE_SMALL TAG('S','S','S','S')
+#define SIGNATURE_OTHER TAG('O','O','O','O')
+#define TCP_TAG TAG('T','C','P',' ')
+
+static NPAGED_LOOKASIDE_LIST LargeLookasideList;
+static NPAGED_LOOKASIDE_LIST SmallLookasideList;
+
+NTSTATUS
+TCPMemStartup( void )
+{
+    ExInitializeNPagedLookasideList( &LargeLookasideList,
+                                     NULL,
+                                     NULL,
+                                     0,
+                                     LARGE_SIZE + sizeof( ULONG ),
+                                     TCP_TAG,
+                                     0 );
+    ExInitializeNPagedLookasideList( &SmallLookasideList,
+                                     NULL,
+                                     NULL,
+                                     0,
+                                     SMALL_SIZE + sizeof( ULONG ),
+                                     TCP_TAG,
+                                     0 );
+
+    return STATUS_SUCCESS;
+}
+
+void *TCPMalloc( void *ClientData,
+		 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
+    void *v;
+    ULONG Signature;
+
+#if 0 != MEM_PROFILE
+    static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
+    static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
+    OSK_UINT i, NewSize, *NewArray;
+    int Found;
+
+    Found = 0;
+    for ( i = 0; i < ArrayUsed && ! Found; i++ ) {
+	Found = ( Sizes[i] == Bytes );
+	if ( Found ) {
+	    Counts[i]++;
+	}
+    }
+    if ( ! Found ) {
+	if ( ArrayAllocated <= ArrayUsed ) {
+	    NewSize = ( 0 == ArrayAllocated ? 16 : 2 * ArrayAllocated );
+	    NewArray = PoolAllocateBuffer( 2 * NewSize * sizeof( OSK_UINT ) );
+	    if ( NULL != NewArray ) {
+		if ( 0 != ArrayAllocated ) {
+		    memcpy( NewArray, Sizes,
+		            ArrayAllocated * sizeof( OSK_UINT ) );
+		    PoolFreeBuffer( Sizes );
+		    memcpy( NewArray + NewSize, Counts,
+		            ArrayAllocated * sizeof( OSK_UINT ) );
+		    PoolFreeBuffer( Counts );
+		}
+		Sizes = NewArray;
+		Counts = NewArray + NewSize;
+		ArrayAllocated = NewSize;
+	    } else if ( 0 != ArrayAllocated ) {
+		PoolFreeBuffer( Sizes );
+		PoolFreeBuffer( Counts );
+		ArrayAllocated = 0;
+	    }
+	}
+	if ( ArrayUsed < ArrayAllocated ) {
+	    Sizes[ArrayUsed] = Bytes;
+	    Counts[ArrayUsed] = 1;
+	    ArrayUsed++;
+	}
+    }
+
+    if ( 0 == (++AllocationCount % MEM_PROFILE) ) {
+	TI_DbgPrint(DEBUG_TCP, ("Memory allocation size profile:\n"));
+	for ( i = 0; i < ArrayUsed; i++ ) {
+	    TI_DbgPrint(DEBUG_TCP,
+	                ("Size %4u Count %5u\n", Sizes[i], Counts[i]));
+	}
+	TI_DbgPrint(DEBUG_TCP, ("End of memory allocation size profile\n"));
+    }
+#endif /* MEM_PROFILE */
+
+    if ( SMALL_SIZE == Bytes ) {
+	v = ExAllocateFromNPagedLookasideList( &SmallLookasideList );
+	Signature = SIGNATURE_SMALL;
+    } else if ( LARGE_SIZE == Bytes ) {
+	v = ExAllocateFromNPagedLookasideList( &LargeLookasideList );
+	Signature = SIGNATURE_LARGE;
+    } else {
+	v = PoolAllocateBuffer( Bytes + sizeof(ULONG) );
+	Signature = SIGNATURE_OTHER;
+    }
+    if( v ) {
+	*((ULONG *) v) = Signature;
+	v = (void *)((char *) v + sizeof(ULONG));
+	TrackWithTag( FOURCC('f','b','s','d'), v, (PCHAR)File, Line );
+    }
+
+    return v;
+}
+
+void TCPFree( void *ClientData,
+	      void *data, OSK_PCHAR File, OSK_UINT Line ) {
+    ULONG Signature;
+
+    UntrackFL( (PCHAR)File, Line, data );
+    data = (void *)((char *) data - sizeof(ULONG));
+    Signature = *((ULONG *) data);
+    if ( SIGNATURE_SMALL == Signature ) {
+	ExFreeToNPagedLookasideList( &SmallLookasideList, data );
+    } else if ( SIGNATURE_LARGE == Signature ) {
+	ExFreeToNPagedLookasideList( &LargeLookasideList, data );
+    } else if ( SIGNATURE_OTHER == Signature ) {
+	PoolFreeBuffer( data );
+    } else {
+	ASSERT( FALSE );
+    }
+}
+
+void
+TCPMemShutdown( void )
+{
+    ExDeleteNPagedLookasideList( &SmallLookasideList );
+    ExDeleteNPagedLookasideList( &LargeLookasideList );
+}

Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c
--- trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c	2006-01-02 20:04:19 UTC (rev 20535)
+++ trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c	2006-01-02 20:26:03 UTC (rev 20536)
@@ -286,10 +286,12 @@
 			      OSK_UINT FindType,
 			      OSK_SOCKADDR *ReqAddr );
 
+NTSTATUS TCPMemStartup( void );
 void *TCPMalloc( void *ClientData,
 		 OSK_UINT bytes, OSK_PCHAR file, OSK_UINT line );
 void TCPFree( void *ClientData,
 	      void *data, OSK_PCHAR file, OSK_UINT line );
+void TCPMemShutdown( void );
 
 int TCPSleep( void *ClientData, void *token, int priority, char *msg,
 	      int tmio );
@@ -376,10 +378,16 @@
  *     Status of operation
  */
 {
+    NTSTATUS Status;
+
     TcpipRecursiveMutexInit( &TCPLock );
     ExInitializeFastMutex( &SleepingThreadsLock );
     InitializeListHead( &SleepingThreadsList );
     InitializeListHead( &SignalledConnections );
+    Status = TCPMemStartup();
+    if ( ! NT_SUCCESS(Status) ) {
+	return Status;
+    }
 
     PortsStartup( &TCPPorts, 1, 0xfffe );
 
@@ -433,6 +441,8 @@
 
     PortsShutdown( &TCPPorts );
 
+    TCPMemShutdown();
+
     return STATUS_SUCCESS;
 }