I was fiddling with Parse server with MongoDB to understand its performance characteristics.
I created a collection of 87000 items, all readable only with the master key.
I used Postman to execute empty queries on the collection, without the master key or a session token. Of course, the query returns an empty result. What I am interested in is how long it takes to notice that an anonymous user is not allowed to read any of the objects.
Using a commit more recent than the latest release as of today, 4.5.0, the query takes about 47ms.
So I tried creating a MongoDB index on the _rperm field, which is what the Parse server filters on to enforce ACLs:
db.tmp.createIndex({_rperm: 1})
And the execution time jumps to 120ms, again, measured by Postman.
So that’s quite strange. Adding an index makes the query substantially slower, even with such a sizable collection.
I ran some queries on the Mongo shell directly. I filtered on the _rperm field, similar to what the Parse server does. And the query ran in less than a millisecond, as measure by the Mongo shell. That’s also perplexing. Digging into the Parse source, I see this line that adds ACL restrictions to user queries, in DatabaseController.js:
newQuery._rperm = { $in: [null, ‘*’, …acl] };
Adding the null to the query I ran using the Mongo shell, the execution time indeed jumps to ~100ms. Mind you, it was less than a ms without the null.
I am not sure what is causing that. I read the Mongo documentation on $in and couldn’t find a special meaning to null that would cause such behavior. As expected, removing the null from the Parse source makes the query significantly faster (~8ms), but it also breaks it as a non-existent _rperm field denotes public read access.
I have made all the necessary modifications to avoid using null in $in, and the code is at https://github.com/Ocell-io/parse-server/tree/query_acl_index_perf. It works and passes all tests (using Mongo, that is), however has a ~45% overhead in the non-indexed case.
Overall, this is how long the query takes, measured by Postman:
upstream, no index : 47ms
upstream, _rperm index: 120ms
patch, no index : 69ms
patch, _rperm index : 8ms
I initially considered creating a pull request, but given that it only seems to work with Mongo (likely because it uses $and) and has a relatively large overhead for non-indexed collections, I am hesitant.
Any ideas?