/*++ Copyright (c) 1996 Microsoft Corporation Module Name bench.c Abstract: Measure time for a number of API calls or small application modules Author: Dan Almosnino (danalm) July 96 Based on code by (MarkE) and DarrinM Enviornment: User Mode Revision History: Dan Almosnino (danalm) 20-Sept-195 1. Timer call modified to run on both NT and WIN95. Dan Almosnino (danalm) 20-Nov-1995 1. Modified Timer call to measure Pentium cycle counts when applicable 2. Modified default numbers for test iterations to accomodate the statistical module add-on. (Typically 10 test samples are taken, doing 10-1000 iterations each). Dan Almosnino (danalm) 25-July-96 1. Adapted to the same format as that of GDIbench, including the features above. 2. Cleanup some tests. --*/ #include "precomp.h" #include "bench.h" #include "usrbench.h" #include "resource.h" #ifndef WIN32 #define APIENTRY FAR PASCAL typedef int INT; typedef char CHAR; #endif #define SETWINDOWLONGVAL 99999L /* * Function prototypes */ INT_PTR APIENTRY FileOpenDlgProc(HWND, UINT, WPARAM, LPARAM); INT_PTR APIENTRY ClearDlg(HWND, UINT, WPARAM, LPARAM); INT_PTR APIENTRY ClearDlgNoState(HWND, UINT, WPARAM, LPARAM); LRESULT APIENTRY CreateDestroyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT APIENTRY CreateDestroyWndProcW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); #ifdef ASSERT #undef ASSERT #endif #define ASSERT(expr) if (!(expr)) { char szBuf[256]; \ sprintf(szBuf,"Assertion Failure %s %ld:"#expr"\n", __FILE__, __LINE__); \ MessageBox(NULL, szBuf, "Assert Failure", MB_OK); } static void DispErrorMsg(const char* title) { LPVOID msgbuf; if (title == NULL) { title = "Error"; } FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&msgbuf, 0, NULL); MessageBox(NULL, msgbuf, title, MB_OK | MB_ICONEXCLAMATION); LocalFree(msgbuf); } /* * Global variables */ CHAR* aszTypical[] = { "change", "alteration", "amendment", "mutation", "permutation", "variation", "substitution", "modification", "transposition", "transformation" }; INT NStrings = sizeof(aszTypical) / sizeof(aszTypical[0]); BOOL gfSetFocus = TRUE; #define PROPCLASSNAME TEXT("PropWindow") /* * External global variables. */ extern HWND ghwndFrame, ghwndMDIClient; extern HANDLE ghinst; /*++ Routine Description: Measure start count Return Value - Performance Count --*/ extern BOOL gfPentium; _int64 BeginTimeMeasurement() { _int64 PerformanceCount; extern BOOL gfUseCycleCount; #ifdef _X86_ SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); if (gfUseCycleCount && (PROCESSOR_INTEL_PENTIUM == SystemInfo.dwProcessorType)) gfPentium = TRUE; else #endif gfPentium = FALSE; #ifdef _X86_ if (gfPentium) PerformanceCount = GetCycleCount(); else #endif QueryPerformanceCounter((LARGE_INTEGER*)&PerformanceCount); return(PerformanceCount); } /*++ Routine Description: Measure stop count and return the calculated time difference Arguments StartTime = Start Time Count Iter = No. of Test Iterations Return Value - Test Time per Iteration, in 100 nano-second units --*/ ULONGLONG EndTimeMeasurement(_int64 StartTime, ULONG Iter) { _int64 PerformanceCount; extern _int64 PerformanceFreq; extern BOOL gfPentium; #ifdef _X86_ if (gfPentium) { PerformanceCount = GetCycleCount(); PerformanceCount -= CCNT_OVERHEAD; } else #endif QueryPerformanceCounter((LARGE_INTEGER*)&PerformanceCount); PerformanceCount -= StartTime; #ifdef _X86_ if (gfPentium) PerformanceCount /= Iter; else #endif PerformanceCount /= (PerformanceFreq * Iter); // Result is in 100ns units // because PerformanceFreq // was set to Counts/(100ns) return((ULONGLONG)PerformanceCount); } /*++ Routine Description: Measure APIs Arguments hdc - dc iter - number of times to call Return Value time for calls --*/ ULONGLONG msProfRegisterClass(HDC hdc, ULONG Iter) { INIT_TIMER; WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = CreateDestroyWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghinst; wc.hIcon = LoadIcon(ghinst, (LPSTR)IDUSERBENCH); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = PROPCLASSNAME; START_TIMER; while (ix--) { RegisterClass(&wc); UnregisterClass(PROPCLASSNAME, ghinst); } END_TIMER; } ULONGLONG msProfClassGroup(HDC hdc, ULONG Iter) { char szBuf[50]; HICON hIcon; INIT_TIMER; WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = CreateDestroyWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghinst; wc.hIcon = hIcon = LoadIcon(ghinst, (LPSTR)IDUSERBENCH); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = PROPCLASSNAME; RegisterClass(&wc); START_TIMER; while (ix--) { GetClassInfo(ghinst, PROPCLASSNAME, &wc); GetClassName(ghwndFrame, szBuf, sizeof(szBuf) / sizeof(szBuf[0])); GetClassLongPtr(ghwndFrame, GCLP_HBRBACKGROUND); SetClassLongPtr(ghwndFrame, GCLP_HICON, (LONG_PTR)hIcon); } END_TIMER_NO_RETURN; UnregisterClass(PROPCLASSNAME, ghinst); RETURN_STOP_TIME; } ULONGLONG msProfClipboardGroup(HDC hdc, ULONG Iter) { INIT_TIMER; HGLOBAL h; int i; START_TIMER; while (ix--) { START_OVERHEAD; h = GlobalAlloc(GPTR | GMEM_DDESHARE, 80); strcpy(h, "hello"); END_OVERHEAD; OpenClipboard(ghwndFrame); EmptyClipboard(); SetClipboardData(CF_TEXT, h); GetClipboardData(CF_TEXT); CloseClipboard(); } END_TIMER_NO_RETURN; RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgDraw(HDC hdc, ULONG Iter) { CHAR szFile[128]; INIT_TIMER; HWND hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(CLEARBOX), ghwndFrame, ClearDlg, MAKELONG(szFile, 0)); START_TIMER; while (ix--) { ShowWindow(hwnd, TRUE); UpdateWindow(hwnd); ShowWindow(hwnd, FALSE); } END_TIMER_NO_RETURN; DestroyWindow(hwnd); RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgCreate(HDC hdc, ULONG Iter) { HWND hwnd; CHAR szFile[128]; INIT_TIMER; START_TIMER; while (ix--) { hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(CLEARBOX), ghwndFrame, ClearDlg, MAKELONG(szFile, 0)); ShowWindow(hwnd, TRUE); UpdateWindow(hwnd); DestroyWindow(hwnd); } END_TIMER_NO_RETURN; RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgCreateDestroy(HDC hdc, ULONG Iter) { HWND hwnd; CHAR szFile[128]; INIT_TIMER; gfSetFocus = FALSE; // Trying to minimize GDI's impact. START_TIMER; while (ix--) { hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(CLEARBOX), ghwndFrame, ClearDlg, MAKELONG(szFile, 0)); DestroyWindow(hwnd); } END_TIMER_NO_RETURN; gfSetFocus = TRUE; RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgCreateDestroyNoMenu(HDC hdc, ULONG Iter) { HWND hwnd; CHAR szFile[128]; INIT_TIMER; gfSetFocus = FALSE; // Trying to minimize GDI's impact. START_TIMER; while (ix--) { hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(CLEARBOXNOMENU), ghwndFrame, ClearDlg, MAKELONG(szFile, 0)); DestroyWindow(hwnd); } END_TIMER_NO_RETURN; gfSetFocus = TRUE; RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgCreateDestroyNoFont(HDC hdc, ULONG Iter) { HWND hwnd; CHAR szFile[128]; INIT_TIMER; gfSetFocus = FALSE; // Trying to minimize GDI's impact. START_TIMER; while (ix--) { hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(CLEARBOXNOFONT), ghwndFrame, ClearDlg, MAKELONG(szFile, 0)); DestroyWindow(hwnd); } END_TIMER_NO_RETURN; gfSetFocus = TRUE; RETURN_STOP_TIME; } ULONGLONG msProfAvgDlgCreateDestroyEmpty(HDC hdc, ULONG Iter) { HWND hwnd; CHAR szFile[128]; INIT_TIMER; gfSetFocus = FALSE; // Trying to minimize GDI's impact. START_TIMER; while (ix--) { hwnd = CreateDialogParam(ghinst, MAKEINTRESOURCE(EMPTY), ghwndFrame, ClearDlgNoState, MAKELONG(szFile, 0)); DestroyWindow(hwnd); } END_TIMER_NO_RETURN; gfSetFocus = TRUE; RETURN_STOP_TIME; } ULONGLONG msProfCreateDestroyWindow(HDC hdc, ULONG Iter) { HWND hwnd; INIT_TIMER; WNDCLASS wc; if (!ghinst)MessageBox(GetParent(ghwndMDIClient), "1ghinst==0", "ERROR!", MB_OK); wc.style = 0; wc.lpfnWndProc = CreateDestroyWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghinst; wc.hIcon = LoadIcon(ghinst, (LPSTR)IDUSERBENCH); wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = "CreateDestroyWindow"; if (!RegisterClass(&wc)) { MessageBox(GetParent(ghwndMDIClient), "1RegisterClass call failed.", "ERROR!", MB_OK); return (ULONGLONG)(0); } START_TIMER; while (ix--) { hwnd = CreateWindow("CreateDestroyWindow", "Create/DestroyWindow test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, ghinst, NULL); if (hwnd == NULL) { MessageBox(GetParent(ghwndMDIClient), "CreateWindow call failed.", "ERROR!", MB_OK); break; } DestroyWindow(hwnd); } END_TIMER_NO_RETURN; UnregisterClass("CreateDestroyWindow", ghinst); RETURN_STOP_TIME; } ULONGLONG msProfCreateDestroyChildWindow(HDC hdc, ULONG Iter) { HWND hwnd, hwndParent; INIT_TIMER; WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = CreateDestroyWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghinst; wc.hIcon = LoadIcon(ghinst, (LPSTR)IDUSERBENCH); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = "CreateDestroyWindow"; if (!RegisterClass(&wc)) { MessageBox(GetParent(ghwndMDIClient), "2RegisterClass call failed.", "ERROR!", MB_OK); return (ULONGLONG)(0); } hwndParent = CreateWindow("CreateDestroyWindow", NULL, WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, ghwndMDIClient, NULL, ghinst, NULL); START_TIMER; while (ix--) { hwnd = CreateWindow("CreateDestroyWindow", "Create/DestroyWindow test", WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndParent, NULL, ghinst, NULL); if (hwnd == NULL) { MessageBox(GetParent(ghwndMDIClient), "CreateWindow call failed.", "ERROR!", MB_OK); break; } DestroyWindow(hwnd); } END_TIMER_NO_RETURN; DestroyWindow(hwndParent); UnregisterClass("CreateDestroyWindow", ghinst); RETURN_STOP_TIME; } LRESULT APIENTRY CreateDestroyWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_SETTEXT: case WM_GETTEXTLENGTH: break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } LRESULT APIENTRY CreateDestroyWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_SETTEXT: case WM_GETTEXTLENGTH: break; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } return 0; } ULONGLONG msProfLocalAllocFree(HDC hdc, ULONG Iter) { HANDLE h1, h2, h3, h4, h5; INIT_TIMER; START_TIMER; // Try to stress the heap a little bit more than just doing a // series of Alloc/Frees. while (ix--) // originally ixAnsi text",(PFN_MS)msProfSendMessageAA, 4000, 0 , (PUCHAR)"SendMessage Ansi->Unicode text",(PFN_MS)msProfSendMessageAW, 4000, 0 , (PUCHAR)"SendMessage Unicode->Ansi text", (PFN_MS)msProfSendMessageWA, 4000, 0, (PUCHAR)"SendMessage Unicode->Unicode text", (PFN_MS)msProfSendMessageWW, 4000, 0, (PUCHAR)"SendMessage - DiffThread",(PFN_MS)msProfSendMessageDiffThread, 1000, 0 , (PUCHAR)"SetWindowLong",(PFN_MS)msProfSetWindowLong, 400, 0 , (PUCHAR)"GetWindowLong",(PFN_MS)msProfGetWindowLong, 2000, 0 , (PUCHAR)"PeekMessageA",(PFN_MS)msProfPeekMessageA, 1000, 0 , (PUCHAR)"PeekMessageW",(PFN_MS)msProfPeekMessageW, 1000, 0 , (PUCHAR)"DispatchMessageA",(PFN_MS)msProfDispatchMessageA, 4000, 0 , (PUCHAR)"DispatchMessageW",(PFN_MS)msProfDispatchMessageW, 4000, 0 , (PUCHAR)"LocalAlloc/Free",(PFN_MS)msProfLocalAllocFree, 2000, 0 , (PUCHAR)"200 Listbox Insert",(PFN_MS)msProfListboxInsert1, 20, 0 , (PUCHAR)"200 Listbox Insert (ownerdraw)",(PFN_MS)msProfListboxInsert2, 20, 0 , (PUCHAR)"200 Listbox Insert (ownerdraw/sorted)",(PFN_MS)msProfListboxInsert3, 20, 0 , (PUCHAR)"GetClientRect",(PFN_MS)msProfGetClientRect, 8000, 0 , (PUCHAR)"ScreenToClient",(PFN_MS)msProfScreenToClient, 8000, 0 , (PUCHAR)"GetInputState",(PFN_MS)msProfGetInputState, 2000, 0 , (PUCHAR)"GetKeyState",(PFN_MS)msProfGetKeyState, 2000, 0 , (PUCHAR)"GetAsyncKeyState",(PFN_MS)msProfGetAsyncKeyState, 8000, 0 , (PUCHAR)"Register|UnregisterClass",(PFN_MS)msProfRegisterClass, 500, 0 , (PUCHAR)"GetClassInfo|Name|Long|SetClassLong",(PFN_MS)msProfClassGroup, 500, 0 , (PUCHAR)"Menu pulldown",(PFN_MS)msProfMenu, 2000, 0 , (PUCHAR)"Open|Empty|Set|Get|CloseClipboard",(PFN_MS)msProfClipboardGroup, 1000, 0 , (PUCHAR)"GetWindowTextLengthA",(PFN_MS)msProfGetWindowTextLengthA, 10000, 0, (PUCHAR)"GetWindowTextLengthW",(PFN_MS)msProfGetWindowTextLengthW, 10000, 0, (PUCHAR)"UdpateWindow",(PFN_MS)msProfUpdateWindow, 10000, 0, (PUCHAR)"TranslateMessage", (PFN_MS)msProfTranslateMessage, 10000, 0, (PUCHAR)"IsCharUpperA", (PFN_MS)msProfCharUpperA, 2000, 0, (PUCHAR)"IsCharLowerA", (PFN_MS)msProfCharLowerA, 2000, 0, (PUCHAR)"IsCharUpperW", (PFN_MS)msProfCharUpperW, 2000, 0, (PUCHAR)"IsCharLowerW", (PFN_MS)msProfCharLowerW, 2000, 0, (PUCHAR)"CharNextA", (PFN_MS)msProfCharNextA, 2000, 0, (PUCHAR)"CharNextW", (PFN_MS)msProfCharNextW, 2000, 0, (PUCHAR)"GetMessageW", (PFN_MS)msProfGetMessageW, 5000, 0, (PUCHAR)"GetMessageA", (PFN_MS)msProfGetMessageA, 5000, 0, // Add New Tests Here }; ULONG gNumTests = sizeof gTestEntry / sizeof gTestEntry[0]; //Total No. of Tests ULONG gNumQTests = 10;// No. of tests in Group 1 (starting from first in the list)