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; }