7-1.Áø´Ü Á¤º¸ Ãâ·Â

¿©±â±îÁö µ¿¿µ»ó Ç÷¹À̾î·Î¼­ÀÇ ±âº» ±â´ÉÀº °ÅÀÇ ´Ù ±¸ÇöÇÏ¿´´Ù. ±×·¯³ª ¾ÆÁ÷ »ç¿ëÀÚ¸¦ À§ÇÑ ±â´ÉÀÌ ºÎÁ·ÇÏ¸ç ´õ ¼¶¼¼ÇÏ°Ô Á¶Á¤ÇØ¾ß ÇÒ ±â´ÉÀÌ ¸¹°í ¹ö±×µµ »ó´ç¼ö ³²¾Æ ÀÖ´Ù. ¸î °¡Áö ÆíÀÇ ±â´É°ú ¾ÕÀ¸·ÎÀÇ °³¹ßÀ» À§ÇÑ Áغñ¸¦ ÇØ º¸ÀÚ.

Á¤È®ÇÑ ÇÁ·Î±×·¥À» ¸¸µé·Á¸é ´õ ´Ù¾çÇÑ Àåºñ¿¡¼­ Å×½ºÆ®ÇØ ºÁ¾ß ÇÑ´Ù. ±×¶§¸¶´Ù ÄÄÆÄÀÏ·¯ ±ò¾Æ ³õ°í µð¹ö±ëÇÒ ¼ö´Â ¾ø´Ù. ·Î±× Ãâ·Â¹®µµ ²À ÇÊ¿äÇÑ °÷¿¡¸¸ Àá½Ã ³Ö±â ¶§¹®¿¡ ¼º´É Á¡°Ë¿ëÀ¸·Î ¾²±â´Â ¾î·Æ´Ù. ±×·¡¼­ Áß¿äÇÑ Á¤º¸´Â Ç×»ó È®ÀÎ °¡´ÉÇØ¾ß ÇÑ´Ù. Áø´Ü Á¤º¸´Â º¯¼ö°¡ ¸¹°í ½ÇÇà°ú Á÷Á¢ÀûÀÎ ¿¬°üÀÌ ¾øÀ¸¹Ç·Î ±¸Á¶Ã¼·Î ¹­´Â´Ù.

 

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;

 

Áø´Ü Á¤º¸´Â µð¹ö±ë Á¤º¸°¡ ¾Æ´Ï¶ó ¾ÈÁ¤È­µÉ ¶§±îÁö Ç×»ó ÀÖ¾î¾ß ÇÏ´Â Âü°í ±â´ÉÀÌ´Ù. µð¹ö±× ¹öÀüÀÌ¸é µðÆúÆ®°ª¸¸ ´Ù¸¦ »Ó ¾ðÁ¦µçÁö ÀÌ ±â´ÉÀ» ÄѼ­ Áø´ÜÇØ º¼ ¼ö ÀÖ´Ù. ¸±¸®Áî ¸ðµå¿¡¼­´Â ±âº»ÀûÀ¸·Î ¼û°ÜÁ® ÀÖ¾î »ç¿ëÀÚ°¡ ÀÌ ±â´ÉÀ» ¹ß°ßÇϱ⠾î·Æ´Ù.