2015-02-07 4 views
0

이미지를 사용하여 메모리 사용량을 능률적으로 개선하기 위해 내 게임과의 인터페이싱을위한 실행 가능하고 합리적인 솔루션을 며칠 동안 수색했습니다. 나는 너무 많은 RAM이 필요하다는 것을 알았을 때 2D Turn-based Strategy를 프로파일 링했다. 내 문제는 단순히 총 36MB의 JAR 크기의 게임 리소스를 600-800MB RAM에서 런타임에 예상되는 50MB로 바꾸는 것입니다. MediaTracker를 제거하면 RAM이 크게 줄어들었고 필요하다는 것을 알았습니다. 이미 저장된 이미지를 사용하기 위해이 정적 클래스를 참조하는 것 이외의 다른 이미지로 뒤죽박죽 된 다른 클래스는 없습니다.이미지 검색 및 저장 결과가 너무 많은 RAM 사용

더 이상 고민하지 않고도 쉽게 읽을 수있는 코드를 제공 할 것입니다.

package editor; 

import java.awt.Font; 
import java.awt.Image; 
import java.awt.MediaTracker; 
import java.awt.Toolkit; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 
import javax.imageio.ImageIO; 

/** 
* 
* @author Darryl Thomas Idle 
*/ 
public final class ResourceStash { 

public static Map<String, Image[]> CHARMAP; 
public static Map<String, Image[]> ITEMMAP; 
public static Map<String, Sound> SOUNDS; 
public static Map<String, Image[]> TILEMAP; 
public static Map<String, Image> UIMAP; 
public static Map<String, Image> GLARES; 
public Font font; 

protected EditorEngine engine; 
protected MediaTracker media; 

public ResourceStash(EditorEngine engine){ 
    CHARMAP = new HashMap<>(); 
    SOUNDS = new HashMap<>(); 
    TILEMAP = new HashMap<>(); 
    ITEMMAP = new HashMap<>(); 
    UIMAP = new HashMap<>(); 
    GLARES = new HashMap<>(); 
    this.engine = engine; 
    media = new MediaTracker(engine); 
    try{ 
     font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("fonts/EngineerHand.ttf")); 
     addSound(SOUNDS, "button_press.wav"); 
     addSound(SOUNDS, "ambience.mp3"); 
     addSound(SOUNDS, "grass_step.mp3"); 
     addAnimation(CHARMAP, CharacterObject.WALKDL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKDR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A2DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A2DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A2UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A2UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A3DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A3DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A3UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A3UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A4DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A4DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A4UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A4UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A5DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A5DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A5UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A5UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A6DL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A6DR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A6UL, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.A6UR, CharacterObject.DUSKWITCH, 10); 
     addAnimation(CHARMAP, CharacterObject.DEATHDL, CharacterObject.DUSKWITCH, 10); 

     addAnimation(CHARMAP, CharacterObject.WALKDL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKDR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DR, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UL, CharacterObject.TINKERER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UR, CharacterObject.TINKERER, 10); 

     addAnimation(CHARMAP, CharacterObject.WALKDL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKDR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A2DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A2DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A2UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A2UR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A3DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A3DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A3UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A3UR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A4DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A4DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A4UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A4UR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A5DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A5DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A5UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A5UR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A6DL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A6DR, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A6UL, CharacterObject.HOPLITE, 10); 
     addAnimation(CHARMAP, CharacterObject.A6UR, CharacterObject.HOPLITE, 10); 

     addAnimation(CHARMAP, CharacterObject.WALKDL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKUR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.WALKDR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDUR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMDDR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPUR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.JUMPDR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1DR, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UL, CharacterObject.SHADOWYCONTENDER, 10); 
     addAnimation(CHARMAP, CharacterObject.A1UR, CharacterObject.SHADOWYCONTENDER, 10); 
     addTileImgs(TILEMAP, "AIR", 1); 
     addTileImgs(TILEMAP, "DIRT", 1); 
     addTileImgs(TILEMAP, "DIRT_SEL", 1); 
     addTileImgs(TILEMAP, "COBBLE", 1); 
     addTileImgs(TILEMAP, "COBBLE_SEL", 1); 
     addTileImgs(TILEMAP, "FROST", 1); 
     addTileImgs(TILEMAP, "FROST_SEL", 1); 
     addTileImgs(TILEMAP, "GRASS", 1); 
     addTileImgs(TILEMAP, "GRASS_SEL", 1); 
     addTileImgs(TILEMAP, "SAND", 1); 
     addTileImgs(TILEMAP, "SCORCHED", 1); 
     addTileImgs(TILEMAP, "SCORCHED_SEL", 1); 
     addTileImgs(TILEMAP, "WATER", 30); 
     addTileImgs(TILEMAP, "WATER_SEL", 30); 
     addTileImgs(TILEMAP, "LAVA", 30); 
     addItemImgs(ITEMMAP, "TREE", 1); 
     addItemImgs(ITEMMAP, "TREE_SEL", 1); 
     addItemImgs(ITEMMAP, "SPAWN", 1); 
     addItemImgs(ITEMMAP, "SPAWN_SEL", 1); 
     addItemImgs(ITEMMAP, "BUSH", 1); 
     addItemImgs(ITEMMAP, "BUSH_SEL", 1); 
     addItemImgs(ITEMMAP, "LIGHT", 1); 
     addItemImgs(ITEMMAP, "LIGHT_SEL", 1); 
     addUIImage(UIMAP, "mappreview", "leftbutton"); 
     addUIImage(UIMAP, "mappreview", "rightbutton"); 
     addUIImage(UIMAP, "mappreview", "pane"); 
     addUIImage(UIMAP, "layout", "frameui"); 
     addUIImage(UIMAP, "camera", "00"); 
     addUIImage(UIMAP, "portraits", "DUSKWITCH"); 
     addUIImage(UIMAP, "portraits", "HOPLITE"); 
     addUIImage(UIMAP, "portraits", "TINKERER"); 
     addUIImage(UIMAP, "portraits", "SHADOWYCONTENDER"); 
     addUIImage(UIMAP, "portraits", "UNKNOWN"); 
     addUIImage(GLARES, "glares", "00"); 
     int pos = 0; 
     for(Entry<String, Image[]> imageEntry: CHARMAP.entrySet()){ 
      int i = 0; 
      for(; i < imageEntry.getValue().length; i++) 
       media.addImage(imageEntry.getValue()[i], i+pos); 
      pos += i; 
     } 
     for(Entry<String, Image[]> imageEntry: TILEMAP.entrySet()){ 
      int i = 0; 
      for(; i < imageEntry.getValue().length; i++) 
       media.addImage(imageEntry.getValue()[i], i+pos); 
      pos += i; 
     } 
     for(Entry<String, Image[]> imageEntry: ITEMMAP.entrySet()){ 
      int i = 0; 
      for(; i < imageEntry.getValue().length; i++) 
       media.addImage(imageEntry.getValue()[i], i+pos); 
      pos += i; 
     } 
     for(Entry<String, Image> imageEntry: UIMAP.entrySet()) 
      media.addImage(imageEntry.getValue(), pos++); 
     media.waitForAll(2000); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
private void addAnimation(Map<String, Image[]> map, String animation, String characterType, int frameCount){ 
    try{ 
     Toolkit tk = Toolkit.getDefaultToolkit(); 
     Image[] returnImgs = new Image[frameCount]; 
     for(int i = 0; i < frameCount; i++){ 
      Image image = null; 
      //System.out.println(this.getClass().getResource("images/characters/"+characterType+"/"+animation+"/0"+i+".png").getPath()); 
      if(i < 10) image = tk.getImage(this.getClass().getResource("images/characters/"+characterType+"/"+animation+"/0"+i+".png")); 
      else image = tk.getImage(this.getClass().getResource("images/characters/"+characterType+"/"+animation+"/"+i+".png")); 
      returnImgs[i] = image; 
     } 
     map.put(characterType+animation, returnImgs); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
private void addItemImgs(Map<String, Image[]> map, String itemType, int frameCount){ 
    try{ 
     Toolkit tk = Toolkit.getDefaultToolkit(); 
     Image[] returnImgs = new Image[frameCount]; 
     for(int i = 0; i < frameCount; i++){ 
      Image image = null; 
      //System.out.println(this.getClass().getProtectionDomain().getCodeSource().getLocation()+"images/items/"+itemType+"/"+"0"+i); 
      if(i < 10) image = tk.getImage(this.getClass().getResource("images/items/"+itemType+"/"+"0"+i+".png")); 
      else image = tk.getImage(this.getClass().getResource("images/items/"+itemType+"/"+i+".png")); 
      returnImgs[i] = image; 
     } 
     map.put(itemType, returnImgs); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
private void addSound(Map<String, Sound> sounds, String soundName){ 
    try{ 
     //System.out.println(this.getClass().getResource("sounds/"+soundName).toURI().toString()); 
     Sound sound = new Sound(this.getClass().getResource("sounds/"+soundName).toURI().toString(), false); 
     sounds.put(soundName, sound); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
private void addTileImgs(Map<String, Image[]> map, String tileType, int frameCount){ 
    try{ 
     Toolkit tk = Toolkit.getDefaultToolkit(); 
     Image[] returnImgs = new Image[frameCount]; 
     for(int i = 0; i < frameCount; i++){ 
      Image image = null; 
      //System.out.println(this.getClass().getProtectionDomain().getCodeSource().getLocation()+"images/tiles/"+tileType+"/"+"0"+i); 
      if(i < 10) image = tk.getImage(this.getClass().getResource("images/tiles/"+tileType+"/"+"0"+i+".png")); 
      else image = tk.getImage(this.getClass().getResource("images/tiles/"+tileType+"/"+i+".png")); 
      returnImgs[i] = image; 
     } 
     map.put(tileType, returnImgs); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
private void addUIImage(Map<String, Image> map, String uiName, String partOfUI) { 
    try{ 
     //System.out.println(this.getClass().getResource("images/"+uiName+"/"+partOfUI+".png").getPath()); 
     Image image = ImageIO.read(this.getClass().getResource("images/"+uiName+" /"+partOfUI+".png")); 
     map.put(uiName+partOfUI, image); 
    }catch(Exception ex){ex.printStackTrace(System.out);} 
} 
} 
+0

어떤 종류의 프로파일 러를 사용했는지, 힙 덤프 (heap dump)와 같은 것을 사용해 어떤 객체가 메모리를 소비하는지 정확히 판단 했습니까? –

+0

예 Netbean의 고급 프로파일 러를 사용했으며 이미지 저장 공간을 만들 때 DataBufferInt []에서 볼륨이 많이 발생 함을 알려줍니다. 나는 그 부분을 추가하는 것을 잊었다. –

+0

http://i.imgur.com/AIDinKd.png?1은 프로파일 러가 기록한 스택 추적 이미지의 링크입니다. –

답변

0

Java JVM은 (기본적으로) 캐싱 및 자체 사용을 위해 많은 양의 메모리를 할당합니다 (기본값). 당신은 조정 RAM의 양이 -Xmx512m

는 힙 512 MB 이상의를 사용하지 않도록 JVM을 구성 할 것이라고 -Xmx 옵션 heap size에 사용할 수 있습니다. 링크 된 페이지,

최대 힙

물리적 메모리 또는 1기가바이트의 1/4의 작은에서. J2SE 5.0 이전의 기본 최대 힙 크기는 64MB였습니다. -Xmx 명령 줄 옵션을 사용하여이 기본값을 무시할 수 있습니다.

+0

저는 그것들을 run-time 인수에 -Xmx1g로 넣었습니다. 기본 이미지 캐싱에 대해 잘 모르는 뭔가가 있다고 생각하기 때문에 사용되는 메모리 양을 줄이고 싶습니다. –

+0

그리고 ~ 800MB를 사용하고 있습니다 ... 사용중인 RAM을 * 줄이기를 원한다고하셨습니다. 512 (또는 256) MB로 설정하십시오. 참고 사항, 귀하의 명시된 ** 50 MB ** 대상 크기보다 여전히 크기가 큽니다. –

+0

50MB 대상은 사용중인 이미지와 함께 사용할 수 없습니다. 그러나 500-600MB에 가까운 것이 가능할 수도 있습니다. –

0

이미지를 메모리로 읽으면 메모리에 압축되지 않은 상태로 유지됩니다. 읽는 모든 이미지가 압축 된 png 파일 인 것 같습니다. 즉, 파일 크기보다 훨씬 많은 메모리를 소비하게됩니다.

1200 개 이상의 이미지가있는 것으로 보입니다. 가능한 최소의 메모리 사용량은 픽셀 당 ~ 4 바이트입니다 (각 픽셀은 int으로 표시됨).

+0

그래, 나는 캐릭터의 애니메이션을위한 많은 이미지를 가지고있다. 메모리 소비를 줄이기 위해 권장되는 방법은 무엇입니까? 대부분의 이미지는 250x250입니다. –

+0

@ElliotFrisch가 말했듯이, Xmx 값을 줄이십시오. 1G로 설정 한 경우 jvm에 최대 1GB의 메모리를 사용할 수 있다고 말한 것입니다. 당신은 그것이 그것을 사용하기로 결정한 것을 놀래켜서는 안됩니다. 사용 된 메모리를 줄이는 첫 번째 단계는 jvm이 사용할 수있는 양을 제한하는 것입니다. –

+0

그래, 내가 그것을 500MB로 약간 뽑아서 OutOfMemory라고한다. 나는 모든 다른 RAM 수를 시도했다. 800MB-1g는 어떤 이유로 달콤한 장소입니다. –