'전산'에 해당되는 글 131

  1. 2010/02/09 LUA 를 이용한 RPC
  2. 2009/09/11 lock-free 와 최적화 (9)
  3. 2009/09/09 volatile 과 memory barrier (2)
  4. 2009/09/07 TDD (4)
  5. 2009/06/11 undefined behavior (4)
  6. 2009/06/11 객체 모델링 (2)
  7. 2009/03/20 짐승같이 일해서 버그를 늘려보세... (2)
  8. 2009/02/22 C++ 하면서 먹고 살기 (12)
  9. 2009/01/22 MS Windows 포커스 테스트 (9)
  10. 2009/01/21 병역특례 프로그래머 모집합니다. (4)

LUA 를 이용한 RPC

전산 2010/02/09 10:16
코드 :

실행결과 :

CALL_HANDLER 에 장난을 쳐주면 RPC 로 동작할 수 있다. 확장시키면 리모트의 객체 참조 및 대입등도 가능한데 한번 해서 프로젝트에 적용해 보려다가 갑자기 이게 뭐하는 짓인가 싶어서 관둠.

메타프로그래밍이란건 일단 재밌는데다가 근사해 보이기도 하지만.. 사실은 제한적이고도 쓸데 없는, 사악한 것이 될 가능성이 큰 관계로 너무 빠져들지 않는게 좋다.
2010/02/09 10:16 2010/02/09 10:16

lock-free 와 최적화

전산 2009/09/11 19:34
나는 lock-free 를 사용하지 않는다. 성능이득은 거의 미미한데 비해 투자비용이 너무 과다하다고 생각하기 때문이다. lock-free 같은 하드코어 튜닝 기법 관련해서는 Eric S. Raymond 본좌의 이야기를 경청할 필요가 있겠다.


시간복잡도를 변화시키는 최적화라면 모를까, 선형적인 성능향상은 쓸데없는 짓이며 무어의 법칙앞에 무력할 뿐이라는 얘기인데 나는 저 의견에 동의한다. 링크 따라 가보면 그런짓 할시간에 딴걸 더 만들라고 충고하고 있다. Eric S. Raymond 스스로가 개발자 이므로 피가 되고 살이 되는 이야기를 저렇게 명쾌하게 해줄 수 있는것 같다.

사실 최근에는 무어의 법칙이 한계에 다다라서, 코어를 좀 더 단순하게, 그리고 많이 박는쪽으로 나가고 있다 보니 저 이야기가 진리만은 아니다. 하지만 그렇다 해도 게임에서의 lock-free 는 성능이득이 너무 작다. 내가 커널이나 디바이스 드라이버를 만들거나 혹은 진짜 시간이 남아돌지 않는 이상, lock-free 를 쓰는 일은 없을 것 같다.
2009/09/11 19:34 2009/09/11 19:34
volatile 과 메모리 베리어의 이해부족으로 인한 잘못된 정보가 인터넷에 꽤 널려있다. 특히 한글 문서에서 미묘한 오류를 포함하고 있는 문서가 많이 발견되는것 같다. OOE(Out of order execution) 는 컴파일러와 프로세서에 의해 일어날 수 있는데 어지간한 지식 없이는 메모리 베리어를 제대로 이해하기 힘들다. 오류의 발생 빈도가 낮아재현과 해결이 무척 힘든 부분이기 때문에, 개념부터 바닥의 디테일까지 확실하게 이해해야할 필요가 있다.

관련해서 f군과 수집한 몇가지 자료들을 추천해 본다.

* Eric Eilebrecht - Fun programming problem: a simple lock-free algorithm
* Jonathan Morrison - How Does KeMemoryBarrier Work
* Bartosz Milewski - Who ordered memory fences on an x86?
* David Howells - Linux Kernel Memory barriers

자신은 제대로 이해하고 있고, 응용에도 강하다고 생각한다면 아래의 연습문제를 풀어보자.

1. 인라인 어셈블리는 왜 컴파일러 메모리 베리어로 기능하는가?
2. 컴파일러 메모리 베리어와 프로세서 메모리 베리어는 왜 구분해서 사용되어야 하는가?
3. 크리티컬 섹션이나 뮤텍스 등 동기화 객체로 코드를 동기화하면 메모리 베리어 효과가 발생한다. 그 이유는 무엇인가?

덧. 나라면 여차하면 삑사리 나는짓 하지 않고 그냥 동기화 객체 쓴다.
2009/09/09 19:16 2009/09/09 19:16

TDD

전산 2009/09/07 22:07

나는 TDD 의 장점이 두 가지가 있다고 생각한다.

 

우선 첫 번째는살다 보면 예전에 만들어둔 코드가 이후의 수정 때문에 문제가 생기는 경우가 가끔 있다. 그런데 TDD 로 개발해 왔다면 이전에 작성해 둔 테스트를 활용 할 수 있기 때문에 이런 문제 발견이 쉬워진다. 대신, 코드 인터페이스 변경 시에는 기존의 테스트들도 고쳐주는 수고를 감수해야 할 것이다.

 

두 번째로, TDD 는 결합도(coupling) 낮은 디자인을 유도한다. 코드를 테스트 가능하게 만들려면 인터페이스가 명확해야 하고 어떻게든 다른 모듈과의 관계를 제거하거나 줄여야만 한다. 일반적으로 결합도가 낮은 코드는 좋은 디자인일 확률이 높기 때문에 모든 코드를 테스트 가능하게 유지하다 보면 전체적인 코드 수준도 좋아진다.

 

위와 같은 이유로, 기존의 프로젝트에 TDD 를 적용하는 것은 불가능하다고 본다. TDD 는 좋은 디자인을 유도할 뿐이지 이미 존재하는 나쁜 디자인을 좋은 디자인으로 변화시키지는 않기 때문이다. 켄트 벡은 기존 프로젝트에 TDD 를 어떻게 적용하냐는 질문에 책에서 그것은 책 한권으로 설명해야 하는 분량이다라는 답을 한것 같은데 내 생각에 기존 코드를 테스트 가능하게 만드는 방법은 없다. 그냥 새로 짜는게 빠르고 효율적일거다.

 

그렇다면 Testors는 모든 것을 TDD 로 개발하느냐..? 그렇지 않다. 나는 에반젤리스트도, 방법론자도 아니다. 뭔가가 새로 나오면 그것이 필드에서 실제로 동작하는걸 확인하지 않는 이상은 도입을 꺼린다. 좋은 방법론 1~2년쯤 늦게 도입한다 해서 프로젝트가 망하지는 않는다. 구지 리스크를 감수할 필요 없이 나 빼고 남들이 다 써서 긍정적인 효과가 명백히 드러날때에 써도 늦지 않다.

 

만약 내가 엔진이나 라이브러리나 웹, 혹은 비즈니스 로직을 주로 다루는 프로그래머였다면 대부분을 TDD 로 작성했을지 모르겠다. 하지만 나는 온라인 게임 프로그래머이고(였고) 게임에서 발생하는 상황에 대한 테스트 케이스를 작성하는 것은 쉽지 않다. 이건 숫자들의 합을 더하는 수준의 문제가 아니다. 결합도를 없애는 것만이 능사가 아니며 효율을 위해 어느정도의 관계는 분명히 유지시켜야 한다.

 

사실 TDD 라는 용어를 접하기 전부터 길찾기라던가 기타 게임 개발에 필요한 기하 문제들을 풀때는 항상 테스트를 작성했었다. input & output 이 명확한 이런 문제들을 테스트를 작성하지 않고 작업하는 사람이 정말 근성가이라고 본다.

 

3년쯤 전인가 회사의 UI 엔진을 스크립팅 가능하게 리뉴얼 하는 작업을 한 적이 있었다. 기존의 엔진은 폼 디자이너 툴만이 제공되었는데 이걸 기존 C++ 코드 & 리소스들과의 하위호환성을 유지하면서 루아 스크립팅 & 시뮬레이션이 가능하도록 만드게 목표였다. 작업은 순조로워서 엔진과 툴 모두 쓸만한 수준으로 부작용 없이 리뉴얼 할 수 있었다. 이후 UI 들은 자체 테스트를 내장한 채로 개발이 되었었다. 그런데 어떤 경우들은 테스트 작성 비용이 재현 및 디버깅 비용을 넘어서기도 했다.

 

게임 프로그래밍이란게 그렇다. input output 을 명확하게 정의하기 힘들다. 시간의 흐름도 중요하고 타이밍도 중요하다. 몇몇 특정한 상태에 대한 테스트를 작성하고 유지하는것에 대한 비용은 정말이지 엄청나게 커질 수 있다. 내가 취한 방법은 대부분의 UI 들에서 테스트 작성을 포기하고, 런타임에 재현 및 디버깅이 쉽도록 한 것이었다. 키 하나로 스크립트가 모두 reload 되고, UI 가 문제 발생 이전으로 리셋되는 식이었다.

 

요약하자면, TDD 는 사실 패턴과 마찬가지로 이전부터 쓰는 사람은 모두 써왔던 방법이고, 그게 모든 분야에 사용되고 있지 않은 이유는 당연하게도 TDD 모든것에 대한 해답이 될 수 없기 때문이라고 생각한다. (난 사실 TDD 가 적용될 수 있는 분야가 매우 한정적이라고 생각한다) 문제는 이런글 (http://testors.net/tt/625)들이 귀 얇은 친구들을 혹세무민하여 주화입마에 빠지게 하는것에 있다. (이 대목에서 모 군이 찔려할것 같다...)

 

만약 TDD 가 정말로 결함을 줄여주고 개발 기간을 단축시켜 준다면 (참고: 난 이런 개발 효율이 측정 가능하지 않다고 생각한다), TDD 를 도입하지 않은것을 불안해 할 필요가 없다. 그게 사실이라면 어느샌가 당신 주변의 대부분의 개발자들이 TDD 를 사용해 프로젝트를 진행하고 있게 될거다. 그때 관심 가져도 늦지 않을것 같다.

2009/09/07 22:07 2009/09/07 22:07

undefined behavior

전산 2009/06/11 01:30
C/C++ 같은 언어를 다루다 보면 아무래도 사람인 이상 메모리를 꽤나 깨먹게 된다. 표준에는 그냥 간단히 undefined behavior 라고 해서 "니가 잘못한거니까 무슨일이 일어나도 놀라지 마셈~" 정도로 다루고 있는데 이런 정의되지 않은 동작을 대했을때 프로그래머의 대응이 난 중요하다고 본다.

얼마전 키즈에 이런 질문 (#2) 이 올라왔었는데 대번에 붙는 대답이 "그건 99% 님이 메모리를 깨먹어서 그런거임." 이라던가 "부동소수점은 == 로 비교하면 안됨" 같은 대답이 달렸었다. 사실 저건 extended floating point 변환 문제였고 다른분이 http://kldp.org/node/105975 에 해답을 주셨다. (참고로 중간에 How not to program in C++(2003) 책에 소개되어 있는 문제라고 하는분이 있는데 그 책의 해당 내용은 그냥 일반적인 부동소수점 유효숫자 내용으로 본래 문제와 별 상관이 없는걸로 알고있다.)

원 질문자의 소스코드를 보고서는 저건 메모리 문제가 아니라는걸 알아챌 수 있다면 좋을 것이다. 사실 힌트는 충분히 있었다. 이미 printf() 가 앞뒤로 정상 동작했기에 스택은 최소한 수행 결과를 왜곡할 만큼 심각하게 망가지지 않았다는걸 알 수 있고, 메모리가 밀린경우 부동소수점이 0.00001 식으로 사람이 읽기 좋게 떨어지는 경우는 거의 드물기 때문이다. 그리고 단순히 메모리를 읽기만 하는 독립적인 명령어들의 순서를 바꿨는데 결과가 달라졌다면 이건 최적화등과 관계가 있다는것도 알 수 있다.

"메모리를 깨먹었겠지" 라는건 달콤한 유혹이다. 이건 '내가 모르는 모든 문제들' 에 대해 항상그럴듯한 답변이 되어줄 수 있기 때문이다. 어떤 문제가 발생했는데 인과관계를 증명하기도 전에 근처 어딘가에 숨어있던 메모리 버그를 발견하고 "이것 때문이었군!" 하고 탐색을 중단하는 프로그래머를 주변에서 많이 봤다. (사실 고백하자면 내가 그랬었다. -_-;) 물론 그것으로 해결되지 않는 문제들이 많았다.

그래서 나는 undefined behavior 가 일어났을때, 왜 그런 결과가 나왔는지 증명하는 것을 권장한다. 어떤 예외가 발생했는지, 어디의 메모리를 접근하다 문제가 터졌는지, vtbl 은 어떻게 되어 있는지, 스택과 레지스터의 상태는 어떤지 등등.. 리버서 수준까지 될 필요는 없다. 그냥 예외정보가 확실한지 증명만 하면 된다.

진짜 이렇게 까지 하면서 프로그래밍 해야되나 싶지만 C/C++ 이란게 원래 좀 그렇다. -_-
2009/06/11 01:30 2009/06/11 01:30

객체 모델링

전산 2009/06/11 01:07
http://gpgstudy.com/forum/viewtopic.php?t=23443

OOP 모델링을 한방에 잘 해내는것은 무척 어렵다. 링크에서 보듯 사람을 버스에 태운다는 간단한 개념도 의견을 모으기가 힘든데 하물며 처음 접해보는 것을 모델링 하는것은 얼마나 어렵겠는가...

구현 도중에 기획이 휙휙 바뀌는 게임 개발쪽에 한참 있어서 그런지 모르겠는데, 나는 그냥 고민할 시간에 일단 대충 돌아가는걸 만들고 나중에 이게 아니다 싶으면 리팩토링 하자는 주의다. 스타일상의 문제도 있겠지만, 내경우는 백날 고민하는 것보다 한번 덤벼서 깨져 보는게 대상을 이해하는데 더 빨랐다.

사실 하드코딩이나 개념적으로 세련되지 못한 디자인은 리팩토링 하기 그다지 어렵지 않다고 본다. 리팩토링 하기 어려운건 설계상의 문제보다는 매직넘버, 중복코드등 코딩 스타일 문제인 경우가 더 많다.

개인적으로도 남의 코드 넘겨받을때는 개념적으로 오류가 없이 잘 추상화된 코드는 그닥 좋아하지 않는다. (설계자의 사고를 그대로 다시 따라가 보아야 하기 때문이다.) 사실 real world 가 세련되게 추상화 될 수 있다고 믿지도 않고... 차라리 하드코드를 보는게 속 편했었다.

덧. 링크에 대한 질문에 대한거라면 구지 탑승에 대한 구현을 둘 중 하나에 둬야한다면 난 bus 에 있는게 맞다고 본다.긴말 필요 없이 Human.h 에다가 #include "Vehicle.h" 를 타이핑 하는 순간 아 이건 뭐가 좀 아니다라는 생각이 들어야 하지 않겠는가..?
2009/06/11 01:07 2009/06/11 01:07
어느날인가 잠깐동안 프로그램 팀장 아저씨의 MSN 닉이 "짐승같이 일해서 버그를 늘려보세" 였는데...

이제 프로그램팀의 팀 구호가 된듯...

너도나도 따라하고 있다.. -_-;;;;
2009/03/20 00:28 2009/03/20 00:28
면접 할때면 간혹 C++ 로우레벨 문제들을 질문하곤 한다. 혹자로부터 "너무 문제를 위한 문제가 아니냐, 그런거 몰라도 게임 충분히 만들 수 있다." 라는 지적도 받았는데 나 역시 C++ 을 어느정도만 해도 충분히 좋은 게임을 만들 수 있다고 생각한다. 아니, 조금 더 정확하게 말하자면 "게임 만드는데 충분히 참여할 수 있다." 라고 해야겠다.
 
C++ 의 tricky 한 면을 속속들이 알고 있는 팀원만으로 팀을 꾸릴 수 있다면 참 좋겠지만 현실적으로 그것은 불가능한 얘기이고, 난 이상주의자가 아니다. 타협점은 적어도 팀에 한명정도는 저런 골치아픈 문제를 해결할 수 있는 개발자를 두는 것이다. 만약 조직에 그럴 수 있는 개발자가 없다면 팀의 종착지는 둘 중 하나다. 문제가 발생하지 않기를 기도하며 그대로 전진하거나(발생 확률이 낮다면 충분히 상용화 해서 성공할 수도 있다) 혹은 좌초하거나.

질문을 던지는 이유는 떨어트리기 위함이 아니라 그것을 해결해 줄 수 있는 사람인지 아닌지 알아보기 위함일 뿐이다. 언젠가 Linus 가 이런 얘기를 한적이 있다.

“C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it. [...] C++ leads to really really bad design choices. You invariably start using [...] STL and Boost and other total and utter crap [...] and anybody who tells me that STL and especially Boost are stable and portable is just so full of BS that it’s not even funny. [C++ leads to] inefficient abstracted programming models. [...]  The only way to do good, efficient, and system-level and portable C++ [...] is limiting your project to C [which] means that you get a lot of programmers that do actually understand low-level issues and don’t screw things up with any idiotic ‘object model’ crap.”

표현이 격하긴 하지만 나는 저 주장의 몇몇 부분들에 진심으로 동의한다. C++ 은 많은 설계 결함을 가진 끔찍한 언어인게 사실이고 때문에 컴파일러 뒤편에 숨겨진 빌어먹을 일들에 대해 속속들히 알고 있어야 제대로 쓸 수 있다.

다른 얘기로, 지금 C++ 을 쓸수밖에 없다면 그 모든걸 누군가는 알아야만 한다는 거다. 만약 그게 자신이라면 더욱 좋을 것이다.
2009/02/22 23:53 2009/02/22 23:53

관련링크 : 팝업창은 키보드 포커스를 빼앗으면 안됩니다. 

평소에 MS Windows 를 쓰다보면 프로그램 실행 후에 로딩이 되는동안 다른 작업을 하고 있으면 로딩을 다 마친 프로그램이 짠 하고 나타나면서 포커스를 빼앗아 가는것에 매우 분노를 느끼고 있었다. 이런 것은 X Windows 나 맥에서는 거의 경험해 보지 못했기 때문에 새 윈도우를 띄울때 포커스를 가져가는것을 기본 동작으로 해놓은 MS 에 굉장히 반감을 가지고 있었는데....

윗 링크의 object 님의 글에서 댓글을 달다 보니 object 님의 테스트 결과로는 파폭, 아이튠즈, 기타등등 모두 로딩이 완료되어도 포커스를 빼앗기지 않았다는 거다. 어라? 그럼 내가 겪었던 그 불쾌한 경험들은 모두 무어란 말인가... 싶어 나도 테스트를 해 보았다.

그랬더니... 어? 정말 object님 말대로 포커스가 안옮겨지네...? 뭐지? 뭐지? 난 뭘 봤던거지..? 라면서 테스트를 반복하다가 순간 경악...

.
.
.
.
.
.


하다보면 가끔 포커스가 강제로 옮겨간다.  -_-;;;;;;


아니.. 일관성조차 없었단 말야? 라며 더욱 분노하였는데.... 아래는 동영상으로 찍어놓은것이다. 볼륨을 올리면 클릭소리가 들린다.



동영상을 보면 아이튠즈를 실행하고 웹브라우저로 포커스를 옮겨 놓았는데 아이튠즈 로딩이 완료되면서 포커스를 강제로 가져가는것을 볼 수 있다. 그런데 웃긴것은 두번째 테스트에는 포커스가 옮겨가지 않는다는것. 세번째 테스트는 사파리로 한것인데 역시 로딩이 끝나고 강제로 포커스를 가져간다. 노파심에 덧붙이자면, 나는 절대 온갖 쉐어웨어 태스크바나 빌어먹을 패커드벨 구식 컴퓨터를 사용하고 있는게 아니다. oTL

사실 동영상처럼 저렇게 자주 발생하지는 않는다. 대략 10% 정도인것 같은데 당시 PC 의 버벅거림 상황에 따라 확률은 매우 달라진다.

링크글에도 걸었지만 나는 포커스의 이동은 유저의 입력에 대한 반응으로서만 변경되어야 한다고 본다. 느닷없이 변경되는 포커스는 유저가 집중을 잃고 불쾌하도록 만든다.

(최근의 WM 들은 어떨런지 모르겠지만) 내가 쓰던 시절 X Windows 에서는 WM 설정으로 유저가 직접 포커스 정책을 바꿀수 있었다. 그리고 맥OS 의 경우 프로그램 실행후 로딩이 완료되기 전에 유저가 의도적으로 다른 창에 포커스를 옮기면 로딩이 완료되더라도 동영상처럼 포커스가 강제로 이동되지 않는다.

사실 포커스 얘길 하려던 건데 테스트 결과 주제를 바꾸어야겠다. 포커스 문제는 집어치우고 우선 일관성 문제부터 어떻게 해 달라. 같은 프로그램도 매번 실행할때마다 결과가 달라지는것도 큰 문제이고, 같은 MS 에서 나온 어플들 역시 저마다 런칭시 포커스 정책이 다른것도 문제다. (IE 는 포커스를 강제로 가져가는데 오피스는 가져가지 않는것 같다.) 유저는 그런것에 적응하기 힘들다.

2009/01/22 00:33 2009/01/22 00:33

게임 개발사, (주)엔플레버 입니다.

설립한지 5년 됐고 직원은 100명정도 입니다.

현재 현역 & 보충역 모두 대기자 없습니다.

가급적이면 서버 프로그래머를 원츄합니다.

좋은분 추천해 주심 술 쏩니다.

자세한건 메일이나 MSN 으루다가...

testors@welovebeer.org 입니다.

2009/01/21 00:43 2009/01/21 00:43