Create performance test program

svn path=/trunk/; revision=13087
This commit is contained in:
Gé van Geldorp 2005-01-16 22:35:11 +00:00
parent 182c4064e6
commit 230af59be2
7 changed files with 1211 additions and 0 deletions

View file

@ -0,0 +1,24 @@
PATH_TO_TOP = ../../..
TARGET_TYPE = program
TARGET_APPTYPE = console
TARGET_NAME = rosperf
TARGET_SDKLIBS = version.a gdi32.a user32.a kernel32.a ntdll.a
TARGET_OBJECTS = rosperf.o testlist.o fill.o lines.o
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# Automatic dependency tracking
DEP_OBJECTS := $(TARGET_OBJECTS)
include $(PATH_TO_TOP)/tools/depend.mk
# EOF

View file

@ -0,0 +1,60 @@
/*
* ReactOS RosPerf - ReactOS GUI performance test program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <windows.h>
#include "rosperf.h"
void
FillProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps)
{
unsigned Rep;
for (Rep = 0; Rep < Reps; Rep++)
{
PatBlt((Rep & 0x100) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, 0, 0,
PerfInfo->WndWidth, PerfInfo->WndHeight, PATCOPY);
}
}
void
FillSmallProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps)
{
#define SMALL_SIZE 16
unsigned Rep;
unsigned x, y;
x = 0;
y = 0;
for (Rep = 0; Rep < Reps; Rep++)
{
PatBlt((Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, x, y,
SMALL_SIZE, SMALL_SIZE, PATCOPY);
x += SMALL_SIZE + 1;
if (PerfInfo->WndWidth < x + SMALL_SIZE)
{
x = 0;
y += SMALL_SIZE + 1;
if (PerfInfo->WndHeight < y + SMALL_SIZE)
{
y = 0;
}
}
}
}
/* EOF */

View file

@ -0,0 +1,97 @@
/*
* ReactOS RosPerf - ReactOS GUI performance test program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <windows.h>
#include "rosperf.h"
void
LinesProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps)
{
unsigned Rep;
int Dest;
HDC Dc;
for (Rep = 0; Rep < Reps; )
{
Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc;
for (Dest = 2; Dest < PerfInfo->WndHeight && Rep < Reps; Rep++, Dest += 2)
{
MoveToEx(Dc, 0, 0, NULL);
LineTo(Dc, PerfInfo->WndWidth, Dest);
}
for (Dest = PerfInfo->WndWidth - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2)
{
MoveToEx(Dc, PerfInfo->WndWidth, 0, NULL);
LineTo(Dc, Dest, PerfInfo->WndHeight);
}
for (Dest = PerfInfo->WndHeight - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2)
{
MoveToEx(Dc, PerfInfo->WndWidth, PerfInfo->WndHeight, NULL);
LineTo(Dc, 0, Dest);
}
for (Dest = 2; Dest < PerfInfo->WndWidth && Rep < Reps; Rep++, Dest += 2)
{
MoveToEx(Dc, 0, PerfInfo->WndHeight, NULL);
LineTo(Dc, Dest, 0);
}
}
}
void
LinesHorizontalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps)
{
unsigned Rep;
unsigned y;
HDC Dc;
for (Rep = 0; Rep < Reps; )
{
Dc = (Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc;
for (y = 0; y < PerfInfo->WndHeight && Rep < Reps; Rep++, y += 3)
{
MoveToEx(Dc, 0, y, NULL);
LineTo(Dc, PerfInfo->WndWidth, y);
}
}
}
void
LinesVerticalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps)
{
unsigned Rep;
unsigned x;
HDC Dc;
for (Rep = 0; Rep < Reps; )
{
Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc;
for (x = 0; x < PerfInfo->WndWidth && Rep < Reps; Rep++, x += 3)
{
MoveToEx(Dc, x, 0, NULL);
LineTo(Dc, x, PerfInfo->WndHeight);
}
}
}
/* EOF */

View file

@ -0,0 +1,923 @@
/*
* ReactOS RosPerf - ReactOS GUI performance test program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Ideas copied from x11perf:
*
* Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Digital not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <reactos/buildno.h>
#include "rosperf.h"
#define MAINWND_WIDTH 400
#define MAINWND_HEIGHT 400
static HWND LabelWnd;
unsigned
NullInit(void **Context, PPERF_INFO PerfInfo, unsigned Reps)
{
*Context = NULL;
return Reps;
}
void
NullCleanup(void *Context, PPERF_INFO PerfInfo)
{
}
static void
ProcessMessages(void)
{
MSG Msg;
while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
{
if (WM_QUIT == Msg.message)
{
exit(Msg.wParam);
}
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
}
static void
ClearWindow(PPERF_INFO PerfInfo)
{
InvalidateRect(PerfInfo->Wnd, NULL, TRUE);
UpdateWindow(PerfInfo->Wnd);
}
static unsigned
CalibrateTest(PTEST Test, PPERF_INFO PerfInfo)
{
#define GOAL 2500 /* Try to get up to 2.5 seconds */
#define ENOUGH 2000 /* But settle for 2.0 seconds */
#define TICK 10 /* Assume clock not faster than .01 seconds */
unsigned Reps, DidReps; /* Reps desired, reps performed */
unsigned Exponent;
void *Context;
DWORD StartTick;
DWORD Duration;
/* Attempt to get an idea how long each rep lasts by getting enough
reps to last more than ENOUGH. Then scale that up to the number of
seconds desired.
If init call to test ever fails, return False and test will be skipped.
*/
Reps = 1;
for (;;)
{
ClearWindow(PerfInfo);
DidReps = (*Test->Init)(&Context, PerfInfo, Reps);
ProcessMessages();
if (0 == DidReps)
{
return 0;
}
StartTick = GetTickCount();
(*Test->Proc)(Context, PerfInfo, Reps);
Duration = GetTickCount() - StartTick;
(*Test->PassCleanup) (Context, PerfInfo);
(*Test->Cleanup)(Context, PerfInfo);
ProcessMessages();
if (DidReps != Reps)
{
/* The test can't do the number of reps as we asked for.
Give up */
return DidReps;
}
/* Did we go long enough? */
if (ENOUGH <= Duration)
{
break;
}
/* Don't let too short a clock make new reps wildly high */
if (Duration <= TICK)
{
Reps *= 10;
}
else
{
/* Try to get up to GOAL seconds. */
Reps = (int)(GOAL * (double) Reps / (double) Duration) + 1;
}
}
Reps = (int) ((double) PerfInfo->Seconds * 1000.0 * (double) Reps / (double) Duration) + 1;
/* Now round reps up to 1 digit accuracy, so we don't get stupid-looking
numbers of repetitions. */
Reps--;
Exponent = 1;
while (9 < Reps)
{
Reps /= 10;
Exponent *= 10;
}
Reps = (Reps + 1) * Exponent;
return Reps;
}
static void
DisplayStatus(HWND Label, LPCWSTR Message, LPCWSTR Test, int Try)
{
WCHAR Status[128];
snwprintf(Status, sizeof(Status) / sizeof(Status[0]), L"%d %s %s", Try, Message, Test);
SetWindowTextW(Label, Status);
InvalidateRect(Label, NULL, TRUE);
UpdateWindow(Label);
}
static double
RoundTo3Digits(double d)
{
/* It's kind of silly to print out things like ``193658.4/sec'' so just
junk all but 3 most significant digits. */
double exponent, sign;
exponent = 1.0;
/* the code below won't work if d should happen to be non-positive. */
if (d < 0.0)
{
d = -d;
sign = -1.0;
}
else
{
sign = 1.0;
}
if (1000.0 <= d)
{
do
{
exponent *= 10.0;
}
while (1000.0 <= d / exponent);
d = (double)((int)(d / exponent + 0.5));
d *= exponent;
}
else
{
if (0.0 != d)
{
while (d * exponent < 100.0)
{
exponent *= 10.0;
}
}
d = (double)((int)(d * exponent + 0.5));
d /= exponent;
}
return d * sign;
}
static void
ReportTimes(DWORD Time, int Reps, LPCWSTR Label, BOOL Average)
{
double MSecsPerObj, ObjsPerSec;
if (0 != Time)
{
MSecsPerObj = (double) Time / (double) Reps;
ObjsPerSec = (double) Reps * 1000.0 / (double) Time;
/* Round obj/sec to 3 significant digits. Leave msec untouched, to
allow averaging results from several repetitions. */
ObjsPerSec = RoundTo3Digits(ObjsPerSec);
wprintf(L"%7d %s @ %8.4f msec (%8.1f/sec): %s\n",
Reps, Average ? L"trep" : L"reps", MSecsPerObj, ObjsPerSec, Label);
}
else
{
wprintf(L"%6d %sreps @ 0.0 msec (unmeasurably fast): %s\n",
Reps, Average ? L"t" : L"", Label);
}
}
static void
ProcessTest(PTEST Test, PPERF_INFO PerfInfo)
{
unsigned Reps;
unsigned Repeat;
void *Context;
DWORD StartTick;
DWORD Time, TotalTime;
DisplayStatus(LabelWnd, L"Calibrating", Test->Label, 0);
Reps = CalibrateTest(Test, PerfInfo);
if (0 == Reps)
{
return;
}
Reps = Test->Init(&Context, PerfInfo, Reps);
if (0 == Reps)
{
return;
}
TotalTime = 0;
for (Repeat = 0; Repeat < PerfInfo->Repeats; Repeat++)
{
DisplayStatus(LabelWnd, L"Testing", Test->Label, Repeat + 1);
ClearWindow(PerfInfo);
StartTick = GetTickCount();
(*Test->Proc)(Context, PerfInfo, Reps);
Time = GetTickCount() - StartTick;
ProcessMessages();
TotalTime += Time;
ReportTimes(Time, Reps, Test->Label, FALSE);
(*Test->PassCleanup)(Context, PerfInfo);
ProcessMessages();
}
(*Test->Cleanup)(Context, PerfInfo);
ReportTimes(TotalTime, Repeat * Reps, Test->Label, TRUE);
ProcessMessages();
}
static void
PrintOSVersion(void)
{
#define BUFSIZE 160
OSVERSIONINFOEXW VersionInfo;
BOOL OsVersionInfoEx;
HKEY hKey;
WCHAR ProductType[BUFSIZE];
DWORD BufLen;
LONG Ret;
unsigned RosVersionLen;
LPWSTR RosVersion;
/* Try calling GetVersionEx using the OSVERSIONINFOEX structure.
* If that fails, try using the OSVERSIONINFO structure. */
ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFOEXW));
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
OsVersionInfoEx = GetVersionExW((OSVERSIONINFOW *) &VersionInfo);
if (! OsVersionInfoEx)
{
VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionExW((OSVERSIONINFOW *) &VersionInfo))
{
return;
}
}
RosVersion = VersionInfo.szCSDVersion + wcslen(VersionInfo.szCSDVersion) + 1;
RosVersionLen = sizeof(VersionInfo.szCSDVersion) / sizeof(VersionInfo.szCSDVersion[0]) -
(RosVersion - VersionInfo.szCSDVersion);
if (7 <= RosVersionLen && 0 == wcsnicmp(RosVersion, L"ReactOS", 7))
{
wprintf(L"Running on %s\n", RosVersion);
return;
}
switch (VersionInfo.dwPlatformId)
{
/* Test for the Windows NT product family. */
case VER_PLATFORM_WIN32_NT:
/* Test for the specific product. */
if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows Server 2003, ");
}
else if (5 == VersionInfo.dwMajorVersion && 1 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows XP ");
}
else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows 2000 ");
}
else if (VersionInfo.dwMajorVersion <= 4 )
{
wprintf(L"Running on Microsoft Windows NT ");
}
/* Test for specific product on Windows NT 4.0 SP6 and later. */
if (OsVersionInfoEx)
{
/* Test for the workstation type. */
if (VER_NT_WORKSTATION == VersionInfo.wProductType)
{
if (4 == VersionInfo.dwMajorVersion)
{
wprintf(L"Workstation 4.0 ");
}
else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_PERSONAL))
{
wprintf(L"Home Edition ");
}
else
{
wprintf(L"Professional ");
}
}
/* Test for the server type. */
else if (VER_NT_SERVER == VersionInfo.wProductType ||
VER_NT_DOMAIN_CONTROLLER == VersionInfo.wProductType)
{
if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion)
{
if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER))
{
wprintf(L"Datacenter Edition ");
}
else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE))
{
wprintf(L"Enterprise Edition ");
}
else if (VER_SUITE_BLADE == VersionInfo.wSuiteMask)
{
wprintf(L"Web Edition ");
}
else
{
wprintf(L"Standard Edition ");
}
}
else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion)
{
if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER))
{
wprintf(L"Datacenter Server ");
}
else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE))
{
wprintf(L"Advanced Server " );
}
else
{
wprintf(L"Server " );
}
}
else /* Windows NT 4.0 */
{
if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE))
{
wprintf(L"Server 4.0, Enterprise Edition ");
}
else
{
wprintf(L"Server 4.0 ");
}
}
}
}
else /* Test for specific product on Windows NT 4.0 SP5 and earlier */
{
BufLen = BUFSIZE;
Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_QUERY_VALUE, &hKey);
if (ERROR_SUCCESS != Ret)
{
return;
}
Ret = RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
(LPBYTE) ProductType, &BufLen);
if (ERROR_SUCCESS != Ret || BUFSIZE < BufLen)
{
return;
}
RegCloseKey(hKey);
if (0 == lstrcmpiW(L"WINNT", ProductType))
{
wprintf(L"Workstation ");
}
else if (0 == lstrcmpiW(L"LANMANNT", ProductType))
{
wprintf(L"Server ");
}
else if (0 == lstrcmpiW(L"SERVERNT", ProductType))
{
wprintf(L"Advanced Server ");
}
wprintf(L"%d.%d ", VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion);
}
/* Display service pack (if any) and build number. */
if (4 == VersionInfo.dwMajorVersion &&
0 == lstrcmpiW(VersionInfo.szCSDVersion, L"Service Pack 6"))
{
/* Test for SP6 versus SP6a. */
Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
0, KEY_QUERY_VALUE, &hKey);
if (ERROR_SUCCESS == Ret)
{
wprintf(L"Service Pack 6a (Build %d)\n", VersionInfo.dwBuildNumber & 0xFFFF);
}
else /* Windows NT 4.0 prior to SP6a */
{
wprintf(L"%s (Build %d)\n",
VersionInfo.szCSDVersion,
VersionInfo.dwBuildNumber & 0xFFFF);
}
RegCloseKey(hKey);
}
else /* not Windows NT 4.0 */
{
wprintf(L"%s (Build %d)\n",
VersionInfo.szCSDVersion,
VersionInfo.dwBuildNumber & 0xFFFF);
}
break;
/* Test for the Windows Me/98/95. A bit silly since we're using Unicode... */
case VER_PLATFORM_WIN32_WINDOWS:
if (4 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows 95 ");
if (L'C' == VersionInfo.szCSDVersion[1] || L'B' == VersionInfo.szCSDVersion[1])
{
wprintf(L"OSR2");
}
}
else if (4 == VersionInfo.dwMajorVersion && 10 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows 98 ");
if (L'A' == VersionInfo.szCSDVersion[1])
{
wprintf(L"SE");
}
}
else if (4 == VersionInfo.dwMajorVersion && 90 == VersionInfo.dwMinorVersion)
{
wprintf(L"Running on Microsoft Windows Millennium Edition");
}
wprintf(L"\n");
break;
case VER_PLATFORM_WIN32s: /* Even silier... */
wprintf(L"Running on Microsoft Win32s\n");
break;
}
}
static void
PrintAppVersion(void)
{
wprintf(L"RosPerf %S (Build %S)\n", KERNEL_VERSION_STR, KERNEL_VERSION_BUILD_STR);
}
static void
PrintDisplayInfo(void)
{
HDC Dc;
Dc = GetDC(NULL);
if (NULL == Dc)
{
return;
}
wprintf(L"Display settings %d * %d * %d\n", GetDeviceCaps(Dc, HORZRES),
GetDeviceCaps(Dc, VERTRES), GetDeviceCaps(Dc, BITSPIXEL) * GetDeviceCaps(Dc, PLANES));
ReleaseDC(NULL, Dc);
}
static void
PrintStartupInfo(void)
{
PrintAppVersion();
PrintOSVersion();
PrintDisplayInfo();
}
static LRESULT CALLBACK
MainWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT Ps;
HDC Dc;
LRESULT Result;
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
Result = 0;
break;
case WM_PAINT:
Dc = BeginPaint(Wnd, &Ps);
EndPaint (Wnd, &Ps);
Result = 0;
break;
default:
Result = DefWindowProcW(Wnd, Msg, wParam, lParam);
break;
}
return Result;
}
static LRESULT CALLBACK
LabelWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT Ps;
HDC Dc;
RECT ClientRect, WindowRect;
TEXTMETRICW Tm;
LRESULT Result;
WCHAR Title[80];
switch (Msg)
{
case WM_CREATE:
/* Make text fit */
Dc = GetDC(Wnd);
if (NULL != Dc && GetClientRect(Wnd, &ClientRect) && GetWindowRect(Wnd, &WindowRect)
&& GetTextMetricsW(Dc, &Tm))
{
if (Tm.tmHeight != ClientRect.bottom)
{
SetWindowPos(Wnd, NULL, 0, 0, WindowRect.right - WindowRect.left,
(WindowRect.bottom - WindowRect.top) + (Tm.tmHeight - ClientRect.bottom),
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
if (NULL != Dc)
{
ReleaseDC(Wnd, Dc);
}
Result = DefWindowProcW(Wnd, Msg, wParam, lParam);
break;
case WM_PAINT:
Dc = BeginPaint(Wnd, &Ps);
GetWindowTextW(Wnd, Title, sizeof(Title) / sizeof(Title[0]));
TextOutW(Dc, 0, 0, Title, wcslen(Title));
EndPaint (Wnd, &Ps);
Result = 0;
break;
default:
Result = DefWindowProcW(Wnd, Msg, wParam, lParam);
break;
}
return Result;
}
static HWND
CreatePerfWindows(HINSTANCE hInstance, PPERF_INFO PerfInfo)
{
WNDCLASSW wc;
HWND MainWnd;
wc.lpszClassName = L"RosPerfMain";
wc.lpfnWndProc = MainWndProc;
wc.style = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(PerfInfo->BackgroundColor);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if (RegisterClassW(&wc) == 0)
{
fwprintf(stderr, L"Failed to register RosPerfMain (last error %d)\n",
GetLastError());
return NULL;
}
wc.lpszClassName = L"RosPerfLabel";
wc.lpfnWndProc = LabelWndProc;
wc.style = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if (RegisterClassW(&wc) == 0)
{
fwprintf(stderr, L"Failed to register RosPerfLabel (last error %d)\n",
GetLastError());
return NULL;
}
MainWnd = CreateWindowW(L"RosPerfMain",
L"ReactOS performance test",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0,
0,
MAINWND_WIDTH,
MAINWND_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if (NULL == MainWnd)
{
fwprintf(stderr, L"Failed to create main window (last error %d)\n",
GetLastError());
return NULL;
}
LabelWnd = CreateWindowW(L"RosPerfLabel",
L"",
WS_POPUP | WS_THICKFRAME | WS_VISIBLE,
0,
MAINWND_HEIGHT + 10,
MAINWND_WIDTH,
20,
MainWnd,
NULL,
hInstance,
NULL);
if (NULL == LabelWnd)
{
fwprintf(stderr, L"Failed to create label window (last error 0x%lX)\n",
GetLastError());
return NULL;
}
SetActiveWindow(MainWnd);
return MainWnd;
}
static BOOL
ProcessCommandLine(PPERF_INFO PerfInfo, unsigned *TestCount, PTEST *Tests)
{
int ArgC, Arg;
LPWSTR *ArgV;
LPWSTR EndPtr;
PTEST AllTests;
BOOL *DoTest;
BOOL DoAll;
unsigned AllTestCount, i, j;
ArgV = CommandLineToArgvW(GetCommandLineW(), &ArgC);
if (NULL == ArgV)
{
fwprintf(stderr, L"CommandLineToArgvW failed\n");
return FALSE;
}
GetTests(&AllTestCount, &AllTests);
DoTest = malloc(AllTestCount * sizeof(BOOL));
if (NULL == DoTest)
{
fwprintf(stderr, L"Out of memory\n");
return FALSE;
}
DoAll = TRUE;
for (Arg = 1; Arg < ArgC; Arg++)
{
if (L'/' == ArgV[Arg][0] || L'-' == ArgV[Arg][0])
{
if (0 == wcsicmp(ArgV[Arg] + 1, L"repeat"))
{
if (ArgC <= Arg + 1)
{
fwprintf(stderr, L"%s needs a repeat count\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
Arg++;
PerfInfo->Repeats = wcstoul(ArgV[Arg], &EndPtr, 0);
if (L'\0' != *EndPtr || (long) PerfInfo->Repeats <= 0 || ULONG_MAX == PerfInfo->Repeats)
{
fwprintf(stderr, L"Invalid repeat count %s\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
}
else if (0 == wcsicmp(ArgV[Arg] + 1, L"seconds"))
{
if (ArgC <= Arg + 1)
{
fwprintf(stderr, L"%s needs a number of seconds\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
Arg++;
PerfInfo->Seconds = wcstoul(ArgV[Arg], &EndPtr, 0);
if (L'\0' != *EndPtr || (long) PerfInfo->Seconds < 0 || ULONG_MAX == PerfInfo->Seconds)
{
fwprintf(stderr, L"Invalid duration %s\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
}
else
{
fwprintf(stderr, L"Unrecognized option %s\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
}
else
{
if (DoAll)
{
for (i = 0; i < AllTestCount; i++)
{
DoTest[i] = FALSE;
}
DoAll = FALSE;
}
for (i = 0; i < AllTestCount; i++)
{
if (0 == wcsicmp(ArgV[Arg], AllTests[i].Option))
{
DoTest[i] = TRUE;
break;
}
}
if (AllTestCount <= i)
{
fwprintf(stderr, L"Unrecognized test %s\n", ArgV[Arg]);
free(DoTest);
GlobalFree(ArgV);
return FALSE;
}
}
}
GlobalFree(ArgV);
if (DoAll)
{
for (i = 0; i < AllTestCount; i++)
{
DoTest[i] = TRUE;
}
}
*TestCount = 0;
for (i = 0; i < AllTestCount; i++)
{
if (DoTest[i])
{
(*TestCount)++;
}
}
*Tests = malloc(*TestCount * sizeof(TEST));
if (NULL == *Tests)
{
fwprintf(stderr, L"Out of memory\n");
free(DoTest);
return FALSE;
}
j = 0;
for (i = 0; i < AllTestCount; i++)
{
if (DoTest[i])
{
(*Tests)[j] = AllTests[i];
j++;
}
}
free(DoTest);
return TRUE;
}
int WINAPI
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
PTEST Tests;
unsigned TestCount;
unsigned CurrentTest;
RECT Rect;
PERF_INFO PerfInfo;
PrintStartupInfo();
PerfInfo.Seconds = 15;
PerfInfo.Repeats = 4;
PerfInfo.ForegroundColor = RGB(0, 0, 0);
PerfInfo.BackgroundColor = RGB(255, 255, 255);
if (! ProcessCommandLine(&PerfInfo, &TestCount, &Tests))
{
exit(1);
}
PerfInfo.Wnd = CreatePerfWindows(hInstance, &PerfInfo);
if (NULL == PerfInfo.Wnd)
{
exit(1);
}
GetClientRect(PerfInfo.Wnd, &Rect);
PerfInfo.WndWidth = Rect.right - Rect.left;
PerfInfo.WndHeight = Rect.bottom - Rect.top;
PerfInfo.ForegroundDc = GetDC(PerfInfo.Wnd);
PerfInfo.BackgroundDc = GetDC(PerfInfo.Wnd);
if (NULL == PerfInfo.ForegroundDc || NULL == PerfInfo.BackgroundDc)
{
fwprintf(stderr, L"Failed to create device contexts (last error %d)\n",
GetLastError());
exit(1);
}
SelectObject(PerfInfo.ForegroundDc, CreateSolidBrush(PerfInfo.ForegroundColor));
SelectObject(PerfInfo.ForegroundDc, CreatePen(PS_SOLID, 0, PerfInfo.ForegroundColor));
SelectObject(PerfInfo.BackgroundDc, CreateSolidBrush(PerfInfo.BackgroundColor));
SelectObject(PerfInfo.BackgroundDc, CreatePen(PS_SOLID, 0, PerfInfo.BackgroundColor));
ProcessMessages();
/* Move cursor out of the way */
GetWindowRect(LabelWnd, &Rect);
SetCursorPos(Rect.right, Rect.bottom);
for (CurrentTest = 0; CurrentTest < TestCount; CurrentTest++)
{
wprintf(L"\n");
ProcessTest(Tests + CurrentTest, &PerfInfo);
}
GlobalFree(Tests);
return 0;
}
/* EOF */

View file

@ -0,0 +1,64 @@
/*
* ReactOS RosPerf - ReactOS GUI performance test program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef ROSPERF_H_INCLUDED
#define ROSPERF_H_INCLUDED
typedef struct tagPERF_INFO
{
HWND Wnd;
unsigned Seconds;
unsigned Repeats;
COLORREF ForegroundColor;
COLORREF BackgroundColor;
HDC ForegroundDc;
HDC BackgroundDc;
ULONG WndWidth;
ULONG WndHeight;
} PERF_INFO, *PPERF_INFO;
typedef unsigned (*INITTESTPROC)(void **Context, PPERF_INFO PerfInfo, unsigned Reps);
typedef void (*TESTPROC)(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
typedef void (*CLEANUPTESTPROC)(void *Context, PPERF_INFO PerfInfo);
typedef struct tagTEST
{
LPCWSTR Option;
LPCWSTR Label;
INITTESTPROC Init;
TESTPROC Proc;
CLEANUPTESTPROC PassCleanup;
CLEANUPTESTPROC Cleanup;
} TEST, *PTEST;
void GetTests(unsigned *TestCount, PTEST *Tests);
/* Tests */
unsigned NullInit(void **Context, PPERF_INFO PerfInfo, unsigned Reps);
void NullCleanup(void *Context, PPERF_INFO PerfInfo);
void FillProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
void FillSmallProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
void LinesHorizontalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
void LinesVerticalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
void LinesProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps);
#endif /* ROSPERF_H_INCLUDED */
/* EOF */

View file

@ -0,0 +1,4 @@
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS performance tester\0"
#define REACTOS_STR_INTERNAL_NAME "rosperf\0"
#define REACTOS_STR_ORIGINAL_FILENAME "rosperf.exe\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,39 @@
/*
* ReactOS RosPerf - ReactOS GUI performance test program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <windows.h>
#include "rosperf.h"
static TEST TestList[] =
{
{ L"fill", L"Fill", NullInit, FillProc, NullCleanup, NullCleanup },
{ L"smallfill", L"Small Fill", NullInit, FillSmallProc, NullCleanup, NullCleanup },
{ L"hlines", L"Horizontal Lines", NullInit, LinesHorizontalProc, NullCleanup, NullCleanup },
{ L"vlines", L"Vertical Lines", NullInit, LinesVerticalProc, NullCleanup, NullCleanup },
{ L"lines", L"Lines", NullInit, LinesProc, NullCleanup, NullCleanup }
};
void
GetTests(unsigned *TestCount, PTEST *Tests)
{
*TestCount = sizeof(TestList) / sizeof(TEST);
*Tests = TestList;
}
/* EOF */