2013-04-26 1 views
2

가비지 수집을 위해 거의 완성 된 게임 (libgdx로 작성)을 테스트하고있었습니다. verbose gc 및 2MB 힙 VM 옵션 만 사용하여 데스크톱 버전을 실행했습니다.간단한 화면 (libgdx)을 렌더링하는 동안 가비지 콜렉터가 호출됩니다.

나는 화면 렌더링 중에 gc가 매번 실행되는 것을주의해야합니다.

단일 스테이지로 간단한 화면을 만들고 하나의 이미지 액터를 추가하기로 결정했습니다. 다른 개체가 생성되지 않았습니다. 나는 그런 간단한 설정 gc로조차도 매번 킥을 발견했다. 나는 두 개의 GC 호출 약 5 분 동안 실행 한 후 얻을 수 아래의 코드와

:

[GC [DefNew: 998K->4K(1024K), 0.0014329 secs] 2336K->1359K(3124K), 0.0015340 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC [DefNew: 964K->3K(1024K), 0.0005355 secs] 2319K->1358K(3124K), 0.0006174 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

그리고 요약 :

Heap 
def new generation total 1024K, used 133K [0x323c0000, 0x324d0000, 0x325c0000) 
eden space 960K, 13% used [0x323c0000, 0x323e0918, 0x324b0000) 
from space 64K, 5% used [0x324c0000, 0x324c0d10, 0x324d0000) 
to space 64K, 0% used [0x324b0000, 0x324b0000, 0x324c0000) 
tenured generation total 2100K, used 1355K [0x325c0000, 0x327cd000, 0x329c0000) 
the space 2100K, 64% used [0x325c0000, 0x32712c48, 0x32712e00, 0x327cd000) 
compacting perm gen total 12288K, used 2520K [0x329c0000, 0x335c0000, 0x369c0000) 
the space 12288K, 20% used [0x329c0000, 0x32c36140, 0x32c36200, 0x335c0000) 
ro space 10240K, 54% used [0x369c0000, 0x36f3daf0, 0x36f3dc00, 0x373c0000) 
rw space 12288K, 55% used [0x373c0000, 0x37a61ce8, 0x37a61e00, 0x37fc0000) 

다음

import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.Screen; 
import com.badlogic.gdx.graphics.GL10; 
import com.badlogic.gdx.scenes.scene2d.Stage; 
import com.badlogic.gdx.scenes.scene2d.actions.Actions; 
import com.badlogic.gdx.scenes.scene2d.ui.Image; 

public class TestScreen implements Screen { 

    private static final float viewportWidth = 40f; 
    private static final float viewportHeight = 24f; 

    private final Assets assets = new Assets(); 
    private Stage stage; 

    @Override 
    public void render(float delta) { 
     Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 
     stage.act(); 
     stage.draw(); 
    } 

    @Override 
    public void resize(int width, int height) { 
    } 

    @Override 
    public void show() { 
     stage = new Stage(viewportWidth, viewportHeight, false); 
     Image image = new Image(assets.getMenuSkin(), "stars"); 
     image.setSize(viewportWidth, viewportHeight); 
     image.setPosition(0f, 0f); 
     stage.addActor(image); 
    } 

    @Override 
    public void hide() { 
    } 

    @Override 
    public void pause() { 
    } 

    @Override 
    public void resume() { 
    } 

    @Override 
    public void dispose() { 
     assets.dispose(); 
     stage.dispose(); 
    } 
} 

출력의 가비지 수집 된 배열을 통해 OpenGL 데이터를 보내고 있습니까?

Mario의 책 (Android 게임 시작)에서 읽은 바에 따르면 나는 그렇지 않다는 것을 알았습니다. 내가 기억하는 한, Mario는 gc를이 경우 실행시킨 버그에 대해 썼지 만 초기 Android 버전에서만 존재했습니다.

데스크톱 구현이 gc로 실행되고 Android가 실행되지 않을 수 있습니다.

+0

당신이 사용하고있는 OpenGL 라이브러리에 대해 조금 아는 것이 얼마나 자주 show()가 호출되는지 궁금하십니까? 매번 새로운 이미지를 생성하고 너무 많은 객체를 사용하여 힙을 낭비하여 GC를 많이 강제 실행하지 않을 수 있습니다. – arynaq

+0

show()는 화면이 표시 될 때 한 번만 호출됩니다. 클래스 생성자에서 libgdx 항목을 만들 때 초기화되지 않은 오류가 발생하기 때문에 모든 생성 논리를 여기에 넣는 경향이 있습니다. – Dzik

답변

0

DDMS 힙 추적기 도구를 사용하십시오. 할당 된 내용과 할당 된 백 트레이스를 정확히 알려줍니다. 그것은해야 물론 http://developer.android.com/tools/debugging/ddms.html

이 안드로이드에 구체적으로하지만, Libgdx 코드의 99 %가 동일하기 때문에 (예를 들어, scene2d 모두 동일)를 참조하십시오에서 "개체의 메모리 할당을 추적" 할당이 Libgdx 또는 Lwjgl 또는 심지어 JVM (핫스팟은 백그라운드에서 메소드를 다시 컴파일 할 수도 있습니다.)에서 할당이 발생하면 강조 표시합니다.

사용중인 Libgdx 버전은 무엇입니까?

scene2d에는 새로운 객체를 할당하는 몇 가지 코드 경로가 있지만 일반적으로 Pool에 저장되므로 수집되지 않아야하며 결국 할당이 느려지고 중지되어야합니다.

+0

2012 년 11 월 27 일 0.9.7을 사용하고 있습니다. libgdx가 끊임없이 진화하고 있기 때문에 필자는 그것이 도움이되는지 계속 업데이트하고 확인하려고 노력할 것입니다. scene2d가 Action과 같은 객체를 풀링한다는 것을 알 수 있습니다. 내 게임은 실제로 '새로운', 순수한 문자열, for 루프, autoboxing 등의 코드를 사용하지 않도록주의를 기울 였지만 분당 2 ~ 3MB의 힙 크기로 분당 3 ~ 5 번 킥을 만듭니다. 추적 도구에 대한 정보를 보내 주셔서 감사합니다. 다음으로, 실제로 어떤 일이 일어나고 있는지에 대한 전체 정보를 얻기 위해 어느 것을 사용해야 하는지를 물어 보았습니다. 어쩌면 문제를 해결하는 데 도움이 될 것입니다. – Dzik

+0

당신이 무엇을 발견했는지 알려주세요! –

0

위의 코드를 먼저 libgdx 데스크탑에서 분석하기로 결정했습니다. 응용 프로그램이 시작 된 후 2 메가 바이트 힙 는 처음 두 GC 통화 58 초 241 초 발생했습니다 내가 전에 MAT와 두 번째 GC 호출하고, 몇 힙 몇 초를 잡고

58.163: [GC 58.163: [DefNew: 1024K->19K(1088K), 0.0013214 secs] 2367K->1440K(3328K), 0.0014552 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
241.027: [GC 241.027: [DefNew: 1043K->17K(1088K), 0.0008428 secs] 2464K->1439K(3328K), 0.0009747 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

초 후에 출력을 분석하는 동안 도달 할 수없는 개체에서만 차이점을 발견했습니다.여기

들은 이전 객체 카운트 사이의 차이와 상기 제 GC 호출 후에 계 desending 순서이다 :

Before GC call:             |After GC call: 
Class Name        | Objects | Shallow Heap |Objects | Shallow Heap | 

java.nio.DirectFloatBufferU    | 19753|  948144|  864|   41472| 
int[]          |  2599|  218168| 2507|  207152| 
java.lang.Class[]       |  140|   2384|  133|   2248| 
java.lang.reflect.Constructor    |  42|   2688|  35|   2240| 
char[]         | 11588|  602008| 11584|  601808| 
java.lang.String       | 11237|  269688| 11233|  269592| 
java.io.FileDescriptor     |  4|   96|  1|   24| 
java.io.FileInputStream     |  4|   96|  1|   24| 
java.lang.Object       |  6|   48|  3|   24| 
java.lang.ref.Finalizer     |  4|   128|  1|   32| 
java.util.concurrent.atomic.AtomicInteger |  4|   64|  1|   16| 
java.lang.reflect.Constructor[]   |  5|   160|  3|   96| 

주요 큰 차이가 DirrectFloutBufferU이다. 그래서 OpenGL 데이터 버퍼가 가비지 수집 된 것 같습니다. 렌더링 할 액터를 더 추가 할 때 더 자주 GC 호출이 발생했기 때문에 그런 것처럼 보입니다.

나머지 부분은 중요하지 않습니다. 나는 그들을 설명하는 방법을 모르겠다.

이 올바른 동작입니까?

시간이 지나면 Android에서 비슷한 테스트를 실행합니다.

+0

나에게 좋지 않은 것 같습니다. LWGGL의 일부가 될 가능성이 있고 Libgdx의 일부가 아닐 수도 있습니다 (또는 Libgdx의 일부가 잘못된 LWJGL API를 사용하고있을 수 있습니다). StackOverflow 이외에,이 "대답"은 원래의 질문을 확장/편집하고 "대답"으로 게시하지 않아야합니다. –

+0

'답변'을 게시하는 것에 대해 죄송합니다. 다음 번에 내가 쓴대로 해줄거야 :) – Dzik

+0

Mario Zechner 자신이이 문제에 대한 답을 http://badlogicgames.com/forum/viewtopic.php?f=11&t=8786#p40099에 보냈다. 그는 데스크톱 애플리케이션의 경우 정상이라고 주장합니다. – Dzik

관련 문제