¿©±â±îÁö µ¿¿µ»ó Ç÷¹À̾î·Î¼ÀÇ ±âº» ±â´ÉÀº °ÅÀÇ ´Ù ±¸ÇöÇÏ¿´´Ù. ±×·¯³ª
¾ÆÁ÷ »ç¿ëÀÚ¸¦ À§ÇÑ ±â´ÉÀÌ ºÎÁ·ÇÏ¸ç ´õ ¼¶¼¼ÇÏ°Ô Á¶Á¤ÇØ¾ß ÇÒ ±â´ÉÀÌ ¸¹°í ¹ö±×µµ »ó´ç¼ö ³²¾Æ ÀÖ´Ù. ¸î
°¡Áö ÆíÀÇ ±â´É°ú ¾ÕÀ¸·ÎÀÇ °³¹ßÀ» À§ÇÑ Áغñ¸¦ ÇØ º¸ÀÚ.
Á¤È®ÇÑ ÇÁ·Î±×·¥À» ¸¸µé·Á¸é ´õ ´Ù¾çÇÑ Àåºñ¿¡¼ Å×½ºÆ®ÇØ ºÁ¾ß ÇÑ´Ù. ±×¶§¸¶´Ù
ÄÄÆÄÀÏ·¯ ±ò¾Æ ³õ°í µð¹ö±ëÇÒ ¼ö´Â ¾ø´Ù. ·Î±× Ãâ·Â¹®µµ ²À ÇÊ¿äÇÑ °÷¿¡¸¸ Àá½Ã ³Ö±â ¶§¹®¿¡ ¼º´É Á¡°Ë¿ëÀ¸·Î
¾²±â´Â ¾î·Æ´Ù. ±×·¡¼ Áß¿äÇÑ Á¤º¸´Â Ç×»ó È®ÀÎ °¡´ÉÇØ¾ß ÇÑ´Ù. Áø´Ü
Á¤º¸´Â º¯¼ö°¡ ¸¹°í ½ÇÇà°ú Á÷Á¢ÀûÀÎ ¿¬°üÀÌ ¾øÀ¸¹Ç·Î ±¸Á¶Ã¼·Î ¹´Â´Ù.
struct sDiag {
bool
show;
int64_t
arFrameTime[100];
int
ftCount;
double
framerate;
int
sceneCount;
DWORD
scaleTime;
DWORD
rasterTime;
DWORD
drawTime;
TCHAR
info[128];
};
sDiag diag;
show°¡ Áø´Ü Á¤º¸¸¦ Ãâ·ÂÇÑ °ÍÀΰ¡ ¾Æ´Ñ°¡¸¦ ÁöÁ¤ÇÑ´Ù. Áø´Ü º¸±â´Â µð¹ö±× ¸ðµå¿¡¼¸¸ trueÀÌ¸ç ¸±¸®Áî ¸ðµå¿¡¼´Â ±âº»°ªÀÎ falseÀÌ´Ù.
case WM_CREATE:
....
#ifdef _DEBUG
diag.show
= true;
#endif
ÄÚµåÀÇ °÷°÷¿¡¼ Áø´Ü Á¤º¸¸¦ »Ì¾Æ º¸ÀÚ. Ç÷¹À̳ª ºñµð¿À, ¿Àµð¿À ½º·¹µå´Â ½Ã°£À» °ÅÀÇ ¼Ò¸ðÇÏÁö ¾Ê¾Æ ±»ÀÌ ÃøÁ¤ÇØ º¼ ÇÊ¿ä ¾ø´Ù. ¿Àµð¿À´Â
½Ç ÃøÁ¤ÇØ º¸¸é 0.01ms Á¤µµ ¼öÁØÀ̶ó °ü½É ´ë»óÀÌ ¾Æ´Ï´Ù. ½ºÄÉÀÏ·¯ºÎÅÍ
º¸ÀÚ.
LARGE_INTEGER
start, end;
....
QueryPerformanceCounter(&start);
sws_scale(swsCtx[scaler],
vFrame.data, vFrame.linesize, 0, vFrame.height,
fPool[scalepos].RGBFrame.data,
fPool[scalepos].RGBFrame.linesize);
if
(diag.show && scaler == 0) {
QueryPerformanceCounter(&end);
diag.scaleTime
= DWORD((end.QuadPart - start.QuadPart) * 1000000 / frequency.QuadPart);
}
sws_scale È£Ãâ ¾ÕµÚ·Î ½Ã°£À» Àé´Ù. 0¹ø ½ºÄÉÀÏ·¯¸¸ ´ëÇ¥ÀûÀ¸·Î ÃøÁ¤ÇÑ´Ù. ³ª¸ÓÁö ½ºÄÉÀÏ·¯±îÁö ÃøÁ¤Çϸé
°æÀï »óÅ°¡ µÈ´Ù. ±×·¸´Ù°í ½ºÄÉÀÏ·¯º°·Î Áø´Ü°ªÀ» µû·Î °¡Áú ÇÊ¿äµµ ¾ø´Ù. start´Â ±»ÀÌ Á¶°Ç Á¡°ËÇÏÁö ¾Ê¾Ò´Âµ¥ Á¶°Ç Á¡°Ë ½Ã°£ÀÌ ¿ÀÈ÷·Á ´õ °É¸®±â ¶§¹®ÀÌ´Ù. ´ÙÀ½Àº ·¡½ºÅÍÀÇ ¼º´ÉÀ» ÃøÁ¤ÇÑ´Ù.
LARGE_INTEGER
start, end;
....
QueryPerformanceCounter(&start);
fPool[rastpos].bitmap
= CreateBitmap(fPool[rastpos].width, fPool[rastpos].height,
1,
32, fPool[rastpos].RGBFrame.data[0]);
if
(diag.show && raster == 0) {
QueryPerformanceCounter(&end);
diag.rasterTime
= DWORD((end.QuadPart - start.QuadPart) * 1000000 / frequency.QuadPart);
}
ºñÆ®¸Ê Á¦ÀÛ ¾Õ µÚ·Î ½Ã°£À» Àé´Ù. µå·Î¿ì´Â BitBlt È£Ãâ¹®ÀÇ ¼Óµµ¸¦ ÃøÁ¤ÇÑ´Ù. ½Ã°£ÀÌ ¿À·¡ °É¸±¸¸ÇÑ ÀÛ¾÷¸¶´Ù
Áø´Ü Á¤º¸¸¦ ÀÛ¼ºÇß´Ù.
LARGE_INTEGER
start, end;
....
QueryPerformanceCounter(&start);
if
(pf->width == crt.right || pf->height == crt.bottom || op.allowStretch ==
false) {
BitBlt(hdc,
pt.x, pt.y, pt.x + pf->width, pt.y + pf->height, MemDC, 0, 0, SRCCOPY);
}
else {
StretchBlt(hdc,
pt.x, pt.y, bitsize.cx, bitsize.cy,
MemDC,
0, 0, pf->width, pf->height, SRCCOPY);
}
if
(diag.show) {
QueryPerformanceCounter(&end);
diag.drawTime
= DWORD((end.QuadPart - start.QuadPart) * 1000000 / frequency.QuadPart);
}
ÇÁ·¹ÀÓ·¹ÀÌÆ®´Â µå·Î¿ì¿¡¼ ±¸ÇÑ´Ù. ÃÖÃÊ º¯¼ö¸¦ ÃÖ´ëÇÑ Àû°Ô ¾²±â À§ÇØ
Æò±Õ ÇÁ·¹ÀÓ °£°Ý¸¸ ±¸Çß´Ù. ¿¹¸¦ µé¾î ¼¼ °ú¸ñ Æò±Õ ¼ºÀûÀ» ±¸ÇÑ´Ù¸é ´ÙÀ½°ú °°ÀÌ ÇÏ¸ç »õ ¼ºÀû 50Á¡ÀÌ µé¾î ¿Ô´Ù¸é »õ·Î¿î Æò±ÕÀº ´ÙÀ½°ú °°ÀÌ °è»êÇÑ´Ù.
Æò±Õ = (70 + 80 + 90) / 3 = 80
Æò±Õ = (80 * 3 + 50) / 4
ÀÌ¹Ì ±¸ÇØ ³õÀº 3°ú¸ñÀÇ Æò±Õ 80Á¡¿¡
°ú¸ñ ¼ö¸¦ °öÇÏ°í ¿©±â¿¡ »õ ¼ºÀû 50À» ´õÇϸé ÃÑÁ¡ÀÌ´Ù. ÀÌ
¹æ¹ýÀ¸·Î ÇÁ·¹ÀÓ·¹ÀÌÆ®¸¦ ±¸Çصµ °ÅÀÇ Á¤È®Çѵ¥ À§Ä¡¸¦ À̵¿Çϰųª ¸®»çÀÌÁîÇÏ¸é ¾ÕºÎºÐÀÇ Æò±Õ ¶§¹®¿¡ ¼ø°£ ¼Óµµ¸¦ ±¸Çϱ⠾î·Á¿ü´Ù. ±×·¡¼ Å©±â 100ÀÇ ¹è¿À» ¼±¾ðÇÏ°í °¢ ÇÁ·¹ÀÓÀÇ °£°ÝÀ» ÀúÀåÇØ
µÐ´Ù.
if (diag.ftCount == 100) {
memmove(diag.arFrameTime,
&diag.arFrameTime[1], sizeof(diag.arFrameTime[1]) * 99);
diag.ftCount--;
}
diag.arFrameTime[diag.ftCount] = elapse + (delay
> 0 ? delay : 0);
diag.ftCount++;
diag.sceneCount++;
if (delay > 0 && isResize == false) {
....
100°³°¡ °¡µæÂ÷¸é Á¦ÀÏ ¾ÕÀÇ Çϳª´Â Áö¿ì°í ´Ù½Ã ä¿ö ³Ö´Â´Ù. ´ÙÀ½Àº CPU Á¡À¯À²À» Á¶»çÇÑ´Ù.
¼º´ÉÀÌ Áß¿äÇÑ ÇÁ·Î±×·¥ÀÌ Ç×»ó °ü½ÉÀ» °¡Á®¾ß ÇÏ´Â ´ë»óÀÌ´Ù. ´ÙÀ½ À¯Æ¿¸®Æ¼ Ŭ·¡½º¸¦ ÀÛ¼ºÇÑ´Ù.
#include "pdh.h"
#pragma comment(lib, "pdh.lib")
class CpuUsage {
PDH_HQUERY
query;
PDH_HCOUNTER
usage;
public:
CpuUsage()
{
PdhOpenQuery(NULL,
NULL, &query);
PdhAddCounter(query,
TEXT("\\Processor(_Total)\\% Processor Time"), NULL, &usage);
}
~CpuUsage()
{
PdhCloseQuery(&query);
}
double
GetUsage() {
PDH_FMT_COUNTERVALUE
value;
PdhCollectQueryData(query);
PdhGetFormattedCounterValue(usage,
PDH_FMT_DOUBLE, NULL, &value);
return
value.doubleValue;
}
};
CpuUsage usage;
°ø½Ä API¸¦ Âü°íÇؼ ÀÛ¼ºÇߴµ¥ Á» °ú¼Ò Æò°¡ÇÏ´Â °æÇâÀÌ ÀÖ¾î ÀÛ¾÷
°ü¸®ÀÚ·Î ÃøÁ¤ÇÏ´Â °Í°ú´Â ¾à°£ Â÷ÀÌ°¡ ÀÖ´Ù.
ÀÌ·¸°Ô ¸ðÀº Á¤º¸¸¦ Âï¾î º¸ÀÚ. µð¹ö±ë Á¤º¸¶ó°í Çؼ ŸÀÌƲ ¹Ù µûÀ§¿¡
´ëÃæ Âï¾î º¸¸é ¾ÈµÈ´Ù. ½º·¹µå¿¡¼ ¸ÞÀο¡°Ô ¸Þ½ÃÁö¸¦ º¸³»¸é Á¾·áÇÒ ¶§ µ¥µå¶ô¿¡ °É¸± ¼ö ÀÖ´Ù. ´ÙÀ½ ÇÔ¼ö·Î Ãâ·ÂÇÑ´Ù.
void OutDiagInfo(HDC hdc, sFrame* pFrame, double
framerate, int64_t gap) {
HFONT
hFont, hOldFont;
TCHAR
tStatus[128] = TEXT("");
int64_t
sum, avgTime;
double
avgFrameRate = 0;
hFont
= CreateFont(24, 0, 0, 0, 0, 0, 0, 0, ANSI_CHARSET, 3, 2, 1,
VARIABLE_PITCH
| FF_SWISS, TEXT("Arial"));
if
(diag.sceneCount % int(framerate) == 0) {
for
(int i = 0; i < fsize; i++) {
switch
(fPool[i].status) {
case
F_EMPTY:lstrcat(tStatus, TEXT("E")); break;
case
F_FRAME:lstrcat(tStatus, TEXT("F")); break;
case
F_SCALING:lstrcat(tStatus, TEXT("s")); break;
case
F_SCALE:lstrcat(tStatus, TEXT("S")); break;
case
F_RASTERING:lstrcat(tStatus, TEXT("r")); break;
case
F_RASTER:lstrcat(tStatus, TEXT("R")); break;
case
F_DRAW:lstrcat(tStatus, TEXT("D")); break;
}
}
if
(diag.ftCount != 0) {
sum
= 0;
for
(int i = 0; i < diag.ftCount; i++) {
sum
+= diag.arFrameTime[i];
}
avgTime
= sum / diag.ftCount;
avgFrameRate
= 1000000.0 / avgTime;
}
_stprintf_s(diag.info,
128, TEXT("%.1f%% %.2ffps va:%5dms , %s(%d), ")
TEXT("S:%.1f->R:%.1f->D:%.1f"),
usage.GetUsage(),
avgFrameRate,
(int)(gap / 1000), tStatus, fput, diag.scaleTime / 1000.0,
diag.rasterTime
/ 1000.0, diag.drawTime / 1000.0);
}
hOldFont
= (HFONT)SelectObject(hdc, hFont);
TextOut(hdc,
10, pFrame->height - 26, diag.info, lstrlen(diag.info));
SelectObject(hdc,
hOldFont);
DeleteObject(hFont);
}
³Ê¹« °í¼ÓÀ¸·Î Ãâ·ÂÇϸé Àб⠾î·Á¿ö ÇÁ·¹ÀÓ·¹ÀÌÆ®¿Í µ¿±âÈÇß´Ù. ´ë·« 1ÃÊ¿¡ Çѹø²Ã·Î Áø´Ü Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù. µå·Î¿ì ½º·¹µå¿¡¼ ºñÆ®¸Ê Ãâ·ÂÀü¿¡
ºñÆ®¸Ê À§¿¡ Âï¾îº»´Ù.
if
(diag.show) {
OutDiagInfo(MemDC,
pf, framerate, vagap);
}
QueryPerformanceCounter(&start);
¿µ»óÀÇ ÁÂÇÏ´Ü¿¡ Á¶»çÇÑ Áø´Ü Á¤º¸°¡ Ãâ·ÂµÈ´Ù. Áø´Ü Á¤º¸´Â °³¹ß¿¡´Â
À¯¿ëÇÏÁö¸¸ ¿µ»ó °¨»ó¿¡´Â ¹æÇØ°¡ µÈ´Ù. ½ÇÇàÁß¿¡ ²ø ¼ö ÀÖ¾î¾ß Çϴµ¥ ÆгÎÀ» ´õºíŬ¸¯ÇÒ ¶§ Áø´Ü Á¤º¸
º¸±â¸¦ Åä±ÛÇÑ´Ù.
LRESULT CALLBACK PanelWndProc(HWND hWnd, UINT
iMessage, WPARAM wParam, LPARAM lParam) {
case
WM_LBUTTONDBLCLK:
diag.show
= !diag.show;
return
0;
Áø´Ü Á¤º¸´Â µð¹ö±ë Á¤º¸°¡ ¾Æ´Ï¶ó ¾ÈÁ¤ÈµÉ ¶§±îÁö Ç×»ó ÀÖ¾î¾ß ÇÏ´Â Âü°í ±â´ÉÀÌ´Ù. µð¹ö±× ¹öÀüÀÌ¸é µðÆúÆ®°ª¸¸ ´Ù¸¦ »Ó ¾ðÁ¦µçÁö ÀÌ ±â´ÉÀ» ÄѼ Áø´ÜÇØ º¼ ¼ö ÀÖ´Ù. ¸±¸®Áî ¸ðµå¿¡¼´Â ±âº»ÀûÀ¸·Î ¼û°ÜÁ® ÀÖ¾î »ç¿ëÀÚ°¡ ÀÌ ±â´ÉÀ» ¹ß°ßÇϱ⠾î·Æ´Ù.