Commit 08521b98 by Toby Lawrence

Preload the comment_thread relation before serializing comments.

When a single thread is presented/serialized, it loads all of the
comments for that thread, or whatever ones fall in the pagination range,
and serializes them by calling #to_hash before shoving them into an
array.

When calling #to_hash on a comment, the comment has to look at its
parent thread to get some information, which requires loading that
comment thread lazily and creating the Ruby object for it, etc.

This is an experiment is trying to use Criteria#includes to preload it
instead of letting it be lazily loaded, to see if it can do more of the
work upfront leading to less work needing to happen when lazily loaded.

The database isn't being queried every time right now, but I have an
assumption that it's simply creating new comment thread objects based on
the cached MongoDB results, and that preloading might actually only
create those objects once (because they all share the same parent) and
then assign it to every comment, effectively making it a one-time thing
vs an N-time thing.  This might be totally off: I still need to profile
this to see what's going on precisely.  All I know is that serializing a
single comment can take 10s of milliseconds, which is really slow for
what ought to be simply taking a Mongoid document and making it a hash.
parent 7cc9a131
......@@ -33,9 +33,13 @@ class ThreadPresenter
if with_responses
if @thread.thread_type.discussion? && resp_skip == 0 && resp_limit.nil?
if recursive
content = Comment.where(comment_thread_id: @thread._id).order_by({"sk" => 1})
content = Comment.includes(:comment_thread)
.where(comment_thread_id: @thread._id)
.sort({"sk" => 1})
else
content = Comment.where(comment_thread_id: @thread._id, "parent_ids" => []).order_by({"sk" => 1})
content = Comment.includes(:comment_thread)
.where(comment_thread_id: @thread._id, "parent_ids" => [])
.sort({"sk" => 1})
end
h["children"] = merge_response_content(content)
h["resp_total"] = content.to_a.select{|d| d.depth == 0 }.length
......@@ -77,15 +81,18 @@ class ThreadPresenter
# response_count
# The total number of responses
def get_paged_merged_responses(thread_id, responses, skip, limit, recursive=false)
response_ids = responses.only(:_id).sort({"sk" => 1}).to_a.map{|doc| doc["_id"]}
response_ids = responses.sort({"sk" => 1}).pluck(:_id)
paged_response_ids = limit.nil? ? response_ids.drop(skip) : response_ids.drop(skip).take(limit)
if recursive
content = Comment.where(comment_thread_id: thread_id).
or({:parent_id => {"$in" => paged_response_ids}}, {:id => {"$in" => paged_response_ids}}).
sort({"sk" => 1})
content = Comment.includes(:comment_thread)
.where(comment_thread_id: thread_id)
.or({:parent_id => {"$in" => paged_response_ids}}, {:id => {"$in" => paged_response_ids}})
.sort({"sk" => 1})
else
content = Comment.where(comment_thread_id: thread_id, "parent_ids" => []).
where({:id => {"$in" => paged_response_ids}}).sort({"sk" => 1})
content = Comment.includes(:comment_thread)
.where(comment_thread_id: thread_id, "parent_ids" => [])
.where({:id => {"$in" => paged_response_ids}})
.sort({"sk" => 1})
end
{"responses" => merge_response_content(content), "response_count" => response_ids.length}
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment