2016-07-16 2 views
14

개발자 팀에서 거대한 응용 프로그램의 중간에 있으며 메모리는 초기에 고려해야 할 사항입니다. 이 프로그램을 그대로 실행하면 약 44MB의 메모리가 필요합니다 (작업 관리자에서 찾음). 나는 10,000 개의 시체를 만든다. 메모리 사용량은 약 83MB입니다. 나는 공간을 클릭 할 때 시체를 파괴 할 수있는 방법이 있습니다. 이것이 보이는 방법입니다.LibGdx에서의 메모리 사용량

public static void disposeAllBodies(){ 
    Array<Body> bodies = new Array<Body>(); 
    world.getBodies(bodies); 
    int destroyCount = 0; 
    System.out.println("Attempting to destroy " + world.getBodyCount()+ " bodies"); 
    for(Body b : bodies){ 
     world.destroyBody(b); 
     destroyCount++; 
    } 

    System.out.println("Successfully destroyed " + destroyCount + " body(s), " + world.getBodyCount() + " remain"); 


} 

모든 신체를 문제없이 처리하며, 응용 프로그램에서 유일한 것입니다. 처리가 끝난 후 메모리는 몇 초 동안 약 66MB로 내려간 다음 78MB로 점프하고 거기에 머물러 있습니다.

그래서이 시체를 처분하는 더 좋은 방법이 있습니까? 이 응용 프로그램은 수백만의 시체를 만들지 만 대부분이 파괴 될 것입니다. 그러나 메모리가 계속 올라간다면 메모리가 거의 정적으로 유지되기 때문에 메모리를 계속 처리하지 못할 것입니다.

또한 CPU는 0.2 % (모든 시체보다)에서 23 % (10,000 개 시체가있는 경우)로 이동 한 다음 2.3 % (처분 된 시체)보다 작습니다. 그래서 CPU조차도 시체 처리 후 더 많은 작업을하고 있습니다.

도움 주셔서 감사합니다.

업데이트 :

BodyDef bodyDef = new BodyDef(); 
    bodyDef.type = type; 
    bodyDef.position.set(new Vector2(position.x, position.y)); 

    Body body = world.createBody(bodyDef); 

    FixtureDef fixtureDef = new FixtureDef(); 
    Fixture fixture; 
    if(isCircle){ 
     CircleShape circle = new CircleShape(); 
     circle.setRadius(dimensions.x); 
     fixtureDef.shape = circle; 
     fixture = body.createFixture(fixtureDef); 
     circle.dispose(); 
    }else{ 
     PolygonShape rectangle = new PolygonShape(); 
     rectangle.setAsBox(dimensions.x, dimensions.y); 
     fixtureDef.shape = rectangle; 
     fixture = body.createFixture(fixtureDef); 
     rectangle.dispose(); 
    } 

이 모든 단지 Box2D의 기관, 연결없는 스프라이트 또는 아무것도는 다음과 같이 몸을 만들기위한 코드는. 감사!

+0

본문을 만드는 데 사용할 코드를 포함 할 수 있습니까? –

+0

당신이 만들고/파괴하고있는 것은 box2d 바디입니까? 당신은 몸체의 UserData에 (Entity/Actor 인스턴스와 같은) 아무 것도 추가하지 않겠습니까? 시체를 만들 때, 특히 조명기를 만들 때 생성하는 도형 객체를 파괴합니까? (예 : shape = new PolygonShape(); 등등; fixtureDef.shape = shape; shape.dispose();). 필요하지도 않고 처분하지도 않는 곳이면 어디에서나 새 텍스처를 만들 수 있습니까? 등. –

+0

업데이트 된 답변들 – Luke

답변

5

게시 한 "box2d 전용"코드의 버전을 삭제 해 보았습니까? 여전히 동일한 문제가 있는지 확인하려면 게시 했습니까? 내가 묻는 이유는 "FixtureDef 속성 변경"에 대한 또 다른 질문을 Changing FixtureDef properties Java Libgdx에 게시하고 전체 코드를 더 많이 제공했기 때문입니다. 이 질문의 코드는 다른 질문의 코드의 하위 집합입니다. 이 코드를 보면 몇 가지 문제가있을 수 있습니다.

body, bodyDefs, fixtures 및 fixtureDefs를 HashMap에 넣는 다른 질문에서는지도를 검색/지우는 방법을 표시하지 않습니다. 메모리 누수가 발생할 수 있습니다. 나는 그렇지 않을 것이라고 말하고 싶지만 결코 알지 못합니다.

그러나 나는 확신이 비트는, 문제의 원인이됩니다 보았다 : 당신은 당신이 더 스프라이트를 사용하지 않는 말했다이 질문에

public void attachNewSprite(String internalPath){ 
    entitySprite = new Sprite(new Texture(Gdx.files.internal(internalPath))); 
    ((Body)bodyObjects.get(BodyReferences.BODY)).setUserData(entitySprite); 
} 

,하지만 당신은 당신의 코드 어딘가에 위를 할 경우, 각 새로운 Texture()가 메모리를 차지합니다. 생성 한 각 텍스처를 명시 적으로 처리해야합니다. 새로운 스프라이트를 만들 때마다 새로운 텍스처를 만들지 않아야합니다. 이상적으로는 텍스처를 한 번 만든 다음 TextureRegion 인 Sprite를 사용하여 텍스처에 매핑합니다. 그런 다음 모든 작업이 완료되면 텍스처를 처리하십시오 (레벨/게임/끝 부분에서). 텍스처를 처리하려면 참조를 유지해야합니다.

편집/업데이트 :

는 오늘 아침 그래서 난 당신의 게시 된 코드를 가져다가 몸 생성 및 신체 삭제 코드를 베어 간단한 응용 프로그램을 만드는 데 약간의 추가 시간이 있었다. 나는 모든 X 초 동안 발사하는 타이머를 설정하여 10K 시체를 만들거나 파괴 할 때 어떤 일이 벌어지는 지보고, 게시 한 코드는 괜찮아 보였다. 따라서 귀하의 문제는 귀하가 게시하지 않은 코드가있을 수 있습니다. 내 컴퓨터의 메모리가 약간 변동될 수 있습니다 (GC가 언제 시작될지는 결코 알 수 없지만 실제로는 45MB를 초과하지는 않습니다).

내가하는 일보다 아래에 다른 내용이 있거나 (게시 할 코드가 더 많다면), 지금까지 공유 한 내용과 관련된 문제는 표시되지 않습니다.

import java.util.concurrent.ThreadLocalRandom; 

import com.badlogic.gdx.ApplicationListener; 
import com.badlogic.gdx.math.Vector2; 
import com.badlogic.gdx.physics.box2d.Body; 
import com.badlogic.gdx.physics.box2d.BodyDef; 
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; 
import com.badlogic.gdx.physics.box2d.CircleShape; 
import com.badlogic.gdx.physics.box2d.Fixture; 
import com.badlogic.gdx.physics.box2d.FixtureDef; 
import com.badlogic.gdx.physics.box2d.PolygonShape; 
import com.badlogic.gdx.physics.box2d.World; 
import com.badlogic.gdx.utils.Array; 
import com.badlogic.gdx.utils.Timer; 
import com.badlogic.gdx.utils.Timer.Task; 

public class Memory implements ApplicationListener { 

    private static World world; 

     private static void createNewBodies(boolean isCircle, Vector2 position, Vector2 dimensions) { 
      BodyDef bodyDef = new BodyDef(); 
      //bodyDef.type = type; //all bodies here are dynamic 
      bodyDef.type = BodyType.DynamicBody; 
      bodyDef.position.set(position); 

      Body body = world.createBody(bodyDef); 

      FixtureDef fixtureDef = new FixtureDef(); 
      Fixture fixture; 
      if(isCircle){ 
       CircleShape circle = new CircleShape(); 
       circle.setRadius(dimensions.x); 
       fixtureDef.shape = circle; 
       fixture = body.createFixture(fixtureDef); 
       circle.dispose(); 
      }else{ 
       PolygonShape rectangle = new PolygonShape(); 
       rectangle.setAsBox(dimensions.x, dimensions.y); 
       fixtureDef.shape = rectangle; 
       fixture = body.createFixture(fixtureDef); 
       rectangle.dispose(); 
      } 
     } 

     public static void disposeAllBodies(){ 
      Array<Body> bodies = new Array<Body>(); 
      world.getBodies(bodies); 
      int destroyCount = 0; 
      System.out.println("Attempting to destroy " + world.getBodyCount()+ " bodies"); 
      for(Body b : bodies){ 
       world.destroyBody(b); 
       destroyCount++; 
      } 

      System.out.println("Successfully destroyed " + destroyCount + " body(s), " + world.getBodyCount() + " remain"); 

     } 

     private static void buildAllBodies() { 
      int minPos = 10; 
      int maxPos = 400; 
      int minWidthHeight = 50; 

      Vector2 position = new Vector2(); 
      Vector2 dimensions = new Vector2(); 

      for (int i=0; i<10000; i=i+2) { 
       position.x = ThreadLocalRandom.current().nextInt(minPos, maxPos+1); 
       position.y = ThreadLocalRandom.current().nextInt(minPos*2, maxPos*2+1); 
       dimensions.x = ThreadLocalRandom.current().nextInt(minWidthHeight, minWidthHeight+1); 
       dimensions.y = dimensions.x; 
       createNewBodies(true, position, dimensions); 
       createNewBodies(false, position, dimensions); 
      } 
     } 

     @Override 
     public void create() { 

      world = new World (new Vector2(0.0f, -9.8f), true); 

      Timer.schedule(new Task() { 
        @Override 
        public void run() { 
         buildAllBodies(); 
         disposeAllBodies(); 
        } 
       } 
       , 1.0f 
       , 10.0f //how often to do the cycle (in seconds) 
      ); 
     } 

     @Override 
     public void render() { } 

     @Override 
     public void dispose() { 
      world.dispose(); 
     } 

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

     @Override 
     public void pause() { } 

     @Override 
     public void resume() { } 
} 
+0

이들은 두 개의 개별 프로젝트입니다.이 질문에 게시 한 메서드는 정적 메서드가 아니거나 해시 맵을 반환하지 않습니다. 그러나 왜 몸을 얻고 스프라이트를 설정하면 문제가 발생합니까? – Luke

+0

스프라이트를 설정하는 방법. 새로운 텍스쳐를 만들었습니까? https://github.com/libgdx/libgdx/wiki/Memory-management –

+0

이 코드 또는 이전 질문 코드를 언급하고 있습니까? – Luke