openfl / openfl-html5

[deprecated] OpenFL HTML5 backend
Other
0 stars 1 forks source link

Painful performance regression #21

Closed jgranick closed 10 years ago

jgranick commented 10 years ago

21 Issue by fserb,

So,

there's a performance regression caused by 7a530673ab005b5ed2be0450a51ebe5ebe25a597. I have a code that looks like:

    var m = base_sprite.transform.matrix;
    m.identity();
    m.translate(-sprite.width/2.0, -sprite.height/2.0);
    m.rotate(angle);
    m.translate(pos.x + deltasprite.x, pos.y + deltasprite.y);
    m.translate(sprite.width/2.0, 0);
    base_sprite.transform.matrix = m;

Before this commit, the code ran on average in 9µs. After this commit it goes to around 100µs.

I found the commit with git bisect and double checked that it's the offending one. I'm not 100% on the actual reason. My guess is because every change I make to transform makes __worldDirty true, which triggers a global stage update on any of the getters that request bounds. If I put a trace on Sprite.__getBounds(), __worldDirty swaps constantly between true/false.

But maybe I'm wrong here.

Help?

jgranick commented 10 years ago

Comment by jgranick:

In the previous version, it only updated the "world transform" for objects once before rendering. In general, this was alright, but if you called globalToLocal, or checked bounds and other operations which relied upon current transform data, it would fail. The "__worldTransformDirty" flag is a step in the direction of updating when needed.

I would say that using new Matrix () instead of reading base_sprite.transform.matrix would be much faster (or caching your own Matrix object) as the "transform.matrix" property generates a new Matrix, anyway, but requires the transforms to be updated. On the other hand, checking the sprite width or height will require an update ATM.

I'm thinking that perhaps I should do something where if the world has been dirtied, it will update the transform only for the current object (up through to the stage) and wait for a full update on the next render, or some "smarter" dirty system, I want to try and avoid looping up through every parent to flag as dirty if I can help it. Open to ideas.

I wish there was a data structure that would allow an object to flag itself as dirty, and somehow quickly determine if something "under" the object or "over" the object has been adjusted... I can't think of one, perhaps if each object had a unique ID, and also maintained a table of "related IDs", but that could get messy.

So the recent commits are focused on correctness, but the performance has to be tightened up again, I welcome input :)

jgranick commented 10 years ago

Comment by jgranick:

Thank you again for bringing this up,

I understand your feelings about wanting to submit patches instead of bug reports, I appreciate it! In this case, however, it's a matter of core architecture that needed to be improved.

I've just submitted an update that should improve the "dirty transform" system in the engine, I'm going to do more tests for correctness, but initially I'm already seeing good performance gains, and I think (conceptually) what you're doing above should be much, much lighter if you have a large display list

Please let me know how it works for you :)

jgranick commented 10 years ago

Comment by fserb:

Yay! It's working great and I'm seeing tiny update times again.

I think I understand a bit better now what the dirty transform system is trying to do, but probably not enough to say something useful about it. :P

I will start sending the remaining patches now. :) (there's a couple bugs with line drawing that I fixed while making the LD game).

Thanks so much for doing this. You are amazing! :)