This is just FYI, so others don’t make the same mistake.
We use this or similar all over in our code:
var user = Meteor.user();
confirmUser(user);
Or
var user = Meteor.user();
if (!user) return;
Sometimes we actually care about the fields of the user, sometimes we don’t. Many times we end up calling Meteor.user() multiple times in a single call stack. (never more than 1 per frame)
When looking at Kadira/APM perf logs we learned that these calls are not only not free… but often times quite expensive. The .fetch() is anywhere from a few ms to 100’s of ms.
The suggestion is to use Meteor.userId() instead… and to pass the user doc if that makes sense.
This is a really “extreme” sample:
find on users 0ms
coll : users
func : find
selector : “RvxLpCgrjXsLhzGS2" fetch on users 423ms
coll : users
selector : {”_id":“RvxLpCgrjXsLhzGS2”}
func : fetch
cursor : true
limit : 1
docsFetched : 1
docSize : 1193
find on decks 0ms
fetch on decks 608ms
find on cards 0ms
count on cards 204ms
find on users 0ms fetch on users 1184ms
coll : users
selector : {"_id":“RvxLpCgrjXsLhzGS2”}
func : fetch
cursor : true
limit : 1
docsFetched : 1
docSize : 1193
find on deckLogs 0ms SHOW MORE
fetch on deckLogs 14ms SHOW MORE
find on users 0ms
coll : users
func : find
selector : “RvxLpCgrjXsLhzGS2" fetch on users 57ms
coll : users
selector : {”_id":“RvxLpCgrjXsLhzGS2”}
func : fetch
cursor : true
limit : 1
docsFetched : 1
docSize : 1193
@oemig I got burnt pretty badly by this behaviour - for a long while I thought Meteor.user() was doing something smart, eg caching the user for subsequent calls, until profiling proved otherwise.
From looking at the code, it’s just a thin wrapper around Meteor.users.findOne(this.userId) without any field filtering going on - ie almost never the right tool for the job in production environments. It would have really helped to see this indicated in the docs somewhere.
Hmm, even though I don’t use Meteor.user() “accidentally”, I still need to retrieve the user document on every method call to check permissions, so it’d definitely be good to have a caching solution for it.
I don’t know what so terrible about my suggestion, if it really was the case that Meteor.user() was slow on the client. Of course it’s pointless now that I realized he was talking about serverside, and yeah Meteor.user() doesn’t have much of a cost on the client since Minimongo is fast.
It’s the easiest to understand for an example. Would you have been happier if I used a ReactiveVar or ReactiveDict instead? You know Session is just a ReactiveDict right?