Среда, 13 Ноября 2024, 12:14

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Оптимизация памяти в Libgdx игре
AlexSteinДата: Пятница, 26 Июня 2015, 07:55 | Сообщение # 1
частый гость
Сейчас нет на сайте
Есть проблема, имеется 2 текстуры ( Тайлсет врагов и бэкграунд), из тайлсета врагов я вытаскиваю 29 регионов. Дополнительно имеется текстура с 1 анимацией, 2 дорожки с музыкой и 1 звук. У меня есть статический класс Assets, в котором я загружаю все ресурсы. В чём проблемы: память утекает в никуда. Какие есть способы оптимизировать затраты памяти?
Какие способы существуют для оптимизации?


Сообщение отредактировал AlexStein - Пятница, 26 Июня 2015, 08:20
last2424Дата: Пятница, 26 Июня 2015, 08:26 | Сообщение # 2
30 мл. блоков
Сейчас нет на сайте
AlexStein, существуют какие-то, но на очень сильную оптимизацию не надейтесь... это JAVA.

Предупреждение: всё что я написал в зачёркнутом виде является шуткой и никак не пытает обидеть того к кому обращаются.(нет)
AlexSteinДата: Пятница, 26 Июня 2015, 08:39 | Сообщение # 3
частый гость
Сейчас нет на сайте
Цитата last2424 ()
AlexStein, существуют какие-то, но на очень сильную оптимизацию не надейтесь... это JAVA.

Предрассудки предрассудками, но Java - достаточно мощный инструмент для создания игр, и затраты памяти не сильно превышают аналоги...
FadeBakerДата: Пятница, 26 Июня 2015, 09:23 | Сообщение # 4
JavaSE Game Developer
Сейчас нет на сайте
AlexStein, покажите наиболее подозрительный код, который, как вы считаете, больше всего может быть ответственен за утечку. Без него трудно что-либо сказать.

Цитата last2424 ()
но на очень сильную оптимизацию не надейтесь... это JAVA.

С кривыми руками и Hello World тормозить будет.


Уроки по GM
Minecraft 2D на GM
— Мои проекты —
Blood Harvest [2D] — Original
Blood Harvest [2D]: Remastered Edition
Adventure Craft [2D] — Sandbox
Space Shock [2D] — Scroll Shooter
Intel® Core™ i5-3570K 3.40 GHz, 8 GB RAM, GeForce GTX 750 Ti, Monitor: LG 23EA63V-P.
AlexSteinДата: Пятница, 26 Июня 2015, 09:26 | Сообщение # 5
частый гость
Сейчас нет на сайте
Цитата FadeBaker ()
AlexStein, покажите наиболее подозрительный код, который, как вы считаете, больше всего может быть ответственен за утечку. Без него трудно что-либо сказать.

Цитата last2424 ()
но на очень сильную оптимизацию не надейтесь... это JAVA.

С кривыми руками и Hello World тормозить будет.


Код

   @Override
   public void render(float delta) {   
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    game.batch.setProjectionMatrix(this.camera.combined);
    this.game.batch.disableBlending();
    this.game.batch.begin();
    this.game.batch.draw(Assets.background,0,0,1024,768);
    this.game.batch.end();
    this.update();
    this.game.batch.enableBlending();
    this.game.batch.begin();
    this.platform.draw(this.game.batch);
    this.drawCurrentEnemy();
    this.drawCurrentEnemyHealthPoint();
    if(Settings.soundEnabled)
     Assets.drawString(game.batch, "Sound: ON",870 , 750, 15, Color.WHITE);
    else
     Assets.drawString(game.batch, "Sound: OFF", 870, 750, 15, Color.WHITE);
    if(this.enableDamageUpgrade)
    {
     this.enableUpgrade.draw(game.batch);
    }
    else
    {
     this.disableUpgrade.draw(game.batch);
    }
    this.game.batch.end();
   }

   @Override
   public void pause() {
    Settings.save();
   }
   @Override
   public void dispose() {
   }
   private void drawCurrentEnemy(){
    switch(currentEnemy)
    {
     case CASE:
     {
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.weaponCase.setSize(Assets.weaponCase.getRegionWidth()/2,Assets.weaponCase.getRegionHeight()/2);
       this.weaponCase.setPosition((float) (512-Assets.weaponCase.getRegionWidth()/4),(float) (384-Assets.weaponCase.getRegionHeight()/4));
      }
      else
      {
       this.weaponCase.setSize((float) (Assets.weaponCase.getRegionWidth()/2.1),(float) (Assets.weaponCase.getRegionHeight()/2.1));
       this.weaponCase.setPosition((float)(512-Assets.weaponCase.getRegionWidth()/4.2),384-Assets.weaponCase.getRegionHeight()/4);
      }
      this.weaponCase.draw(game.batch);
      break;
     }
     case GABE:
     {
      this.game.batch.draw(Assets.body,512+Assets.body.getRegionWidth()/4,384-Assets.body.getRegionHeight()/4,-Assets.body.getRegionWidth()/2,Assets.body.getRegionHeight()/2);
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       //game.batch.draw(Assets.faceGabe1,667-Assets.faceGabe1.getRegionWidth()/2,364+Assets.body.getRegionHeight()/4,Assets.faceGabe1.getRegionWidth()/4,Assets.faceGabe2.getRegionHeight()/4);
       this.gabeHead1.draw(this.game.batch);
      else   
       //game.batch.draw(Assets.faceGabe2,667-Assets.faceGabe2.getRegionWidth()/2,364+Assets.body.getRegionHeight()/4,Assets.faceGabe1.getRegionWidth()/4,Assets.faceGabe2.getRegionHeight()/4);
       this.gabeHead2.draw(this.game.batch);
      break;
     }
     case STANDART:
     {
      this.game.batch.draw(Assets.body,522-Assets.body.getRegionWidth()/4,384-Assets.body.getRegionHeight()/4,Assets.body.getRegionWidth()/2,Assets.body.getRegionHeight()/2);
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       this.face1.draw(game.batch);
      else
       this.face2.draw(game.batch);
      break;
     }
     case SOUVENIR:
     {   
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.souvenir.setSize(Assets.souvenirCase.getRegionWidth()/2, Assets.souvenirCase.getRegionHeight()/2);
       this.souvenir.setPosition(512-Assets.souvenirCase.getRegionWidth()/4, 334-Assets.souvenirCase.getRegionHeight()/4);
      }
      else
      {      
       this.souvenir.setSize((float)(Assets.souvenirCase.getRegionWidth()*0.45),(float)( Assets.souvenirCase.getRegionHeight()*0.45));
       this.souvenir.setPosition((float)(512-Assets.souvenirCase.getRegionWidth()*0.225), (float)(334-Assets.souvenirCase.getRegionHeight()*0.225));
      }
      this.souvenir.draw(game.batch);
      break;
     }
     case STEAM_BOX:
     {
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.steamBox.setSize((float)(Assets.steamBox.getRegionWidth()/3),(float)(Assets.steamBox.getRegionHeight()/3));
       this.steamBox.setPosition((float) (512-Assets.steamBox.getRegionWidth()/6),(float) (364-Assets.steamBox.getRegionHeight()/6));
       }
      else
      {
       this.steamBox.setSize((float) (Assets.steamBox.getRegionWidth()/3.1),(float) (Assets.steamBox.getRegionHeight()/3.1));
       this.steamBox.setPosition((float)(512-Assets.steamBox.getRegionWidth()/6.2),(float) (364-Assets.steamBox.getRegionHeight()/6) );
      }
      this.steamBox.draw(game.batch);
      break;
     }
     case STEAM:
     {
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.steam.setPosition(512-Assets.steam.getRegionWidth()/4,384-Assets.steam.getRegionHeight()/4);
       this.steam.setSize(Assets.steam.getRegionWidth()/2, Assets.steam.getRegionHeight()/2);
      }
      else
      {
       this.steam.setPosition((float)(512-Assets.steam.getRegionWidth()*0.24),(float)(384-Assets.steam.getRegionHeight()*0.24));
       this.steam.setSize((float)(Assets.steam.getRegionWidth()*0.48), (float)(Assets.steam.getRegionHeight()*0.48));
      }
      this.steam.draw(game.batch);
      break;
     }
     case DISCOUNT:
     {
      if(this.currentEnemyHealth/this.maxHealth>0.75)
      {
       if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       {
        this.discount10.setSize(Assets.discount10.getRegionWidth(), Assets.discount10.getRegionHeight());
        this.discount10.setPosition((float)(512-Assets.discount10.getRegionWidth()/2), (float)(384-Assets.discount10.getRegionHeight()/2));
       }
       else
       {
        this.discount10.setSize(Assets.discount10.getRegionWidth()*0.9f, Assets.discount10.getRegionHeight()*0.9f);
        this.discount10.setPosition((float)(512-Assets.discount10.getRegionWidth()*0.45f), (float)(384-Assets.discount10.getRegionHeight()*0.45f));
       }
       this.discount10.draw(game.batch);
      }
      else if(this.currentEnemyHealth/this.maxHealth>0.5)
      {       
       if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       {
        this.discount50.setSize(Assets.discount50.getRegionWidth(), Assets.discount50.getRegionHeight());
        this.discount50.setPosition((float)(512-Assets.discount50.getRegionWidth()/2), (float)(384-Assets.discount50.getRegionHeight()/2));
       }
       else
       {
        this.discount50.setSize(Assets.discount50.getRegionWidth()*0.9f, Assets.discount50.getRegionHeight()*0.9f);
        this.discount50.setPosition((float)(512-Assets.discount50.getRegionWidth()*0.45f), (float)(384-Assets.discount50.getRegionHeight()*0.45f));
       }
       this.discount50.draw(game.batch);
      }
      else if(this.currentEnemyHealth/this.maxHealth>0.25)
      {
       if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       {
        this.discount75.setSize((float)(Assets.discount75.getRegionWidth()*0.8f),(float)( Assets.discount75.getRegionHeight()*0.75f));
        this.discount75.setPosition((float)(512-Assets.discount75.getRegionWidth()*0.4),(float)( 384-Assets.discount75.getRegionHeight()*0.375));
       }
       else
       {
        this.discount75.setPosition((float)(512-Assets.discount75.getRegionWidth()*0.35),(float)( 384-Assets.discount75.getRegionHeight()*0.326325));
        this.discount75.setSize((float)(Assets.discount75.getRegionWidth()*0.7), (float)(Assets.discount75.getRegionHeight()*0.65265));
       }
       this.discount75.draw(game.batch);
      }
      else   
      {
       if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
       {
        this.discount90.setPosition((float)(512-Assets.discount90.getRegionWidth()*0.375),(float)( 384-Assets.discount90.getRegionHeight()*0.375));
        this.discount90.setSize((float)(Assets.discount90.getRegionWidth()*0.75), (float)(Assets.discount90.getRegionHeight()*0.75f));
       }
       else
       {
        this.discount90.setPosition((float)(512-Assets.discount90.getRegionWidth()*0.325),(float)( 384-Assets.discount90.getRegionHeight()*0.325));
        this.discount90.setSize((float)(Assets.discount90.getRegionWidth()*0.65), (float)(Assets.discount90.getRegionHeight()*0.65f));
       }
       this.discount90.draw(game.batch);
      }
      break;
     }
     case EARLY_ACCESS:
     {
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.earlyAccess.setSize((float)(Assets.earlyAccess.getRegionWidth()*0.5),(float)(Assets.earlyAccess.getRegionHeight()*0.5));
       this.earlyAccess.setPosition((float)(495-Assets.earlyAccess.getRegionWidth()*0.25),(float)(369-Assets.earlyAccess.getRegionHeight()*0. 2 5));
      }
      else
      {
       this.earlyAccess.setSize((float)(Assets.earlyAccess.getRegionWidth()*0.45),(float)(Assets.earlyAccess.getRegionHeight()*0.45));
       this.earlyAccess.setPosition((float)(495-Assets.earlyAccess.getRegionWidth()*0.225),(float)(369-Assets.earlyAccess.getRegionHeight()*0 . 225));
      }
      this.earlyAccess.draw(game.batch);
      break;
     }
     case DLC:
     {
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.dlc.setSize((float)(Assets.dlc1.getRegionWidth()*0.5), (float)(Assets.dlc1.getRegionHeight()*0.5));
       this.dlc.setPosition((float)(512-Assets.dlc1.getRegionWidth()*0.25),(float)(364 - Assets.dlc1.getRegionHeight()*0.25));
      }
      else
      {
       this.dlc.setSize((float)(Assets.dlc1.getRegionWidth()*0.45), (float)(Assets.dlc1.getRegionHeight()*0.45));
       this.dlc.setPosition((float)(512-Assets.dlc1.getRegionWidth()*0.225),(float)(364 - Assets.dlc1.getRegionHeight()*0.225));
      }
      this.dlc.draw(game.batch);
      break;
     }
     case MONEY:
     {   
      if((TimeUtils.nanoTime()-lastClickTime>130000000 && click)|| !click)
      {
       this.moneyPack.setPosition(512-Assets.moneyPacket.getRegionWidth()/2, 384-Assets.moneyPacket.getRegionHeight()/2);
       this.moneyPack.setSize(Assets.moneyPacket.getRegionWidth(), Assets.moneyPacket.getRegionHeight());
      }
      else
      {
       this.moneyPack.setPosition((float)(512-Assets.moneyPacket.getRegionWidth()*0.45f), (float)(384-Assets.moneyPacket.getRegionHeight()*0.45f));
       this.moneyPack.setSize((float)(Assets.moneyPacket.getRegionWidth()*0.9f),(float)( Assets.moneyPacket.getRegionHeight()*0.9f));
      }
      this.moneyPack.draw(game.batch);
      break;
     }
    }
   }
   private void drawCurrentEnemyHealthPoint(){
    //Assets.drawString(game.batch, "HP = "+this.currentEnemyHealth, 450, 100, 20, Color.WHITE);
    Assets.fullHp.setRegionWidth((int) (this.currentEnemyHealth*Assets.HpWidth/this.maxHealth));
    this.fullHp.setRegion(Assets.fullHp);
    this.fullHp.setSize(Assets.fullHp.getRegionWidth()/2, Assets.fullHp.getRegionHeight()/2);
    this.fullHp.draw(game.batch);
    this.hpBar.draw(game.batch);
   }
   private void update(){
    System.out.println(Gdx.app.getNativeHeap());
    System.gc();
    //Обработка кликов мышкой
    if(this.enemyList.size()<10)
    {
     this.newEnemy();
    }
    if(Gdx.input.justTouched())
    {
     this.camera.unproject(this.touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
     if(this.touchBounds.contains(this.touchPoint.x, this.touchPoint.y))
     {
      this.lastClickTime=TimeUtils.nanoTime();
      this.currentEnemyHealth=this.currentEnemyHealth-this.Damage;
      this.click=true;
     }
     if(this.soundBounds.contains(this.touchPoint.x,this.touchPoint.y))
     {
      Settings.soundEnabled=!Settings.soundEnabled;
      if(Settings.soundEnabled)
       Assets.gameMusic.play();
      else
       Assets.gameMusic.pause();
     }
     if(this.enableDamageUpgrade)
      if(this.damageUpBounds.contains(this.touchPoint.x,this.touchPoint.y))
      {
       this.Damage+=25;
       this.upgradeCount--;
       this.enableDamageUpgrade=false;
      }
    }
      
    //Чит на увеличение здоровья врага
    if(Gdx.input.isKeyJustPressed(Keys.J))
    {
     this.lastClickTime=TimeUtils.nanoTime();
     this.currentEnemyHealth=this.currentEnemyHealth+this.Damage;
     this.click=true;
    }
      
    if(this.currentEnemyHealth<=0)
    {
     //Проверка на каждый пятый и каждый пятый +1 уровень
     if((level+1)%5==0)
      this.maxHealth+=level*1000;
     else if(level%5==0)
     {
      this.maxHealth-=(level-1)*1000;
      this.maxHealth+=level*100;
     }
     else
      this.maxHealth+=level*100;    
      
     //Включение кнопки увеличения уровня
     if(level%2==0)
     {
      this.upgradeCount++;
      this.enableDamageUpgrade=true;
     }   
       
     //Установка здоровья следующего врага
     this.currentEnemyHealth=this.maxHealth;
       
       
     //Смена врага
     this.enemyList.remove(0);        
     this.level++;
     if(level%5==0)
      this.newBoss();
     this.currentEnemy=this.enemyList.get(0);
     this.lastClickTime=TimeUtils.nanoTime()-99999999;
       
    }
   }
   private void newEnemy(){
    switch(MathUtils.random(0, 7))
    {
     case 0:
     {
      this.enemyList.add(Enemy.DISCOUNT);
      break;
     }
     case 1:
     {
      this.enemyList.add(Enemy.DLC);
      break;
     }
     case 2:
     {
      this.enemyList.add(Enemy.EARLY_ACCESS);
      break;
     }
     case 3:
     {
      this.enemyList.add(Enemy.GABE);
      break;
     }
     case 4:
     {
      this.enemyList.add(Enemy.MONEY);
      break;
     }
     case 5:
     {
      this.enemyList.add(Enemy.STANDART);
      break;
     }
     case 6:
     {
      this.enemyList.add(Enemy.STEAM);
      break;
     }
     case 7:
     {
      this.enemyList.add(Enemy.STEAM_BOX);
     }
    }    
   }
   private void newBoss(){
    switch(MathUtils.random(0, 1))
    {
     case 0:
     {
      this.enemyList.set(0, Enemy.CASE);
      break;
     }
     case 1:
     {
      this.enemyList.set(0, Enemy.SOUVENIR);
      break;
     }
    }
   }


Подозреваю проблемы в этом коде ибо память улетает после начала прорисовки врагов

Полный код класса в котором я подозреваю проблемы: http://rghost.ru/private/8j6dHnSSq/248254eabca8428076b66a945aa76cf6


Сообщение отредактировал AlexStein - Пятница, 26 Июня 2015, 09:33
1nt3g3rДата: Пятница, 26 Июня 2015, 11:24 | Сообщение # 6
почетный гость
Сейчас нет на сайте
AlexStein, замечание по коду - стиль просто ахтунг.

Не делайте, пожалуйста, такие огромные switch - это безобразно.

Для отдельных обьектов (враги, бонусы) используйте отдельные классы на основе Image или Actor.

Не вызывайте System.gc() каждый раз в update() - это затратная операция, и игра может лагать. Постарайтесь вообще не вызывать этот метод.

Используйте Array (встроенная коллекция libGDX) вместо ArrayList - это уменьшит потребление памяти

Используйте обработчики событий (EventListener, ClickListener) вместо Gdx.input.isTouched(). Это сделает ваш код чище и понятней

По конкретно вашему вопросу - я не нашел какой-то явной утечки памяти. Как вы обнаружили утечку (как меряли)? Сколько памяти течет (за минуту, например)? По вашему Assets - еще его нужно посмотреть. Например, Assets.drawString() - это черный ящик, в котором может быть что угодно (например, вы создаете каждый раз новый шрифт).

Как заключение - пока вы не приведете код в порядок, найти какую-либо ошибку будет очень и очень тяжело.


Нужно писать такие игры, чтобы в них было интересно играть самому
AlexSteinДата: Пятница, 26 Июня 2015, 11:26 | Сообщение # 7
частый гость
Сейчас нет на сайте
Цитата 1nt3g3r ()
AlexStein, замечание по коду - стиль просто ахтунг.

Не делайте, пожалуйста, такие огромные switch - это безобразно.

Для отдельных обьектов (враги, бонусы) используйте отдельные классы на основе Image или Actor.

Не вызывайте System.gc() каждый раз в update() - это затратная операция, и игра может лагать. Постарайтесь вообще не вызывать этот метод.

Используйте Array (встроенная коллекция libGDX) вместо ArrayList - это уменьшит потребление памяти

Используйте обработчики событий (EventListener, ClickListener) вместо Gdx.input.isTouched(). Это сделает ваш код чище и понятней

По конкретно вашему вопросу - я не нашел какой-то явной утечки памяти. Как вы обнаружили утечку (как меряли)? Сколько памяти течет (за минуту, например)? По вашему Assets - еще его нужно посмотреть. Например, Assets.drawString() - это черный ящик, в котором может быть что угодно (например, вы создаете каждый раз новый шрифт).

Как заключение - пока вы не приведете код в порядок, найти какую-либо ошибку будет очень и очень тяжело.


Ок, спасибо, сейчас буду изменять код и попробую ещё раз отловить утечку.
JhonДата: Пятница, 26 Июня 2015, 11:42 | Сообщение # 8
частый гость
Сейчас нет на сайте
А можно поподробнее, как была обнаружена утечка памяти? Я просто тоже пишу на libgdx, но в Javа новичок, поэтому еще не знаком с инструментами.
AlexSteinДата: Пятница, 26 Июня 2015, 12:46 | Сообщение # 9
частый гость
Сейчас нет на сайте
Цитата Jhon ()
А можно поподробнее, как была обнаружена утечка памяти? Я просто тоже пишу на libgdx, но в Javа новичок, поэтому еще не знаком с инструментами.

Во время работы приложение тратило слишком много памяти и используемая память только увеличивалась.

-------------------------------------------------------------------------------------------------------------------------------
И вновь у меня проблема, память утекает тогда и только тогда, когда начинается рендер... В этом проблема

-------------------------------------------------------------------------------------------------------------------------------

Утечка найдена - множественное пересоздание публичных статических переменных...
FadeBaker и 1nt3g3r, спасибо за помощь!


Сообщение отредактировал AlexStein - Пятница, 26 Июня 2015, 13:18
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг