Jump to content

Mobile performance - tips && tricks


valueerror
 Share

Recommended Posts

  • 2 weeks later...

not  Phaser code below but as an example, from what I understand when avoiding prototypes you don't extend Sprite you make it a property 

 

a basic JS-only example of avoiding 'prototype' & 'new' as suggested here: http://www.html5gamedevs.com/topic/9931-mobile-performance-tips-tricks/ .

 

I'm not sure it's totally correct, but it works

https://jsfiddle.net/yhx43cnm/

 

of course the Phaser library itself uses prototype throughout, all you'd be doing is reducing the prototype-chain I guess.

function setSpritePos(x,y){    this.sprite.x = x    this.sprite.y = y}Sprite = function(game,x,y,name) {    this.game = game;    this.x = x;    this.y = y;    this.name = name;    return this;}BallObject = function(game, x, y) {    this.sprite = new Sprite(game,x,y, 'basketball')    this.setPos = setSpritePos;    return this;};var game = {id: 'myGame'} var b = BallObject(game,0,0);var b2 = BallObject(game,0,0);b.setPos(20,30);b2.setPos(120,130);console.log("b: " + b.sprite.x + "," + b.sprite.y);console.log("b2: " + b2.sprite.x + "," + b2.sprite.y);
Link to comment
Share on other sites

There's a jsperf you can run: http://jsperf.com/closure-prototype-static-performance

Not sure it's a good benchmark - I believe it includes construction in the loop

Well, the difference is only 2x faster which doesn't mean much considering the fact that this benchmark doesn't access any members or global variables. I still think that using prototypes is ok and recommended and is most often not your bottleneck.

Link to comment
Share on other sites

  • 4 months later...

I wouldnt worry about prototypes, JS is optimised to use prototypes anyway and has been for a long time. Almost every library I can think of using prototypes and they are all performance tested to the hilt, Phaser included. (Granted prototypes are mainly for memory rather than performance but there are still perf benefits that can, and have, been made when using a prototypal language).

If the prototype chain gets very long, say 5 or 6 prototypes, then access can be slower, but its not a given (it is, of course, mostly dependent on what you do).

The other issue which is generally just skirted around: removing prototypes from your code is hard, like, seriously hard. It'll up your dev time, it'll up your debug time and it will eat away at your soul! You'd need a concrete use-case where doing the work is necessary.

Memoizing functions, or using thunks to create closures, is a very valid optimisation technique though. I'm not clear if maybe these two points, memoization and prototype removal, are getting confused.

Link to comment
Share on other sites

I modified the JSPerf to be a bit more accurate. If you add an "initialize" function to be run on the raw object in the same way a constructor would, you'll see the performance is actually worse on FireFox and not much better on Chrome. Therefore, I recommend you DO use prototypes for ease of development.

http://jsperf.com/closure-prototype-static-performance/28

Link to comment
Share on other sites

  • 3 months later...
On 10/21/2014 at 9:45 PM, valueerror said:

Because a new thread on this topic pops up every 2 to 3 days in this forum I would like to fill this thread (this first post to be precise) with tips and tricks to maximize mobile performance or things you should probably avoid if targeting mobile devices.

 

I totally rely on your support because my own knowledge on this topic is quite limited.

 

giving explanations(why a tip actually works), pointing out errors in this post, and new tips to fill this post would be very appreciated. (i don't want to spread false "knowledge" )

 

thx in advance !

 

:)

 

P2:

  • polygon shapes will be more expensive than simple circles - especially huge polygons (keep them simple)
  • enabling p2 impactEvents is expensive - use onBeginContact instead
  • having a bunchload of revolute constraints seems to be expensive
  •  

 

 

Arcade:

  • don't call  game.physics.arcade.collide   20 times in the update loop.. try to do the same thing with 5 calls ;-)
  •  

 

 

Both (general programming) :

  • reuse sprites whenever possible - create multiple / kill and revive them (e.g. bullets)
  • be careful with the resolution of your game 640x480 will run faster than 1024x768
  • keep physics simple 
  • instead of "game.time.now" use "game.time.time" or one of the physicsElapsed values, as "now" can often contain high precision timer values (depending on the browser)
  • arcade is faster than p2
  • rendering normal text is expensive, using bitmap-fonts seems to be better but is still somehow heavy on mobile 
  • using tilemaps with more than 2 layers is going to be slow (depending on your device) - try the new tilemap plugin
  • huge tilemaps will be slow
  • when using webGL use a sprite atlas that contains all your sprites instead of many different image files.
  • make use of the particles system - but not to much ^^ (it may be better to use the particlesystem than to create all particles "by hand" but spawning particles will cause a frame drop on slow devices)
  • try to keep the update loop simple - do not call a function 60 times a second if not definitely needed
  • make sure the garbage collector can free some memory - use var  ^^
  • make sure the garbage collector doesn't have too much to do - don't create new objects all the time (functions are treated in the same way)  and finding the balance between to much and to little is the trick
  • don't use the native webview (especially on older android versions) - use a wrapper (like cocoonjs) or use intel crosswalk (which builds on chromium)
  • intel  crosswalk seems to run much better with webgl enabled
  • cocoonjs seems to run much better in canvas mode
  • do not use splice. If you have only one element to cut off an array, use this function, which is multiple times faster that the build in one, and aside it low GC (the built in is the opposite!): 1-item-splice
  • using a lot of tweens in parallel can cause lags
  • using Prototype simply slows down things. It's faster to use precached functions.
  • do not use classes, no new, no prototype, no this, track length by yourself, use custom splice or avoid it completely by using double linked lists
  • tweens that start on creation of a state will be choppy.. use game.time.events.add(1, fadeIn); to delay the tween (it seems that game.time.events will not start before everything is loaded)
  •  

Hey there :)
I am having troubles with the mobile performance myself. I would really appreciate some advice. I've read the recommendations and the only thing that might be slowing me down is the prototyping. Can somebody explain why does the use of a lot of prototypes makes things slow? Let me explain my case:

I have a slot game without any physics. It runs on Canvas, since the WebGL takes 40 fps away :D. 
I am trying to write the code in classes (40 of them) but without the 'class' keyword from ES6, but like this:
 

//file1.js
//I call the Reel via 

this.reel = new Reel(this.game, idx);

//file2.js
Reel = function (game, idx)
{
    Phaser.Group.call(this, game);
    

    for (var symIdx = 0; symIdx < NUM_SYMS; symIdx++)
    {
        this.symbol = new Symbol(game, 0, 0);
    }

    this.reelBack.events.onInputDown.add(this.someFunction, this);
};

Reel.prototype = Object.create(Phaser.Group.prototype);
Reel.prototype.constructor = Reel;

Reel.prototype.someFunction = function(silent)
{
    //Some stuff
};

Is this a really bad approach? I mean, almost everything is prototyped, but I am afraid I am not sure how to use MVC structure or any well-organized code.
On desktop, it is fine of course, but on mobile, only high-end devices don't mind my code :D For example, the iphone 4 makes about 15 fps max, some chinese tablets - 2-5fps max.... 

Link to comment
Share on other sites

Prototyping is not going to be a big performance hit at all(from my experience), almost all JS games do prototyping, RPG Maker MV game engine is 85% prototyping, even Phaser uses prototype among many other frameworks.

As for extending a class without the use of prototyping I have yet to see any examples of it being accomplished and if it can be accomplished how would there be more than one function containing all of the methods inside. In the end, If somehow prototyping is slow then not using it will result in messy code and feel next to impossible to debug or read. It will be all a choice in the end for the developer but I prefer the readability prototyping brings.

I did a quick google search and found this from a year ago with benchmarks of prototyping and not prototyping, I like the results https://www.reddit.com/r/webdev/comments/3cbz6o/to_prototype_or_not_to_prototype_a_look_at_memory/

Speed:

Rolling Without Prototyping: 7ms

Rolling With Prototyping: 8ms

Memory Usage

Closure: 5600 bytes

Prototype: 1600 bytes

Link to comment
Share on other sites

15 hours ago, LTNGames said:

As for extending a class without the use of prototyping I have yet to see any examples of it being accomplished and if it can be accomplished how would there be more than one function containing all of the methods inside. 

You're suggesting using some other method for a class-restricted pattern without using classes/prototypes, the removal of prototypes requires more than simply porting the methodology to a different system. For example, moving to a functional style means that 'extending a class' makes no sense, but there are a few other methods for 'adding functionality or behaviours'. Higher-order functions (googling higher-order components might give better results for anyone looking into it) can be used to add behaviours to existing procedures, but even then its not strictly analogous to extending prototypes.

Removing prototypes and `this` from your code in JS should not be made for perf or memory concerns.

Link to comment
Share on other sites

For all future readers. I used to get 30 fps on an iPhone 4s. Fixed it by checking the device first, put the renderer on WebGL, remove the advanced timing and fps count and BINGO - 60fps:)


Also, after the game ran perfectly on iphone 4s, my Samsung Galaxy S3 Neo (Chrome) started to render the game at 30 fps when using WebGL instead of Canvas(60fps). After 2 weeks of testing and stuff, I have concluded that, for some reason, the android 4.4.2 phones, like Canvas more than WebGL. Newer devices, like Samsung Galaxy S6 and S7, don't care because of the power they provide.


So what you need to do is check the device, if android - Canvas, if iOS - WebGL. That is based on a very simple game, no physics or whatsoever.

Link to comment
Share on other sites

On 6/15/2016 at 4:59 AM, mattstyles said:

You're suggesting using some other method for a class-restricted pattern without using classes/prototypes, the removal of prototypes requires more than simply porting the methodology to a different system. For example, moving to a functional style means that 'extending a class' makes no sense, but there are a few other methods for 'adding functionality or behaviours'. Higher-order functions (googling higher-order components might give better results for anyone looking into it) can be used to add behaviours to existing procedures, but even then its not strictly analogous to extending prototypes.

Removing prototypes and `this` from your code in JS should not be made for perf or memory concerns.

3

I'm not suggesting anything, I was actually elaborating on the OP saying to not use prototypes, I use prototyping for everything and was pretty much just saying why, I agree with everything you said though and prototyping for me is for readability and organization, I don't see prototyping being much of a performance hit, JS is made to use prototyping.

2 hours ago, Igor Georgiev said:

For all future readers. I used to get 30 fps on an iPhone 4s. Fixed it by checking the device first, put the renderer on WebGL, remove the advanced timing and fps count and BINGO - 60fps:)

You're right, any sort of debug info takes a ton of performance from the device, including some desktop browsers. It's different for every device which is why it's wise to constantly test on your target device and make sure things run smooth. For me I get a lot of issues with the desktop version of firefox, like brutally slow with both WebGL and canvas but pop it into chrome and it runs perfectly, with a steady FPS of 60.

Link to comment
Share on other sites

1 hour ago, LTNGames said:

I'm not suggesting anything, I was actually elaborating on the OP saying to not use prototypes, I use prototyping for everything and was pretty much just saying why, I agree with everything you said though and prototyping for me is for readability and organization, I don't see prototyping being much of a performance hit, JS is made to use prototyping.

You're right, any sort of debug info takes a ton of performance from the device, including some desktop browsers. It's different for every device which is why it's wise to constantly test on your target device and make sure things run smooth. For me I get a lot of issues with the desktop version of firefox, like brutally slow with both WebGL and canvas but pop it into chrome and it runs perfectly, with a steady FPS of 60.

Same here, for some reason FireFox Desktop is slow with me as well... 
Another question: do you know if forceSingleUpdate is better performance wise or not? I mean, as I understand, it wont be active if the fps is steady 60, but it seems like it will do the update no matter the clock. 

Link to comment
Share on other sites

  • 4 months later...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...