PImage array and particule system, bad performances on Android

edited February 2016 in Android Mode

Hi,

I'm working on a particules system app for android. I have an array of PImage, from which I select which image will be part of my system. This system emit 5 particules each frame. On my computer, regardless of the nbr of image I select, my framerate is around 60fps. But in Android, The more I select images, the more the framerate drop (around 20 fps when I select 10 image, event if my system still emit 5 particules/frame). I try to change the scope of my array, but I have the same pb if I pass my array as an argument for my constructor, or if I made a copy of it in my particule class, I don't have better result. I guess is related how the way android manage and keep in memory the image, perhaps somebody kno a bit about this...

Any clue, suggestion, idea, advice?

Thanks for yout help!

Answers

  • @Adrien=== can you post some snippet code in order to test???

  • edited February 2016

    Hi Akenaton, thanks to take time to help.

    I can see the same kind of pb if I use Shiffman's SmokeParticule example with some minor change : To do : copy 13 time the "texture.png" image in the data folder, rename them 0.png, 1.png, etc. Here is the sketch with some small changes. You can see in the addParticle method, in the ParticuleSystem class than when I go look for images in the imgs PImage array, the frameRate drop to 37 (it stay at 60 on my computer). I achieved better perfomance with my own program using more local variable, but I still would like to uniderstand why we loose 23fps just by looking in an array... Thanks for your help!

    The code :

    ParticleSystem ps;
    PImage[] imgs;
    PImage oneImg; 
    
    void setup() {
      size(displayWidth, displayHeight, P2D);
      oneImg=loadImage ("0.png"); 
      imgs = new PImage[13];
      for (int i=0; i<imgs.length; i++) {
        imgs[i] = loadImage (i+".png");
      }
      ps = new ParticleSystem(0, new PVector(width/2, height/2), oneImg);
    }
    void draw() {
      background(0);
      text("fps : " + frameRate, 20, 20); 
      text ("nbr of parts : "+ps.particles.size(), 20, 40); 
      ps.run();
      ps.addParticle();
    }
    
    // A class to describe a group of Particles
    // An ArrayList is used to manage the list of Particles 
    
    class ParticleSystem {
    
      ArrayList<Particle> particles; // An arraylist for all the particles
      PVector origin; // An origin point for where particles are birthed
      PImage img;
      PImage imgLoc;
    
      ParticleSystem(int num, PVector v, PImage img_) {
        particles = new ArrayList<Particle>(); // Initialize the arraylist
        origin = v.get(); // Store the origin point
        img = img_;
        imgLoc=loadImage("0.png"); 
        for (int i = 0; i < num; i++) {
          particles.add(new Particle(origin, img)); // Add "num" amount of particles to the arraylist
        }
      }
    
      void run() {
        for (int i = particles.size()-1; i >= 0; i--) {
          Particle p = particles.get(i);
          p.run();
          if (p.isDead()) {
            particles.remove(i);
          }
        }
      }
    
      void addParticle() {
        for (int i=0; i<10; i++) {
          int r = int(random(imgs.length));
    
          particles.add(new Particle(origin, imgs[r])); //37 fps
    
          // particles.add(new Particle(origin, imgs[0])); 60fps
          //particles.add(new Particle(origin, img)); //60fps
          // particles.add(new Particle(origin, imgLoc)); //60 fps
        }
      }
    }
    
    // A simple Particle class, renders the particle as an image
    
    class Particle {
      PVector loc;
      PVector vel;
      PVector acc;
      float lifespan;
      PImage img;
    
      Particle(PVector l, PImage img_) {
        acc = new PVector(0, 0);
    
        vel = new PVector(random(-1, 1), random(-3));
        loc = l.get();
        lifespan = 100.0;
        img = img_;
      }
    
      void run() {
        update();
        render();
      }
    
      // Method to update location
      void update() {
        loc.add(vel);
        lifespan -= 2.5;
      }
    
      // Method to display
      void render() {
        imageMode(CENTER);
        tint(255, lifespan);
        image(img, loc.x, loc.y);
      }
    
      // Is the particle still useful?
      boolean isDead() {
        if (lifespan <= 0.0) {
          return true;
        } else {
          return false;
        }
      }
    }
    
  • highlight code, hit ctrl-o to format.

  • you got loadImage in the constructor of the class

    it may better to use the images you initially loaded in setup() only

  • edited February 2016

    Hi Koogs, yeah, I tried different ways to post my code before find to right way to do it! ;-)

  • edited February 2016

    Hi Chrisir, Acually I actually useimgLoc=loadImage("0.png"); in the constructor to test with different scope (if you uncommentparticles.add(new Particle(origin, imgLoc)); //60 fps); but I also have 60 fps using this way. It's when I use particles.add(new Particle(origin, imgs[r])); //37 fps (randomly pick an image in my global PImage array) than the frameRate drop (on my android device, not on my PC where I still have 60fps), and I'm curious to understand why...

  • how big are the images each?

  • 32*32, 3.47 Ko (all images are the same one copy 13 times)

  • edited February 2016

    size(displayWidth, displayHeight, P2D);

    Remove the "P2D" from your size() function and then run it and see what happens. Just curious at this point based on results in this discussion thread: https://forum.processing.org/two/discussion/14874/p2d-now-slow-even-on-an-empty-sketch-wasn-t-so-slow-before#latest

  • edited February 2016

    @ SiriusCG, yeah, the empty sketch run at 60fps without the P2D on my comupter, but what's very strange it's I'm sure that it was running at 60fps with P2D this morning... But on my android device I need to use P2D, or it's really really slow...

  • If you don't need any 3D for your sketch, use either JAVA2D or FX2D renderer. >-)

  • @GoToLoop : when I use JAVA2D on my Android device, the sketch above (with particles.add(new Particle(origin, imgs[r])); //37 fpsuncommented) drop at 3fps...and FX2D is not accepted...

  • Android doesn't have the native library necessary to use FX2D renderer I'm afraid. 8-|

  • edited February 2016

    @Adrien, Hmm, ok. We can look elsewhere then. What is your mobile device and what Android version is installed? If you could post the entire file with images somewhere I could do some troubleshooting on my Samsung.

  • Thanks all for your help.

    SiriusCG, you'll find the sketch folder here we.tl/sKuCjf1kUd

    I improved a bit the performance by following advices found here : developer.android.com/training/articles/perf-tips.html, specially using more local variables, avoiding the lookups.

    By clicking on the little images on the left, you decide wich images will be part of the particule system If I just selected 1 image, when moving a finger on the screen, fps is around 55 (max particule nbr : 255). If I select 2 images, fps drop around 38 (still with a max of 255 particules alive). If I select 3 images, fps is around 33, etc.

    What about you?

    I have a samsung galaxy tab s 10.5 with Android 5.0.2. I run my processing sketch with APDE.

    Again, thanks all for your time and for your help.

  • edited February 2016

    No worries. Gives me a chance to work on my Android skills. :) My device is a Samsung Tab 4 7, Android 4.4.2, 8Gb, Cortex A-7 1.2Ghz Quad core, Opengl ES 3.1. So let's see ...

    Ok, your code runs between 18fps down to 13fps on my Samsung with 255 particles showing if I select 1,2 or 3 images. If I turn on Force GPU I gain 2fps. Not too surprised as your device has better specs than mine. On my PC it runs a solid 32-34fps and I can get 255 particles on screen. That is interesting as you mention getting 60fps on yours.

    I wish there was a process profiler or logging facility to inspect how long some of these calls were taking. Sorry I'm not providing much help here ...

Sign In or Register to comment.