213 lines
5.4 KiB
C
213 lines
5.4 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
membnch.c
|
|
|
|
Abstract:
|
|
|
|
Short benchmark for testing raw memory throughput of
|
|
SMP machines. Designed to thrash the hell out of the
|
|
system's memory bus.
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 12-Sep-1994
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct _THREADPARAMS {
|
|
DWORD ThreadIndex;
|
|
PCHAR BufferStart;
|
|
ULONG BufferLength;
|
|
DWORD Stride;
|
|
} THREADPARAMS, *PTHREADPARAMS;
|
|
|
|
|
|
DWORD MemorySize = 64*1024*1024;
|
|
HANDLE StartEvent;
|
|
THREADPARAMS ThreadParams[32];
|
|
HANDLE ThreadHandle[32];
|
|
ULONG TotalIterations = 1;
|
|
|
|
|
|
DWORD WINAPI
|
|
MemoryTest(
|
|
IN LPVOID lpThreadParameter
|
|
);
|
|
|
|
main (argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
DWORD CurrentRun;
|
|
DWORD i;
|
|
SYSTEM_INFO SystemInfo;
|
|
PCHAR Memory;
|
|
PCHAR ThreadMemory;
|
|
DWORD ChunkSize;
|
|
DWORD ThreadId;
|
|
DWORD StartTime, EndTime;
|
|
DWORD ThisTime, LastTime;
|
|
DWORD IdealTime;
|
|
LONG IdealImprovement;
|
|
LONG ActualImprovement;
|
|
DWORD StrideValues[] = {4, 16, 32, 4096, 8192, 0};
|
|
LPDWORD Stride = StrideValues;
|
|
BOOL Result;
|
|
|
|
//
|
|
// If we have an argument, use that as the # of iterations
|
|
//
|
|
if (argc > 1) {
|
|
TotalIterations = atoi(argv[1]);
|
|
if (TotalIterations == 0) {
|
|
fprintf(stderr, "Usage: %s [# iterations]\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
printf("%d iterations\n",TotalIterations);
|
|
}
|
|
//
|
|
// Determine how many processors in the system.
|
|
//
|
|
GetSystemInfo(&SystemInfo);
|
|
|
|
//
|
|
// Create the start event.
|
|
//
|
|
StartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
if (StartEvent == NULL) {
|
|
fprintf(stderr, "CreateEvent failed, error %d\n",GetLastError());
|
|
exit(1);
|
|
}
|
|
|
|
//
|
|
// Try and boost our working set size.
|
|
//
|
|
do {
|
|
Result = SetProcessWorkingSetSize(GetCurrentProcess(), MemorySize, MemorySize*2);
|
|
if (!Result) {
|
|
MemorySize -= 10*1024*1024;
|
|
}
|
|
} while ( !Result );
|
|
|
|
printf("MEMBNCH: Using %d MB array\n", MemorySize / (1024*1024));
|
|
|
|
//
|
|
// Allocate a big chunk of memory (64MB)
|
|
//
|
|
Memory = VirtualAlloc(NULL,
|
|
MemorySize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
if (Memory==NULL) {
|
|
fprintf(stderr, "VirtualAlloc failed, error %d\n",GetLastError());
|
|
exit(1);
|
|
}
|
|
|
|
|
|
do {
|
|
printf("STRIDE = %d\n", *Stride);
|
|
for (CurrentRun=1; CurrentRun<=SystemInfo.dwNumberOfProcessors; CurrentRun++) {
|
|
|
|
printf(" %d threads: ", CurrentRun);
|
|
//
|
|
// Start the threads, and let them party on the
|
|
// memory buffer.
|
|
//
|
|
ResetEvent(StartEvent);
|
|
|
|
ChunkSize = (MemorySize / CurrentRun) & ~7;
|
|
|
|
for (i=0; i<CurrentRun; i++) {
|
|
ThreadParams[i].ThreadIndex = i;
|
|
ThreadParams[i].BufferStart = Memory + (i * ChunkSize);
|
|
ThreadParams[i].BufferLength = ChunkSize;
|
|
ThreadParams[i].Stride = *Stride;
|
|
|
|
ThreadHandle[i] = CreateThread(NULL,
|
|
0,
|
|
MemoryTest,
|
|
&ThreadParams[i],
|
|
0,
|
|
&ThreadId);
|
|
if (ThreadHandle[i] == NULL) {
|
|
fprintf(stderr, "CreateThread %d failed, %d\n", i, GetLastError());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Touch all the pages.
|
|
//
|
|
ZeroMemory(Memory, MemorySize);
|
|
|
|
//
|
|
// Start the threads and wait for them to exit.
|
|
//
|
|
StartTime = GetTickCount();
|
|
SetEvent(StartEvent);
|
|
|
|
WaitForMultipleObjects(CurrentRun, ThreadHandle, TRUE, INFINITE);
|
|
EndTime = GetTickCount();
|
|
|
|
ThisTime = EndTime-StartTime;
|
|
|
|
printf("%7d ms",ThisTime);
|
|
printf(" %.3f MB/sec",(float)(MemorySize*TotalIterations)/(1024*1024) / ((float)ThisTime / 1000));
|
|
|
|
if (CurrentRun > 1) {
|
|
IdealTime = (LastTime * (CurrentRun-1)) / CurrentRun;
|
|
IdealImprovement = LastTime - IdealTime;
|
|
ActualImprovement = LastTime - ThisTime;
|
|
printf(" (%3d %% )\n",(100*ActualImprovement)/IdealImprovement);
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
LastTime = ThisTime;
|
|
|
|
for (i=0; i<CurrentRun; i++) {
|
|
CloseHandle(ThreadHandle[i]);
|
|
}
|
|
}
|
|
|
|
++Stride;
|
|
} while ( *Stride );
|
|
}
|
|
|
|
DWORD WINAPI
|
|
MemoryTest(
|
|
IN LPVOID lpThreadParameter
|
|
)
|
|
{
|
|
PTHREADPARAMS Params = (PTHREADPARAMS)lpThreadParameter;
|
|
ULONG i;
|
|
ULONG j;
|
|
DWORD *Buffer;
|
|
ULONG Stride;
|
|
ULONG Length;
|
|
ULONG Iterations;
|
|
|
|
Buffer = (DWORD *)Params->BufferStart;
|
|
Stride = Params->Stride / sizeof(DWORD);
|
|
Length = Params->BufferLength / sizeof(DWORD);
|
|
WaitForSingleObject(StartEvent,INFINITE);
|
|
|
|
for (Iterations=0; Iterations < TotalIterations; Iterations++) {
|
|
for (j=0; j < Stride; j++) {
|
|
|
|
for (i=0; i < Length-Stride; i += Stride) {
|
|
|
|
Params->BufferStart[i+j] += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|