성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>byte[] pData = new byte[100000]로 인한 성능 차이?</h1> <p> 이번에도 데브피아 질문에 대한 답변입니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > new 생성자에 대한 질문입니다. ; <a target='tab' href='http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNO=8&no=140988&ref=140988&page=1'>http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNO=8&no=140988&ref=140988&page=1</a> </pre> <br /> 문제인 즉, 다음과 같이 2가지 방식에 대한 성능 차이를 느낄 수가 없다는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>방식1)</span> while (true) { byte[] pData = new byte[100000]; // pData 에 대한 처리. Thread.Sleep(1); } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>방식2)</span> byte[] pData = new byte[100000]; while (true) { // pData에 대한 처리. Thread.Sleep(1); } </pre> <br /> 그냥 봐도, "방식 1"은 분명히 시스템에 영향을 줄 것이라는 것을 알 수 있습니다. 그런데, 질문을 한 이의 입장에서는 아래와 같은 테스트 코드를 작성해 봤지만, 별다르게 CPU나 메모리 부담을 느낄 수 없다는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > void Function_Th() { while (true) { byte[] pData = new byte[100000]; // pData에 대한 처리. Thread.Sleep(33); } } void main() { for ( int i=0; i<10; i++) { new Thread(new ThreadStart(Function_Th)).Start() } } </pre> <br /> 실제로 (i7 CPU 인 제 컴퓨터에서) 작업 관리자를 보면 전혀 이상이 없어 보입니다. 정말로 부담이 없는 걸까요?<br /> <br /> <hr style='width: 50%' /><br /> <br /> 확인을 위해, 위의 프로그램을 이전에 작성해 두었던 GC 테스트 프로그램을 통해서 비춰보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 윈도우 폼을 열고 닫는 것만으로 메모리 leak이 발생할까? ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/1142'>http://www.sysnet.pe.kr/2/0/1142</a> </pre> <br /> 다음과 같은 결과를 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > GC #0 GC #1 GC #2 Heap WorkingSet Private [13628] 0, 0, 0, 234020, 18395136, 18616320 [13628] 0, 0, 0, 1056124, 23511040, 20045824 [13628] 0, 0, 0, 1788356, 24068096, 20803584 [13628] 0, 0, 0, 2512156, 24616960, 21561344 [13628] <span style='color: blue; font-weight: bold'>0, 0, 0,</span> 3228084, 25153536, 22249472 [13628] <span style='color: blue; font-weight: bold'>11, 11, 11,</span> 1196900, 29716480, 36007936 <----- Thread.Start 시작 이후 [13628] 30, 30, 30, 1197292, 29859840, 36106240 [13628] 49, 49, 49, 1197292, 29970432, 36208640 [13628] 68, 68, 68, 1197292, 29421568, 36106240 [13628] 87, 87, 87, 1197292, 29409280, 35610624 [13628] 106, 106, 106, 1197292, 29978624, 36179968 [13628] 125, 125, 125, 1197292, 29900800, 36311040 [13628] 144, 144, 144, 1197292, 29069312, 35979264 </pre> <br /> 보시는 것처럼 스레드 시작 후부터 GC가 부지런히 활동하면서 메모리를 일정하게 유지하려고 애쓰고 있는 것을 볼 수 있습니다.<br /> <br /> 메모리 관리는 그렇다 치고, 그런데 작업 관리자로 확인한 CPU 사용량도 이상합니다. 거의 0을 유지하고 있거든요. 정말로 GC는 CPU와 무관하게 돌고 있는 것일까요? 물론, 불가능한 상황이지만 그래도 눈으로 확인을 해봐야 직성이 풀릴 것 같습니다. ^^<br /> <br /> 이를 위해서 지난 번의 계측량을 구하는 소스 코드에 프로세스 자체의 CPU 사용량을 구하는 코드를 추가해야 하는데, 다음의 함수를 C#에서 P/Invoke로 사용하면 적당할 듯 싶습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > QueryProcessCycleTime function ; <a target='tab' href='https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryprocesscycletime'>https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryprocesscycletime</a> </pre> <br /> CPU 사용량 변화를 쉽게 확인할 수 있도록 다음과 같이 delta 값을 보이도록 추가했고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [System.Runtime.InteropServices.DllImport("kernel32.dll")] <span style='color: blue; font-weight: bold'>public static extern bool QueryProcessCycleTime(IntPtr hProcess, out long cycleTime);</span> void ThreadFunc(object state) { long oldCycleTime = 0; while (true) { Process currentProcess = Process.GetCurrentProcess(); <span style='color: blue; font-weight: bold'>long cycleTime; QueryProcessCycleTime(currentProcess.Handle, out cycleTime); long deltaCycle = cycleTime - oldCycleTime;</span> string txt = string.Format("{0,6}, {1,6}, {2,6}, {3,10}, {4,10}, {5,10}, <span style='color: blue; font-weight: bold'>{6,10}</span>", GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), GC.GetTotalMemory(false), currentProcess.WorkingSet64, currentProcess.PrivateMemorySize64, <span style='color: blue; font-weight: bold'>deltaCycle</span>); System.Diagnostics.Trace.WriteLine(txt); <span style='color: blue; font-weight: bold'>oldCycleTime = cycleTime;</span> Thread.Sleep(1000 * 2); } } </pre> <br /> 실행해 보면, 예상되는 결과를 보여주게 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > GC #0 GC #1 GC #2 Heap WorkingSet Private # of cpu cycles [13760] 0, 0, 0, 1734372, 24240128, 31555584, 17929179 [13760] 0, 0, 0, 2443708, 24768512, 32247808, 17877155 [13760] 0, 0, 0, 3160836, 25305088, 33005568, 18369483 [13760] 0, 0, 0, 3869452, 25833472, 33697792, 17921554 [13760] 0, 0, 0, 4586180, 26374144, 34390016, 16546720 [13760] 0, 0, 0, 5294716, 26906624, 35147776, 17444334 [13760] 0, 0, 0, 6011444, 27443200, 35840000, 17287101 [13760] 0, 0, 0, 6719900, 26529792, 33251328, <span style='color: blue; font-weight: bold'>17676896</span> [13760] 12, 12, 12, 1196672, 30986240, 37187584, 127745854 <----- Thread.Start 시작 이후 [13760] 31, 31, 31, 1196672, 31305728, 37486592, <span style='color: blue; font-weight: bold'>95881603</span> [13760] 50, 50, 50, 1196672, 31322112, 37584896, 97136948 [13760] 69, 69, 69, 1196672, 31219712, 37388288, 96555172 [13760] 88, 88, 88, 1196672, 31322112, 37486592, 95048736 [13760] 107, 107, 107, 1196672, 31539200, 37822464, 95064560 [13760] 126, 126, 126, 1196844, 31703040, 37900288, 102783980 [13760] 146, 146, 146, 1196844, 31604736, 37797888, 100410108 [13760] 165, 165, 165, 1196844, 31805440, 37998592, 94732637 [13760] 184, 184, 184, 1196844, 31809536, 37998592, 95463257 [13760] 203, 203, 203, 1196844, 31809536, 37998592, 94324847 [13760] 222, 222, 222, 1205036, 31813632, 37998592, 94972692 [13760] 241, 241, 241, 1196844, 31817728, 37998592, 92745471 </pre> <br /> 당연한 결과죠? 평소보다 9배 정도의 CPU Cycle이 해당 프로세스에 할당된 것을 볼 수 있습니다. 즉, GC로 인한 CPU 소비가 분명 높아졌다는 것을 확인할 수 있습니다.<br /> <br /> <a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=642&boardid=331301885'>테스트에 사용되는 소스 코드를 첨부</a>했으니, 결과에 의문이 있으신 분들은 확인해 보시기 바랍니다. ^^<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
6819
(왼쪽의 숫자를 입력해야 합니다.)