late night optimizations

-isMemberOfSets returns true/false instead of 1/0
-when loading the posts of a topic only get the userdata for each user
once, before this commit if a topic had 10 posts from 2 different users
we were getting the user data for each user 5 times (drunk)
-getVoteStatusByPostIDs and getFavouritesByPostIDs no longer make
pids.length calls to the db, they use isMemberOfSets now
-getUserInfoForPost renamed to getUserInfoForPosts and doesnt make
uids.length calls to db, uses getMultipleUserFields instead
v1.18.x
barisusakli 11 years ago
parent d3fc71529a
commit c3a9767bf6

@ -78,7 +78,7 @@ module.exports = function(db, module) {
}); });
result = sets.map(function(set) { result = sets.map(function(set) {
return result.indexOf(set) !== -1 ? 1 : 0; return result.indexOf(set) !== -1;
}); });
callback(null, result); callback(null, result);

@ -40,11 +40,20 @@ module.exports = function(redisClient, module) {
module.isMemberOfSets = function(sets, value, callback) { module.isMemberOfSets = function(sets, value, callback) {
var multi = redisClient.multi(); var multi = redisClient.multi();
for (var i = 0, ii = sets.length; i < ii; i++) { for (var i = 0; i < sets.length; ++i) {
multi.sismember(sets[i], value); multi.sismember(sets[i], value);
} }
multi.exec(callback); multi.exec(function(err, results) {
if (err) {
return callback(err);
}
for (var i=0; i<results.length; ++i) {
results[i] = results[i] === 1;
}
callback(null, results);
});
}; };
module.getSetMembers = function(key, callback) { module.getSetMembers = function(key, callback) {

@ -155,8 +155,21 @@ var async = require('async'),
}; };
Favourites.getVoteStatusByPostIDs = function(pids, uid, callback) { Favourites.getVoteStatusByPostIDs = function(pids, uid, callback) {
async.map(pids, function(pid, next) { var upvoteSets = [],
Favourites.hasVoted(pid, uid, next); downvoteSets = [];
for (var i=0; i<pids.length; ++i) {
upvoteSets.push('pid:' + pids[i] + ':upvote');
downvoteSets.push('pid:' + pids[i] + ':downvote');
}
async.parallel({
upvotes: function(next) {
db.isMemberOfSets(upvoteSets, uid, next);
},
downvotes: function(next) {
db.isMemberOfSets(downvoteSets, uid, next);
}
}, callback); }, callback);
}; };
@ -225,9 +238,12 @@ var async = require('async'),
}; };
Favourites.getFavouritesByPostIDs = function(pids, uid, callback) { Favourites.getFavouritesByPostIDs = function(pids, uid, callback) {
async.map(pids, function(pid, next) { var sets = [];
Favourites.hasFavourited(pid, uid, next); for (var i=0; i<pids.length; ++i) {
}, callback); sets.push('pid:' + pids[i] + ':users_favourited');
}
db.isMemberOfSets(sets, uid, callback);
}; };
Favourites.getFavouritedUidsByPids = function(pids, callback) { Favourites.getFavouritedUidsByPids = function(pids, callback) {

@ -350,7 +350,7 @@
db.isMemberOfSets(groupSets, uid, function(err, isMembers) { db.isMemberOfSets(groupSets, uid, function(err, isMembers) {
for(var i=isMembers.length - 1; i>=0; --i) { for(var i=isMembers.length - 1; i>=0; --i) {
if (parseInt(isMembers[i], 10) !== 1) { if (!isMembers[i]) {
groupData.splice(i, 1); groupData.splice(i, 1);
} }
} }

@ -188,13 +188,15 @@ var async = require('async'),
}); });
}; };
Posts.getUserInfoForPost = function(post, callback) { Posts.getUserInfoForPosts = function(uids, callback) {
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) { user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
async.map(userData, function(userData, next) {
var userInfo = { var userInfo = {
uid: userData.uid,
username: userData.username || '[[global:guest]]', username: userData.username || '[[global:guest]]',
userslug: userData.userslug || '', userslug: userData.userslug || '',
reputation: userData.reputation || 0, reputation: userData.reputation || 0,
@ -211,20 +213,21 @@ var async = require('async'),
postTools.parseSignature(userData.signature, next); postTools.parseSignature(userData.signature, next);
}, },
customProfileInfo: function(next) { customProfileInfo: function(next) {
plugins.fireHook('filter:posts.custom_profile_info', {profile: [], uid: post.uid, pid: post.pid}, next); plugins.fireHook('filter:posts.custom_profile_info', {profile: [], uid: userData.uid}, next);
}, },
groups: function(next) { groups: function(next) {
groups.getUserGroups(post.uid, next); groups.getUserGroups(userData.uid, next);
} }
}, function(err, results) { }, function(err, results) {
if (err) { if (err) {
return callback(err); return next(err);
} }
userInfo.signature = results.signature; userInfo.signature = results.signature;
userInfo.custom_profile_info = results.custom_profile_info; userInfo.custom_profile_info = results.custom_profile_info;
userInfo.groups = results.groups; userInfo.groups = results.groups;
callback(null, userInfo); next(null, userInfo);
}); });
}, callback);
}); });
}; };

@ -270,6 +270,9 @@ var async = require('async'),
} }
async.parallel({ async.parallel({
mainPost: function(next) {
Topics.getMainPost(tid, uid, next);
},
posts: function(next) { posts: function(next) {
Topics.getTopicPosts(tid, set, start, end, uid, reverse, next); Topics.getTopicPosts(tid, set, start, end, uid, reverse, next);
}, },
@ -284,26 +287,6 @@ var async = require('async'),
}, },
tags: function(next) { tags: function(next) {
Topics.getTopicTagsObjects(tid, next); Topics.getTopicTagsObjects(tid, next);
},
mainPost: function(next) {
Topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (err) {
return next(err);
}
if (!parseInt(mainPid, 10)) {
return next(null, []);
}
posts.getPostsByPids([mainPid], function(err, postData) {
if (err) {
return next(err);
}
if (!Array.isArray(postData) || !postData[0]) {
return next(null, []);
}
postData[0].index = 0;
Topics.addPostData(postData, uid, next);
});
});
} }
}, function(err, results) { }, function(err, results) {
if (err) { if (err) {
@ -325,6 +308,27 @@ var async = require('async'),
}); });
}; };
Topics.getMainPost = function(tid, uid, callback) {
Topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (err) {
return callback(err);
}
if (!parseInt(mainPid, 10)) {
return callback(null, []);
}
posts.getPostsByPids([mainPid], function(err, postData) {
if (err) {
return callback(err);
}
if (!Array.isArray(postData) || !postData[0]) {
return callback(null, []);
}
postData[0].index = 0;
Topics.addPostData(postData, uid, callback);
});
});
};
Topics.getTeasers = function(tids, callback) { Topics.getTeasers = function(tids, callback) {
if(!Array.isArray(tids)) { if(!Array.isArray(tids)) {

@ -224,10 +224,10 @@ module.exports = function(Topics) {
}, },
function(result, next) { function(result, next) {
Topics.pushUnreadCount(); Topics.pushUnreadCount();
posts.getUserInfoForPost(postData, next); posts.getUserInfoForPosts([postData.uid], next);
}, },
function(userInfo, next) { function(userInfo, next) {
postData.user = userInfo; postData.user = userInfo[0];
Topics.getTopicFields(tid, ['tid', 'title', 'slug'], next); Topics.getTopicFields(tid, ['tid', 'title', 'slug'], next);
}, },
function(topicData, next) { function(topicData, next) {

@ -42,6 +42,7 @@ module.exports = function(Topics) {
}; };
Topics.addPostData = function(postData, uid, callback) { Topics.addPostData = function(postData, uid, callback) {
var st = process.hrtime();
var pids = postData.map(function(post) { var pids = postData.map(function(post) {
return post.pid; return post.pid;
}); });
@ -54,27 +55,43 @@ module.exports = function(Topics) {
favourites.getVoteStatusByPostIDs(pids, uid, next); favourites.getVoteStatusByPostIDs(pids, uid, next);
}, },
userData: function(next) { userData: function(next) {
async.each(postData, function(post, next) { var uids = [];
async.parallel({ for(var i=0; i<postData.length; ++i) {
editor: function(next) { if (uids.indexOf(postData[i].uid) === -1) {
if (!post.editor) { uids.push(postData[i].uid);
return next();
} }
user.getUserFields(post.editor, ['username', 'userslug'], next);
},
user: function(next) {
posts.getUserInfoForPost(post, next);
} }
}, function(err, results) {
posts.getUserInfoForPosts(uids, function(err, users) {
if (err) { if (err) {
return next(err); return next(err);
} }
post.user = results.user; var userData = {};
post.editor = results.editor; users.forEach(function(user) {
next(); userData[user.uid] = user;
});
next(null, userData);
});
},
editors: function(next) {
var editors = [];
for(var i=0; i<postData.length; ++i) {
if (postData[i].editor && editors.indexOf(postData[i].editor) === -1) {
editors.push(postData[i].editor);
}
}
user.getMultipleUserFields(editors, ['uid', 'username', 'userslug'], function(err, editors) {
if (err) {
return next(err);
}
var editorData = {};
editors.forEach(function(editor) {
editorData[editor.uid] = editor;
})
next(null, editorData);
}); });
}, next);
}, },
privileges: function(next) { privileges: function(next) {
async.map(pids, function (pid, next) { async.map(pids, function (pid, next) {
@ -88,9 +105,11 @@ module.exports = function(Topics) {
for (var i = 0; i < postData.length; ++i) { for (var i = 0; i < postData.length; ++i) {
postData[i].deleted = parseInt(postData[i].deleted, 10) === 1; postData[i].deleted = parseInt(postData[i].deleted, 10) === 1;
postData[i].user = results.userData[postData[i].uid];
postData[i].editor = postData[i].editor ? results.editors[postData[i].editor] : null;
postData[i].favourited = results.favourites[i]; postData[i].favourited = results.favourites[i];
postData[i].upvoted = results.voteData[i].upvoted; postData[i].upvoted = results.voteData.upvotes[i];
postData[i].downvoted = results.voteData[i].downvoted; postData[i].downvoted = results.voteData.downvotes[i];
postData[i].votes = postData[i].votes || 0; postData[i].votes = postData[i].votes || 0;
postData[i].display_moderator_tools = results.privileges[i].editable; postData[i].display_moderator_tools = results.privileges[i].editable;
postData[i].display_move_tools = results.privileges[i].move && postData[i].index !== 0; postData[i].display_move_tools = results.privileges[i].move && postData[i].index !== 0;
@ -100,7 +119,7 @@ module.exports = function(Topics) {
postData[i].content = '[[topic:post_is_deleted]]'; postData[i].content = '[[topic:post_is_deleted]]';
} }
} }
process.profile('derp', st);
callback(null, postData); callback(null, postData);
}); });
}; };

@ -45,7 +45,7 @@ module.exports = function(Topics) {
return callback(err); return callback(err);
} }
var newtids = tids.filter(function(tid, index, self) { var newtids = tids.filter(function(tid, index, self) {
return parseInt(read[index], 10) === 0; return !read[index];
}); });
async.filter(newtids, function(tid, next) { async.filter(newtids, function(tid, next) {

Loading…
Cancel
Save