-
Notifications
You must be signed in to change notification settings - Fork 10
/
0136.txt
242 lines (242 loc) · 12.5 KB
/
0136.txt
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
안녕하세요.
포프입니다.
오늘은 가비지 컬렉션에 대해 좀 얘기를 해보려고 해요.
그 예전에 가비지 컬렉션(garbage collection)보다
뭐 레프 카운트(reference counting)가 개인적으로
좋아하는 이유 이런 얘길 많이 했는데
뭐 지금으로 보면은 사실 재가 일하는 회사가 사실 웹회사이기 때문에
그렇게 순간순간 리얼타임 매 프레임(frame)이 똑같아야되는
그런 성능은 중요하지 않거든요.
사실
뭐...
언제나 최대로 빠르게 돌다가
뭐 가끔 1초 정도 느려지는 거?
뭐 그거야 크게 문제가 아니고
그게 원래 올바른 거라고 생각을 하는데
웬만한 애플리케이션 수준에서도 그럴 거고요.
단지 게임이나 리얼타임으로 매 프레임 돌려대는 거에서
그게 올바르지 않을 뿐이죠.
어쨋든간에 지금 C#을 많이 쓰고 있는 상황에서
음...
일단 뭐 가비지 컬렉션을 쓸 수밖에 없는 거죠.
가비지 컬렉션이
당연히 느릴 수밖에 없어요
생각해보면은 왜냐면
오브젝트 막 만들어 놨다가 어느 순간 메모리(memory)가
어! 없다. 그러면
가비지 컬렉터 들어 오면서
모든 오브젝트를 훑으면서 보는 거에요.
얘가
여기에서 레퍼런스가 몇 번이나 돼 있나. 뭐 이런 식으로
레프 카운트는 아니고
C#은 조금 레프 카운.. 그러니깐 레퍼런스 카운트를
유지하는 게 아니라 다른 방식이라고 하는데
뭐라 그러더라
재가 저...
몇일전에 읽었는데 지금은 기억은 좀 안 나고
(긁적 긁적)
뭐
그냥
고수준에서 생각하면은 더이상
이 개ㄱ.. 문.. 객채? 오브젝트? 오브젝트를 참조하고 있는
다른 객채가 없으면 그냥 가비지 컬렉션이 대두되니깐
그때 가비지 컬렌션 해가지고 치우는 거죠.
근데 이거의 단점은 당연히 볼수있겠지만
모든 오브젝트를 훑어야 되ㄴ..는게 된다는 게 굉장히 느린거건든요.
그래서
몇 년 전에
꾀 됐죠. 사실은
닷넷(.Net)에서 가비지 컬렉션에 옵티마이제이션(optimization)을 하고 도입을 한 게 뭐냐면
시즈널 가비지 컬렌션(seasonal garbage collection)이예요.
물론 이거는
그 완전히
제대로 돼 있는 프레임워크(.NET Framework)에서 되는거고
그 가끔 뭐 엑스박스360라던가 이런 데 들어 갔던
닷넷 프레임워크는 컴팩트 프레임워크(.NET Compact Framework)라고 해서
좀 임베디드쪽으로 들어간 닷넷 프레임워크도 있거든요.
거기서는 시즈널 그 컬렉션 자체자 없었어요.
그리고 뭐 유니티(Unity)에서도 이제 모노(mono)에서 최근에 시즈널 컬렉션 도입 해가고 그것도 한 1년 1년 됐나?
1년? 2년?
에 그래서 가비지 컬렉션이 좀 빨라진 것도 있는데
시즈널 가비지 컬렌터가 작동하는 방법은 이래요.
어떻게 하냐면
물체가 생기면은 그 물체의 라이프타임(lifetime)을 보는거에요. 오브젝트에
그래서 오브젝트가 생겼다.
그러면 그 오브젝트에서
어느 정도 시간까지는 얘를 아, 이거 생긴 지 얼마 안됬으니까 시즌...
zero라고 할까 0이라고 하나? 1부터 시작하나 저는 0이 편하니까 0으로 할게요.
시즌 0에 넣는 거에요.
시즌이라고 하면 계절이잖아요.
그럼 0번 계절 가장 최근 계절
그러고 있다가
메모리가 딱! 가득 찼을 때
그러면 무조건 시즌 0에 있는 오브젝트부터 무조건 치우는 거에요.
가비지 컬렉션을 쫙 하는 거예요.
왜냐면 사람들 프로그래밍 패턴이
C#에서 오브젝트 만들자마자 쓰고 버리는 게 되게 흔한 패턴이기 때문에
그 최근에 만들어지고 버린 오브젝트가 굉장히 많아요.
생각보다 이걸 딱 치웠을 때
메모리가 충분히 돌아왔구나 그러면 더 이상 터치 안하고 계속 진행을 해요.
근데 예를 들어서
시즌이 0이 있던 그 오브젝트가 굉장히 오랫동안 다른
개체나 그거에 의해서 참조가 되어서
오래버티다 보면은 얘네가 시즌 1으로 프로모션 돼요.
너는 오래 있으니까 다음 그 전전 단계라고 해서
그 전 단계 보내고
그다음에 시즌 2까지 있을거야 제가 생각한 시즌이 3개인 것 같은데 더 있을 수도 있고
0, 1, 2이렇게 있는거죠.
0이 가장 최근 거 1이 그것보다 조금 더 오래된 거 2가 정말 오래된거
그래서 이제 3개의 시즌이 있잖아요.
그러면 가비지가 딱 들어왔어 가비지 컬렉션이 그러면
어 처음에 시즌 0을 딱 지워요.
딱 봤는데 아~ 아직도 메모리가 모자라 그러면 시즌 1으로 넘어가요.
그러고 시즌 1을 딱 지워요
가비지 컬렉션을 하는 거죠 다 지우는 게 아니라
더 이상 참조 안 되는 거만
그래서 봐서
메모리가 충분히
충분히 다시 찾아왔다 그러면 거기서 멈추고
그러고 다시
프로세스를 진행을 하고
그게 아니라면은 다시 하나 더 마지막 시즌까지 가서 전부다 긁는 거죠.
그러면 이게 말그대로
전부 시즌을 긁는 게 되는 거에요.
모든.. 모든 오브젝트를 훑게 되는거에요.
그래서
오히려 오브젝트 빨리 만들어서 빨리 버리면은 C#에서는 성능이 오히려 빨라요.
그게 아니라 적당히 어중간하게 잡고 있다가 나중에 풀린다?
그러면 오히려 성능이 느려질 수가 있어요.
뭐 아예 가비지를 안 만든다면 성능은 확실히 좋지만요
그래서
이게
그 가비지 컬렉터가 작동하는 원리에요. 닷넷에서
물론 깊게 들어가면 더 복잡한 게 있겠지만
그게 얘네가 옵티마이제이션하려고 만들어 놓은 거고
최근에 이제
물론 이제 그 가비지 컬렉터 직접 호출할 수 있는 건 알잖아요.
System.GC.Collect()를 호출하면은
뭐 그냥 컬렉트만 하면은 마다 전체다 컬렉트 할거고
그다음에 아마 숫자를 매개변수로 받거든요.
그럼 그 매개변수 따라 뭐 0, 1, 2 뭐 이런 식으로 넣으면은
첫 번째 시즌 두 번째 시즌 세 번째 시즌 이렇게 가비지 컬렉션도 가능하구요.
그래서 얼마 전에
XML시리얼라이저(XmlSerialize) 얘기를 했잖아요.
그 XML시리얼라이저를 물론 그 캐시 해 가지고 뭐
딕셔너리에 넣어 둬서
속도도 빠르게 했고 더이상 메모리 누수도 안나 게 한 건 좋은데
그 외에
또 하나의 단점은
저희 파일을 한번 가비지 컬렉팅을 할때마다
아니 시리얼라이징을 할때마다 XML파일을
가비지가 한
1.5메가(1.5MB) 나왔어요.
일단
그 이유가 리플렉션(Reflection) 시스템을 쓰면 쓸수록
당연히 중간 리플렉션 과정에서 오브젝트를 생성하고
버리는게 많기 때문에
그만큼 가비지가 생기거든요.
그래서
쓰읍(긁적.. 긁적..)
이
문제는 그 서버 자체에서 굉장히 메모리도 많았고
이것저것 하는 짓이 많았기 때문에
어느 순간 이 가비지가 시즈널1에서 안 머무르고 시즌
2?
그니깐 0에서 안 머무르고 1까지 넘어가는 일도 있긴 있더라구요.
보면서 아~~~ 이게 좀
개인적인 입장에서는
솔직히 딱 가비지가 여기서 이만큼 생긴다는 거도 알잖아요.
그때 딱 치워주면 좋잖아요.
근데 그러기 위해서 가비지 컬렉터를
내가 시즌 첫 번째 거에만 계속 호출 해주는 것도 애매하고
한 2메가(2MB) 가비지 생긴거
뭐 XML시리얼라이저 100번하면 200메가니까 메모리에서 뭐 차라리
그때 그때 치워주고 싶은데 방법이 없는 거예요.
그렇다고 가비지 컬렉터를 매번 호출하기도 그렇고
그 시즌
그 지금 0번 시즌에 있는 거 전부다
그래서 생각이 든 게 혹시라도
(긁적 긁적)
이런 게 있으면 어떨까 하는 생각을 했어요.
예를 들어서
C 쪽에서 게임 많이 해보신 분들은 게임 제작해보신 분들은 알겠지만
우리 스택 얼록케이터(stack allocator)라고 해가지고
실제 메모리를 힙(Heap)에서 얼록케이션 하지 않고
스택(stack)에서 계속 올린 다음에
뭐 함수 나갈 때라던가 스코프(scope) 나갈 때 그냥
스택포인터(stack pointer) 되돌아가니까
그러면은 메모리 allocation 빨리 할 수 있잖아요.
뭐...
뭐 엄밀하게 말해서 allocation은 아니지만 스택은 쓰는 거 뿐이니까 그래서
그걸 stack allocator 이렇게 불렀던 사람들도 있고
아니면은
진짜 순수하게 스택에 넣지 않고 힙에 넣는데
힙을 이만큼(많이) 미리 잡아두고
그거를 스택처럼 자기가 다 포인터로 유지해가지고 올라간 다음에
그 범위에서 넘어갈 때 이걸 다시 돌려놓는
그 스택포인터를 원래대로 돌려놔서 다른 그 메모리
필요한 얘들이 거기부터 다시
write 할 수 있는 그러니깐 지울 필요가 없는 거죠. 그냥
그냥 막 write만 하고 다 쓰다가 스택포인터만 돌려 놓는 거니까
그런 식의 패턴을 되게 많이 했었거든요. 사실은
그거를 좀 비슷하게 닷넷에서
그 스코프 가비지 컬렉션이 있으면 어떨까 싶어요.
그러니깐 예를 들어서
그 아까 말했듯이 XML시리얼라이저 하는 거면은 그 함수를 호출하기 전에
가비지 컬렉션 새로운 리전(legion)을 만드는 거죠.
시즌이라고 해서 그래서 뭐
GCStartSeason 아니면 StartLegion 해가지고
거기에다가 하나 열어두고 다음에 이제 XML시리얼라이저 딱 호출하자마자 돌아온 다음에
그 브래킷(bracket) 닫으면 그게 스코프가 넘어가
버리니깐 아니면 뭐 따로 호출 end로 호출해주던가
그러면 알아서 닷넷이 고 요 ㅅ....
범위 안에서 스코프가 있던 범위 안에서 생겼던 오브젝트들 다른
legion에 저장해 주고
딱 그게 끝나는 순간 legion을 훑어가지고
이미 가비지 컬렉션을 할 수 있는 거를 더이상 레퍼런스가 안되는 것들
그냥 가비지 컬렉터 해버리고
남는 거는 그냥 시즌 0으로 다시 던저주고
그래서 이런 식의
stack allocator좀 비슷하고
그런 근데 제가 생각하는 거는 스택 기반
아니지스코프 기반 가비지 컬렉션이라고 해야죠.
그런게 있으면
제 생각에는
그 고성능의 프로그램을 만드는데 굉장히 도움이 되지 않을까 싶어요.
그리고 이거를
뭐라 그럴까
그 스코프가 들어가는 범위 자체가 사실은
쓰레드(Thread) 하나에만 들어가잖아요. 멀티 쓰레드(Multi Thread)가 그 안에 들
(생각중)
실행이 안 된다고 봐야 되잖아요.
멀티 쓰레드가 오면은 다른 쓰레드에 각자 스코프가 생기는 거겠죠.
그렇게 되면은
쓰레드...
멀티 쓰레드
걱정할 이유도 없고
그 오브젝트를 다른 멀티 쓰레드에 던져주지 않는 이상
그런 거만 조금 어떻게
제한을 잘 한다면
쓰레드를 로컬(local)처럼 한 쓰레드에서만 돌고 한 쓰레드에서만 스코프가 생기는
그런 가비지 컬렉션을 지원을 해주면 정말 고성능 프로그램 만들기가 더 좋지 않을까
라는 생각을 해요.
그러면은 아까 말했듯이 2MB씩 가비지 생기는 것도 그냥
거의 가비지를 안 만들고 처리 하는 거고 금방금방
뭐...
그냥 망상인데
물론 닷넷 내부를 훑어보면은
가비지 컬렉터가 좀더 정확히 어떻게 작동하는지 더 훑어보면은
실제 알고리즘이나 이런걸 보면은
제 망상이 아예 틀릴 수도 있어요. 그냥 아예 불가능한 거구나 구조상 그럴 수도 있는데
지금 드는 생각으로는
개인적으로 그런 스코프 기반의 가비지 컬렉션이 가능하면 오히려
정말 성능 빠르고
그때그때 필요 없는 메모리 지워주고
가비지 더더욱 안만들어가지고 프로모션 안되게 하고
그렇게 할 수 있어서 빠르지 않을까라는 망상이 들어서
원래는 그말만 하고 싶었지만
가비지 컬렉션이 어떻게 작동하는지 얘기를 안 하면
또 말이 안 될것 같아서
그거까지 추가해서 어쩔 수 없이 길어진 포프TV였구요.
저는 지금 배고프니까 밥 먹으러 나갈래요.
포프였습니다.