2012-03-24 3 views
7

저는 Linux 기반 서버를 사용하여 멀티 플레이어 온라인 게임을 개발하는 프로그래머입니다. 우리는 우리 세계에 "인스턴스화 된"아키텍처를 사용합니다. 즉, 세계 지역에 입장하는 각 플레이어는 해당 지역의 사본을 얻어 파티원과 게임을하고 동일한 지역에서 플레이하는 다른 모든 플레이어와 독립적입니다.더 효율적으로 fork() 및 copy-on-write 메모리 공유 사용하기

내부적으로 우리는 각 인스턴스에 대해 별도의 프로세스를 사용합니다. 처음에는 각 인스턴스 프로세스가 시작되고 주어진 영역에 필요한 리소스 만로드하고 무작위 지형을 생성 한 다음 플레이어로부터 새로운 연결을 허용합니다. 인스턴스가 사용하는 메모리의 양은 일반적으로 자원과 엔티티가 포함 된 무작위로 생성 된 레벨을 포함하여 약 25MB였습니다.

인스턴스의 메모리 사용 공간을 줄이고 스폰 시간을 단축하기 위해 인스턴스가 필요할 수있는 모든 리소스를로드하는 단일 마스터 인스턴스를 만드는 방법으로 변경했습니다 (약 150MB 메모리)에 저장 한 다음 새 인스턴스가 필요할 때 fork() 함수를 사용하여 새 인스턴스를 생성하고 copy-on-write 메모리 공유를 사용하여 새 인스턴스가 "고유 한"데이터 세트의 메모리 만 필요로합니다. 임의로 생성 된 레벨과 각 인스턴스의 고유 한 데이터를 구성하는 엔티티의 공간은 약 3-4MB의 메모리입니다.

불행히도 메모리 공유가 제대로 작동하지 않는다고 생각합니다. 많은 메모리 페이지가 공유되지 않는 것처럼 보입니다.

처음에는 프리 프레임 인스턴스에서 더 많은 데이터 세트를로드 할 때 각 포크 된 인스턴스에 필요한 메모리가 다운되지만 결국 프리 포크에서 더 많은 에셋을로드하면 실제로 사용되는 데이터가 증가하는 변곡점이 있습니다. 각 포크 된 인스턴스.

우리가 미리 포크 데이터 세트의 약 80 메가를로드 한 다음 새로운 인스턴스가있는 가지고있는 최고의 결과는 나머지를로드 요구한다. 인스턴스 당 약 7-10 추가 메가와 80 메가 고정 비용이 발생합니다. 확실히 좋은 개선이지만 이론상 최고는 아닙니다.

I 전체 150 메가 데이터 세트하고 포크로드되면 각 갈래 인스턴스 메모리는 약 50 메가 이상 사용! 단순히 아무것도하지 않는 것보다 훨씬 더 심합니다.

제 질문은 프리 프레임 인스턴스에 모든 데이터 세트를로드하고 각 인스턴스의 메모리 풋 프린트로 인스턴스 데이터 당 최소 고유 집합 만 가져 오도록하려면 어떻게해야합니까?


은 여기 무슨 일이 일어나고 있는지에 관한 이론을 가지고 누군가가 이런 경우가 나를 위해 확인 도울 수있을 것인지 궁금 해서요.

malloc 무료 체인과 관련이 있다고 생각합니다. prefork 인스턴스의 각 메모리 페이지에는 메모리의 여유 공간이 남아 있습니다. 임의의 레벨 생성 중에 무언가가 페이지의 자유 지점 중 하나에 적합하게 할당되면 전체 페이지가 분기 된 프로세스로 복사됩니다.

Windows에서 대체 힙을 만들고 프로세스에서 사용하는 기본 힙을 변경할 수 있습니다. 이것이 가능하면 문제가 제거됩니다. 리눅스에서 그런 일을 할 수있는 방법이 있습니까? 내 수사는 당신이 할 수 없다는 것을 나타내는 것 같습니다.

또 다른 가능한 해결책은 어떻게 든 기존의 malloc 자유 체인을 삭제하여 이후의 호출을 위해 운영 체제의 새로운 메모리를 malloc에 ​​할당하도록하는 것입니다. 필자는 malloc을 쉽게 구현할 수 있는지 살펴보기 위해 malloc을 시도했지만, 다소 복잡 할 것 같았다. 누구든지이 분야와 관련하여 아이디어가 있거나이 접근법을 어디서부터 시작해야할지 제안을 듣고 싶습니다.

마지막으로 누군가가 여기에서 잘못 될 수있는 것에 대한 다른 아이디어가 있다면, 나는 정말로 그걸 듣고 싶습니다. 고마워요!

답변

2

Windows에서 대체 힙을 만들고 프로세스에서 사용하는 기본 힙 을 변경할 수 있습니다. 가능한 경우 문제가 제거됩니다. 리눅스에서 그런 일을 할 수있는 방법이 있습니까?

I 유닉스 할 수 있습니다 단순히 우회 malloc 모두 mmap(2) 메모리.

나는 또한 모든 "rely-on-cow"를 피할 것입니다. 나는 마스터 프로세스 mmap 일부 메모리 (80M, 150M 무엇이든), 그것에 물건을 쓰는 것이 좋은 방법에 대한 mprotect(2) 통해 읽기 전용으로 표시하고 거기에서 가져 가라. 이것은 실제 문제를 해결할 것이고 코드를 변경하도록 강요하지 않을 것입니다.

+0

큰 기존 코드베이스이기 때문에 malloc/new를 완전히 바이 패싱 할 수는 없으며, 모든 리소스 로더가이를 아주 행복하게 사용합니다. 나는이 접근법을 배제 할 의사가 없지만 가능하면 누군가 elses 메모리 할당자를 계속 사용하고 싶습니다. – Negs

+1

@Negs 사용자 정의 할당자를 사용하거나 'malloc'을 도용 할 수 있습니다. 그러나 두 번째 단락을 읽으십시오. 젖소에 의지하지 말고 자신의'mmap'을하십시오. – cnicutar

+0

그래도 사용자 정의 할당자를 작성해야하는데,이 방법을 사용할 수는 있지만 그렇게 할 필요가없는 해결책을 찾고 싶습니다. 아마도 기존의 malloc 주변에서 래퍼 접근 방식을 사용하여 아마도 내 필요를 용이하게 할 수 있을까요? – Negs