요즘 이 책을 읽고 있는데요.
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=128563714
크로스 플랫폼 개발을 위한 C# 7과 닷넷 코어 2.0
C# 7의 새로운 기능과 닷넷 코어의 전반적인 내용을 다룬다. 설명을 최소한으로 하고 예제를 따라 해보면서 빠르게 익힐 수 있도록 구성되어 있으며, C#의 기본 문법부터 고급 기능, 닷넷 코어를 활용한 콘솔, 데이...
www.aladin.co.kr
프로그램의 메모리 사용량 체크에 관한 코드가 있어서 한번 연습삼아 책을 보고 따라서 만들어 봤습니다.
코드를 보기 전에 다음 2개의 Property를 먼저 알아야 합니다.
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.workingset?view=netcore-3.1
Process.WorkingSet Property (System.Diagnostics)
Gets the associated process's physical memory usage, in bytes.
docs.microsoft.com
이 Property는 현재 process의 physical memory 사용량을 확인할 수 있습니다.
Process.VirtualMemorySize64 Property (System.Diagnostics)
Gets the amount of the virtual memory, in bytes, allocated for the associated process.
docs.microsoft.com
VirtualMemorySize64 는 현재 Process의 가상메모리 사용량을 확인할 수 있습니다.
이 2개의 Property를 가지고 어떤 식으로 프로그램의 메모리 사용량을 체크 하는지 코드를 보겠습니다.
vs code 에서 작성하였습니다.
먼저 Recorder라는 클래스를 만들어 줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
using System;
using System.Diagnostics;
using System.Linq;
using static System.Diagnostics.Process;
using static System.Console;
public class Recorder
{
static Stopwatch timer = new Stopwatch();
static long bytesPhysicalBefore = 0;
static long bytesVirtualBefore = 0;
public static void Start()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
bytesPhysicalBefore = GetCurrentProcess().WorkingSet64;
bytesVirtualBefore = GetCurrentProcess().VirtualMemorySize64;
timer.Restart();
}
public static void Stop()
{
timer.Stop();
long bytesPhysicalAfter = GetCurrentProcess().WorkingSet64;
long bytesVirtualAfter = GetCurrentProcess().VirtualMemorySize64;
WriteLine("Stopped recording.");
WriteLine($"{bytesPhysicalAfter - bytesPhysicalBefore:N0} physical bytes used.");
WriteLine($"{bytesVirtualAfter - bytesVirtualBefore:N0} virtual bytes used.");
WriteLine($"{timer.Elapsed} time span ellapsed");
WriteLine($"{timer.ElapsedMilliseconds:N0} total milliseconds ellapsed.");
}
}
|
cs |
일단 Timer를 사용해서 일정 시간 동안의 메모리 사용량을 체크 하고 있는 것을 볼 수 있습니다.
그리고 Start() method의 16, 18번 줄의 코드를 보면 GC를 발동시켜 주는 코드가 있습니다.
GC는 가비지 컬렉터를 일컷는 말인데요.
메모리를 측정하기 전에 현재 할당된 모든 메모리를 확실하게 정리하기 위해 호출 한다. 하지만 실제로 사용할 일은 없을 것입니다. 라고 정의 하고 있습니다.
참고로 GC에 대한 MSDN 링크 입니다.
https://docs.microsoft.com/ko-kr/dotnet/api/system.gc.collect?view=netframework-4.8
GC.Collect 메서드 (System)
가비지 컬렉션을 수행하도록 합니다.Forces garbage collection.
docs.microsoft.com
다시 본론으로 돌아 가서
이제 Main함수를 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
using System;
using System.Linq;
namespace Monitoring
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press ENTER to start the timer");
Console.ReadLine();
Recorder.Start();
int[] largeArrayOfInts = Enumerable.Range(1, 10000).ToArray();
Console.Write("Press ENTER to stop the timer");
Console.ReadLine();
Recorder.Stop();
Console.ReadLine();
}
}
}
|
cs |
사용자가 Enter를 치면 프로그램을 시작하고 다시 Enter를 입력할 때 까지 메모리 사용량을 체크 하고 마지막에 사용량을 출력하는 코드 입니다.
실행 결과 입니다.
추가 적으로 string or stringbuilder중 어떤 것이 메모리 상으로 더 효율적인지 알아 보는 예제가 있습니다.
기존 코드는 주석을 달아주고 Main 코드를 다음과 같이 작성해 주세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
int[] numbers = Enumerable.Range(1, 10000).ToArray();
Recorder.Start();
Console.WriteLine("using string");
string s = "";
for (int i = 0; i < numbers.Length; i++)
{
s += numbers[i] + ", ";
}
Recorder.Stop();
Recorder.Start();
Console.WriteLine("using StringBuilder");
var builder = new System.Text.StringBuilder();
for (int i= 0; i < numbers.Length; i++)
{
builder.Append(numbers[i]);
builder.Append(", ");
}
Recorder.Stop();
Console.ReadLine();
|
cs |
메모리 사용량 및 성능에서 엄청난 차이를 보이네요.
책에 따르면 문자열을 연결할 때 StringBuilder를 사용하면 속도는 100배 빨라지고 메모리 효율성은 1000배 좋아 진다고 나와 있습니다.
저의 결과물로 계산을 해보니 속도는 80배 좋아 졌고 메모리 효율성은 514배로 나왔습니다.
이 부분은 반드시 숙지하고 있어야 겠습니다.
github 링크
https://github.com/Helloezzi/Monitoring/tree/master
Helloezzi/Monitoring
Memory usage check. Contribute to Helloezzi/Monitoring development by creating an account on GitHub.
github.com
'Programing > dotnet core' 카테고리의 다른 글
[dotnetcore] system.flag를 활용한 enum(열거형) 의 사용법 (0) | 2020.05.11 |
---|---|
지역변수 & 지역변수 추론 (var type) (0) | 2020.03.10 |
[dotnetcore] How to check overflow (산술 오버플로우 검사) checked & unchecked (0) | 2020.02.26 |
dotnetcore : try catch finally vs using (0) | 2020.02.19 |
goto문을 활용한 switch문 (0) | 2020.02.18 |