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

Cache #4

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Cache #4

wants to merge 6 commits into from

Conversation

MioQuispe
Copy link
Contributor

This caches entities by their mask

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 84e2166 on MioQuispe:cache into 1cbe5bc on makrjs:master.

@@ -37,6 +40,8 @@ EntityManager.prototype.create = function() {
var entity = this._entityInst[id]
this._entityFlag[id] = ENTITY_ALIVE

entity._cacheIndex = this._entityCache[0].push(entity) - 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not add anything to the entity.
Instead create an Int32Array to store indexes like _entityMask.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

@MioQuispe
Copy link
Contributor Author

Fyi, I tried preallocating an array based on the amount of entities the query will return. The speedup was roughly 2-3x for 100k entities 50k returned

@ooflorent
Copy link
Member

Can you rebase on master?
I've fixed a bug on Entity#destroy

@MioQuispe
Copy link
Contributor Author

Sure thing.

@@ -22,6 +22,9 @@ function EntityManager(components, storage) {

this._entityPool = []
this._entityCounter = 0

this._entityCache = {}
this._entityCache[0] = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be optimized:

this._entityCache = FastMap()
this._entityCache[0] = []

See https://gist.github.com/ooflorent/c58c9a0f08923973a5e3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do you suggest I add fast.js to the project and require it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Next to utils.js.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting:

/home/user/Projects/mq_makr/makr/lib/fast.js:10
  ForceEfficientMap.prototype = self
  ^^^^^^^^^^^^^^^^^
SyntaxError: Unexpected identifier

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on the gist.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, wow didn't notice the missing brackets

@ooflorent
Copy link
Member

Well let's finish the PR, add some tests to ensure there a no duplicates and we should be good

@MioQuispe
Copy link
Contributor Author

I've added several tests which seem to confirm it's working correctly. But I have something I want to still add to it which would effectively get around the .push() problem. I predict this will have a very big impact on the performance.

@MioQuispe
Copy link
Contributor Author

Initial numbers (All tests pass, including the new ones):

                  EntityManager
  57,264,548 op/s » query on 1000 entities with 1 component (500 matches)
  35,554,763 op/s » query on 1000 entities with 3 components (84 matches)
  10,677,708 op/s » query on 1000 entities with 10 components (1 match)

                  EntityManager
  59,946,961 op/s » query on 10000 entities with 1 component (~5000 matches)
  32,865,792 op/s » query on 10000 entities with 3 components (~840 matches)
   8,758,721 op/s » query on 10000 entities with 10 components (~4 matches)

                  EntityManager
  58,063,592 op/s » query on 100000 entities with 1 component (~50000 matches)
  32,834,461 op/s » query on 100000 entities with 3 components (~8400 matches)
   8,797,725 op/s » query on 100000 entities with 10 components (~40 matches)

As you see, it will be independent of the amount of entities.
So what's going on? The query results are cached.
Whenever an entity is created/destroyed/has a component added/removed
the respective query result caches are set as invalid and get rebuilt the next time query is called with their mask. So no, these numbers aren't 100% realistic as each affected query cache will have to be rebuilt whenever an entity is modified. The good thing is (apart from the crazy speeds when the query cache is used) this should mean much less work for the garbage collector and we aren't really using any extra memory since these arrays would be created anyway each time a query is performed. Unfortunately this adds quite a bit of overhead for modifying entities:

Before:
168,066,626 op/s » #destroy
81,404,501 op/s » #add
84,897,373 op/s » #remove
1,533,740 op/s » #create

After:
34,618,246 op/s » #destroy
2,773,040 op/s » #add
3,422,823 op/s » #remove
880,812 op/s » #create

This is something I'd like to fix by scheduling the cache invalidations for the next query somehow. I'd like to see the numbers back to the old ones ;). Let me know what you think. All the other numbers stayed the same btw.

@eranimo
Copy link

eranimo commented Jul 15, 2017

Can this be merged?

@ooflorent
Copy link
Member

@eranimo I don't think so. I'm not fully satisfied by this change. While the performance improvement is huge for query, there is a significant overhead for entity manipulation methods.

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.

4 participants