Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signal - memory optimization / reductions #1359

Merged
merged 2 commits into from Nov 24, 2014

Conversation

pnstickne
Copy link
Contributor

There are a fair amount of Signal objects created. In the current
implementation these are somewhat "fat" objects for two reasons:

  • A closure / ad-hoc dispatch is created for each new Signal - this
    increases the retained size by 138+ bytes/Signal in Chrome.
  • There are a number of instance variables that never change from their
    default value, and the bindings array is always created, even if never
    used.

This change "lightens" the Signals such that there is significantly less
penalty for having many (unusued) signals.

As an example of how much this does play a role, in the "Random Sprite"
demo ~2000 Signals are created, with only 12 of these signals being
subscribed to. This results in a shallow size of ~300K and a retained size
of ~600K (which is almost as much memory as required by the
Sprites/Sprites themselves!) for .. nothing.

With these changes the shallow and retained sizes are less than 50K each -
and this is with only ~200 sprites!

This change addresses these issues by

  • Changing it so there is no dispatch closure created. This is a
    breaking change (although there is no usage of such in core where it
    breaks); the code referenced "No destroy method on State class #24", but no such [relevant?] issue could be found on
    github.

    In the rare case that code needs to obtain a dispatch-closure, the
    boundDispatch property can be used to trivially obtain a (cached)
    closure.

  • The properties and default values are moved into the prototype; and the
    _bindings array creation is deferred. This change, coupled with the
    removal of the automatic closure, results in a very lightweight
    ~24bytes/object (in Chrome) for unbound signals.

This is minor breaking change, as per the removal of the automatic
closure; but no such need/usage was found in the core. (There may be cases
in the examples, which were not checked.)

If merely opting for the array creation delay and keeping the default
properties in the prototype the shallow size is still halved; less
significant but still a consideration.

Optimizing object creation, mainly of the backing array in situations when
there is no backing array.
There are a fair amount of Signal objects created. In the current
implementation these are somewhat "fat" objects for two reasons:

- A closure / ad-hoc `dispatch` is created for each new Signal - this
  increases the retained size by 138+ bytes/Signal in Chrome.

- There are a number of instance variables that never change from their
  default value, and the bindings array is always created, even if never
  used.

This change "lightens" the Signals such that there is significantly less
penalty for having many (unusued) signals.

As an example of how much this _does_ play a role, in the "Random Sprite"
demo ~2000 Signals are created, with only 12 of these signals being
subscribed to. This results in a shallow size of ~300K and a retained size
of ~600K (which is almost as much memory as required by the
Sprites/Sprites themselves!) for .. nothing.

With these changes the shallow and retained sizes are less than 50K each -
and this is with only ~200 sprites!

This change addresses these issues by

- Changing it so there is _no_ `dispatch` closure created. This is a
  _breaking change_ (although there is no usage of such in core where it
  breaks); the code referenced "phaserjs#24", but no such issue could be found on
  github.

  In the rare case that code needs to obtain a dispatch-closure, the
  `boundDispatch` property can be used to trivially obtain a (cached)
  closure.

- The properties and default values are moved into the prototype; and the
  `_bindings` array creation is deferred. This change, coupled with the
  removal of the automatic closure, results in a very lightweight
  ~24bytes/object (in Chrome) for unbound signals.

This is minor breaking change, as per the removal of the automatic
closure; but no such need/usage was found in the core. (There may be cases
in the examples, which were not checked.)

If merely opting for the array creation delay and keeping the default
properties in the prototype the shallow size is still halved; less
significant but still a consideration.
@pnstickne
Copy link
Contributor Author

Whoops, the code-referenced issue was 47 (#47) and not 24, but it still doesn't seem related.

photonstorm added a commit that referenced this pull request Nov 24, 2014
Signal - memory optimization / reductions
@photonstorm photonstorm merged commit 386c6df into phaserjs:dev Nov 24, 2014
@clark-stevenson
Copy link
Contributor

👍 I use these things everywhere!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants