메모리 관리를 어떻게 하시나요

프로그래밍 일반에 관한 포럼입니다.

Moderator: 류광

Locked
lifeisforu
Posts: 225
Joined: 2005-02-25 11:33
Location: (주)위메이드엔터테인먼트 엔진개발팀
Contact:

메모리 관리를 어떻게 하시나요

Post by lifeisforu »

이번에 프로젝트를 만들어 실행을 시켰는데, 로딩 직후에 엄청난 지연이 생기더군요.

그런 경험들이 있으신지 모르겠는데, 'p4 2.4, 512M' 환경에서 테스트를 할 때는 아무 문제 없더니,
안 좋은 사양에서 테스트를 하니까 게임을 로드한 이후에 엄청나게 버벅대더군요.
이렇게 저렇게 문제점을 알아 보려고 테스트해 보다가 메모리가 부족해서라는 결론을 내리게 되었습니다.
다른 것은 비슷한 사양이더라도 메모리가 많은 시스템에서는 버벅대지가 않더군요.

new를 사용해 메모리를 할당할 때 실시간에 메모리를 확장하느라 cpu 시간을 잡아 먹는
것이라는 결론을 내렸습니다.

한 번에 메모리를 할당해 놓고, 실시간에 부족한 메모리만큼을 확장하지 않는 방법을
고민해 보았는데 안타깝게도 M$가 그런 함수는 구현하지 않은 듯 하더군요.
(혹시 있으면 말씀해 주시면 감사하겠습니다)

그래서 GPG에 메모리 관리에 대한 글들이 있었던 것을 기억해 찾아 보았더니,
프레임 기반 메모리 관리가 저한테 딱 들어맞는다는 생각을 했습니다.

하지만 열심히 구현을 하고 보니까, 문제가 발생했는데 new를 사용하면
상속시 가상함수에 대한 포인터 등을 초기화 해주는 코드가 있지 않습니까.
그런데 책에서는 c 기반 메모리 관리를 해 주는 것 같더군요. 즉 초기화는 없다는 것입니다.

결론적으로 두 가지 방향의 해결책을 찾을 수 있을 것 같습니다.

1. 미리 메모리 할당하고 new를 이용할 수 있는 방법을 찾는다.
2. 프레임 기반 메모리 관리자를 만들고 new의 역할을 구현하는 함수를 만든다.

두 가지 방법 모두 저에게 조금 벅찬 주제인 것 같습니다. 뭘 봐야 할지도 잘 모르겠고...
이 방법이 아니라 다른 방법이 있다면 알려주셨으면 좋겠고,
가급적이면 두 가지 방법을 어떻게 구현할 것인지에 대해 조언을 주셨으면 합니다.

모두들 즐플하세요.
비회원

Post by 비회원 »

new를 재정의하세요.

EC++이나 게임프로그래머를 위한 c++같은 책을 참고 하시면 되겠네요.
비회원

Post by 비회원 »

아시다시키 Win32 에서 프로세스가 사용할 수 있는공간은 대략 2기가 정도 되는데
물리적인 메모리가 이보다 적을 경우 하드 스와핑을 할 수 밖에 없습니다.
즉, 과도한 메모리 사용은 하드 스와핑을 유발해 검나게 느려진다는 거죠.. ^^
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

불필요한 데이터를 로딩하지 않거나
즉시 렌더링해야할 데이터가 아니라면 압축을 한 상태로 가지고 있다던지
오랫동안 사용하지 않는 데이터를 제거하는 방식을
연구하시는것이 직접적인 해결이 되지 않을까 합니다.
빗자루네 http://www.myevan.net >_<b
비회원

^^

Post by 비회원 »

다음과 같은 2가지의 요구사항을 말씀하셨지만 근본적으로는 1번만 해결하면 되는거 같군요.
1. 미리 메모리 할당하고 new를 이용할 수 있는 방법을 찾는다.
2. 프레임 기반 메모리 관리자를 만들고 new의 역할을 구현하는 함수를 만든다.
해결책은 placement new를 사용하시면 될것같습니다.

예를들어 프레임 메모리에서 CTestClass의 크기만큼 할당받고 new를 실행시키고 싶다면

CTestClass *pTest = (CTestClass*)FrameMemory.Alloc(sizeof(CTestClass)); // 메모리를 할당
new (pTest) CTestClass; // 할당된 메모리에 CTestClass의 생성자를 호출

이렇게 하시면 미리 할당된 메모리에 생성자를 호출할수 있게 됩니다.
(게시판에서 바로 코드 적인거니까 대충 그렇구나 하고 봐주세요..)

질문에 답변이 되었나 모르겠군요.. ^^
조순현
Posts: 115
Joined: 2004-07-02 22:14
Location: 네오위즈 게임즈
Contact:

Post by 조순현 »

RAM의 용량이 적다면, 별도의 memory 관리자를 만들어 memory 할당 속도를 빠르게 한다 해도 program이 느린 것은 달라지지 않습니다. 왜냐하면 이 상황에서 문제는 memory 할당 속도가 아니라, memory swapping의 속도이기 때문입니다. Memory swapping을 줄여야 program 속도가 빨라지고, 그렇게 하려면 myevan님이 제시한 방법 같은 것으로 memory 사용량을 줄여야 합니다. Memory 사용량을 줄여 보세요.
Last edited by 조순현 on 2005-03-07 15:48, edited 1 time in total.
쉬운 것은 올바르다.
lifeisforu
Posts: 225
Joined: 2005-02-25 11:33
Location: (주)위메이드엔터테인먼트 엔진개발팀
Contact:

답변 감사합니다.

Post by lifeisforu »

placement new라는 것을 사용하면

즉 new (메모리 주소를 저장하는 포인터) 생성자 식으로 호출할 수 있다는 의미인 것 같은데,

그렇다면 제가 원하는 것이 맞기는 합니다.

한 번 시험을 해 보아야겠군요. 감사합니다.



그리고... 2번째 해결책 관련해서 궁금한게 있는데요,

가상함수를 사용하게 되면 상속시에 가상함수 테이블 주소가 최상위 4byte에 들어가고,

그것을 다시 상속하게 된다면 최상위 4byte에는 최상위 클래스 가상함수 테이블 주소,

다음 4byte에는 다음 클래스의 가상함수 테이블 주소가 들어가는 것으로 알고 있습니다.

만약 new를 오버라이딩 혹은 오버로딩 한다면 클래스의 가상함수 테이블 주소는 어떻게 알아낼 수 있는지,

몇 개의 가상함수 테이블을 가지고 있는지 확인할 수 있는 방법에 대해 아시는게 있으시다면 조언 부탁드립니다.
Last edited by lifeisforu on 2005-03-08 11:38, edited 1 time in total.
lifeisforu
Posts: 225
Joined: 2005-02-25 11:33
Location: (주)위메이드엔터테인먼트 엔진개발팀
Contact:

Post by lifeisforu »

수렁 wrote:RAM의 용량이 적다면, 별도의 memory 관리자를 만들어 memory 할당 속도를 빠르게 한다 해도 loading이 느린 것은 달라지지 않습니다. 왜냐하면 이 상황에서 문제는 memory 할당 속도가 아니라, memory swapping의 속도이기 때문입니다. Memory swapping을 줄여야 loading 속도가 빨라지고, 그렇게 하려면 myevan님이 제시한 방법 같은 것으로 memory 사용량을 줄여야 합니다. Memory 사용량을 줄여 보세요.
음... 로딩 시간이 지연되는 문제에 대해서 이야기하고 있는 것은 아니구요. 로딩이 끝나고 화면을 렌더링했는데도 cpu가 무언가 작업을 하고 있는 것처럼 버벅대고 있는 현상에 대한 문제입니다.

로딩을 끝마치고 나서 카메라를 보간해서 캐릭터의 위치로 옮기는데 cpu가 처리를 제대로 못해서인지 다른데로 갔다가 오더군요. 그리고 나서 시간이 지나면 제대로 나옵니다. 레이싱 게임을 만들고 있는데 첫 번째 실행때는 엄청 버벅대다가 두 번째 실행시에는(두번째 실행시에는 첫 번째에 로드한 자원을 그대로 사용합니다.) 괜찮더군요.

논리적으로 생각하면 로딩이 끝나고 렌더링을 한거기 때문에 문제가 없어야 한다고 생각했는데, 로딩이 끝난 이후에도 메모리 할당과 관련된 cpu 작업이 끝나지 않았다는 느낌이 들기 때문에 이런 질문을 드린 것입니다.
비회원

죄송합니다;

Post by 비회원 »

제가 엉뚱하게 loading에 관련지어 글을 썼네요; 제정신이 아니었나 봅니다 :oops: 죄송합니다. 올린 글은 수정하겠습니다.

그런데 loading중이 아니라도 문제는 같습니다. 즉, memory 할당 자체의 부하는 크지 않고, memory swapping의 부하가 문제라는 것입니다. 그러므로 memory 사용량 자체를 줄여야 합니다.

그리고 placement new를 쓰는 것도 좋은 방법이긴 합니다만, 기존의 source code를 많이 수정해야 하기 때문에 일반적으로는 그냥 new를 재정의합니다. 그러나 전역 new를 재정의할 경우, 다른 곳에서 재정의한 전역 new와 충돌이 일어나기 때문에 생각처럼 깔끔하게 되지 않습니다.
자갈공명
Posts: 60
Joined: 2003-06-25 19:31
Location: ...
Contact:

Post by 자갈공명 »

얘기해주신 상황으로 유추해보면 저역시 메모리부족으로 인한 스왑에 걸리는 시간때문이라는 가정에 한표입니다.

특히 텍스쳐를 MANAGED로 로딩시켰을때 비디오메모리가 부족해서 시스템메모리에 있다가 첫번째 실행시(렌더링시) 비디오로 올라가느라 버벅대고 그 다음부터는 비디오에 있으니 안 버벅대는 상황이 아닌가 합니다.

메모리가 많은 사양에서는 그나마 하드디스크까지 쓰지는 않아서 시스템메모리에서 비디오메모리로 스왑되니까 덜 느리고, 낮은 사양은 하드디스크에서 읽어서 비디오로 스왑되니까 버벅되는구요.

로딩하는 순서가 현재프레임의 렌더링에 필요한것들을 먼저 로딩한게 아니라 그냥 순차적이라면 더더욱 현재 필요로하는 텍스쳐가 비디오메모리에 있을 가능성은 낮아지므로 초반에 스왑이 일어날 가능성이 높습니다.
조순현
Posts: 115
Joined: 2004-07-02 22:14
Location: 네오위즈 게임즈
Contact:

가상 함수 Table

Post by 조순현 »

More Effective C++ 책 항목 24에서 본 바로는, 가상 함수 table의 위치는 compiler마다 다르다고 합니다. 따라서 그것을 이용해 어떤 작업을 하는 것은 위험합니다. 한 가지 version의 compiler만 사용한다면 문제가 없지만, 호환성을 보장할 수 없는 작업은 되도록 삼가하는 것이 좋습니다. 즉 모든 compiler에서 지원이 되는, 보다 상위 수준의 다른 해결책을 찾아 보는 것이 좋습니다.

그런데 왜 new를 중복정의할 때 가상 함수 table의 정보를 알아내려고 하시는지 궁금합니다. new를 중복정의할 때엔, 단지 memory 할당만 해 주면 됩니다. 생성자 호출이나 가상 함수 table 초기화 같은 것은 기존의 것이 그대로 동작합니다.
쉬운 것은 올바르다.
lifeisforu
Posts: 225
Joined: 2005-02-25 11:33
Location: (주)위메이드엔터테인먼트 엔진개발팀
Contact:

감사합니다

Post by lifeisforu »

new의 소스코드 분석을 했었는데, 가상함수에 대한 부분은 없더라구요.
역시 알아서 되는 것이었군요.

많은 도움이 되었습니다.
모두들 답변과 관심에 감사드립니다.
Locked