Delay in IPC message processing

297 views
Skip to first unread message

Phani Vadrevu

unread,
Jan 28, 2016, 7:07:44 PM1/28/16
to Chromium-dev
I've been trying to send a custom IPC message (which I defined in content/common/input_messages.h) from the browser process to the renderer. I need to send this message periodically. Many times this message reaches the renderer within 1 ms. But some other times (I think when there is network activity going on in the background) it can take as much as 3000ms. I am trying to figure out a  way to somehow prioritize the handling of this custom IPC message and avoid such a long delay.

I plumbed my way through the IPC code and noticed that there is no delay in sending the message. On the renderer's side, I am stuck at the ChannelReader::DispatchMessage() function. I can't figure to which object listener_ variable refers to in that code (src/ipc/ipc_channel_reader.cc). Until that point everything happens fairly quickly (with in 1 ms). But after that, the processing task some how ends up on a MessageLoop and is run at a later time (sometimes after 3000ms) by MessagePumpDefault::Run and DoDelayedWork. 

If some one can tell me how to figure out what happens after ChannelReader::DispatchMessage() or a way to reduce this delay, that would be great!

Thanks,
Phani

Alex Clarke

unread,
Jan 29, 2016, 3:57:44 AM1/29/16
to pvad...@gmail.com, Chromium-dev
What does the system you're building do?

Most of the time, tasks posted to renderer task queues are executed very promptly (see http://go/chromium_task_queueing_duration if you have UMA access).  However the task system can get congested (typically during page load) if there are slow tasks (many ad scripts can take up to 1000ms to run) or there is simply a great quantity of tasks to process.

If your task is critical for the user experience it might be possible to do something to expedite it's processing, a bit like what the MainThreadInputEventFilter does.  We need to be careful about how widely techniques like that are used, because if everything is high priority then nothing is :)

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.

Phani Vadrevu

unread,
Feb 8, 2016, 6:52:24 PM2/8/16
to Chromium-dev, pvad...@gmail.com
Thanks for the reply. 

What does the system you're building do?

I am trying to make some browser modifications to enable forensic analysis for security purposes. A part of this is taking the snapshot of the DOM while the input event is queued up in the browser. Specifically, for this, I am passing a "FrameMsg_SerializeAsMHTML" IPC message (from browser to the renderer) and hoping to get it handled as quickly as possible.  

When there is no loading activity going on this task seems to be executed pretty quickly. But when there is loading activity, I saw that this task can get delayed by as much as 1 or 2 seconds.

If your task is critical for the user experience it might be possible to do something to expedite it's processing, a bit like what the MainThreadInputEventFilter does.  We need to be careful about how widely techniques like that are used, because if everything is high priority then nothing is :)

Thanks for this pointer. I am able to intercept the IPC message using InputEventFilter. But the handling of that IPC Message involves execution of the  RenderFrameImpl::OnSerializeAsMHTML function which can only be run on main thread. So, I cannot post a task to do this using the compositor task runner like the InputEventFilter does. 

Can you please mention what task runners (other than the main_task_runner) are dedicated to the Main thread. Is there a task runner whose priority is more than the priority than the task runner for the loading tasks? This will enable us to get the "OnSerializeAsMHTML" function executed before the loading tasks / network requests. 

Also, which is the task runner that currently runs the loading tasks / network requests (I am confused between NewLoadingTaskRunner or the LoadingTaskRunner)

Thanks,
Phani

Alex Clarke

unread,
Feb 9, 2016, 7:19:16 AM2/9/16
to Phani Vadrevu, Chromium-dev
On Mon, Feb 8, 2016 at 11:52 PM, Phani Vadrevu <pvad...@gmail.com> wrote:
Thanks for the reply. 

What does the system you're building do?

I am trying to make some browser modifications to enable forensic analysis for security purposes. A part of this is taking the snapshot of the DOM while the input event is queued up in the browser. Specifically, for this, I am passing a "FrameMsg_SerializeAsMHTML" IPC message (from browser to the renderer) and hoping to get it handled as quickly as possible.  

When there is no loading activity going on this task seems to be executed pretty quickly. But when there is loading activity, I saw that this task can get delayed by as much as 1 or 2 seconds.

Even if you ran tasks at the highest possible priority, you're still going to get delays of up to 1s because the main thread is cooperatively multi tasked and quite a lot of ad and analytics scripts take (imo) an unreasonable length of time to execute.

That said here's how to wire something like this up:
  1. Take a look at RendererSchedulerImpl::NewTimerTaskRunner  and copy it to RendererSchedulerImpl::MyHighPriorityTaskRunner  
  2. Remove  timer_task_runners_.insert(timer_task_queue);  from MyHighPriorityTaskRunner
  3. Add my_task_queue->SetQueuePriority(TaskQueue::HIGH_PRIORITY);
  4. Route this TaskQueue through to wherever you need it.
You'll need to be careful with such a queue since it'll be quite easy to stave out other work (there is some anti starvation prevention in the TaskQueueSelector but even so you still need to be careful).


If your task is critical for the user experience it might be possible to do something to expedite it's processing, a bit like what the MainThreadInputEventFilter does.  We need to be careful about how widely techniques like that are used, because if everything is high priority then nothing is :)

Thanks for this pointer. I am able to intercept the IPC message using InputEventFilter. But the handling of that IPC Message involves execution of the  RenderFrameImpl::OnSerializeAsMHTML function which can only be run on main thread.

RenderFrameImpl::OnSerializeAsMHTML
 sounds somewhat expensive, this may noticeably reduce the responsiveness of the browser to user input in the presence of a TouchHandler (very common).

 
So, I cannot post a task to do this using the compositor task runner like the InputEventFilter does.

That actually depends which compositor task runner you're referring to.  The RendererScheduler::CompositorTaskRunner is for running compositor tasks on the main thread (as an aside we should probably rename it to make this more obvious).
 

Can you please mention what task runners (other than the main_task_runner) are dedicated to the Main thread. Is there a task runner whose priority is more than the priority than the task runner for the loading tasks? This will enable us to get the "OnSerializeAsMHTML" function executed before the loading tasks / network requests. 

I wonder if your current approach is the best way. There's an ongoing project to build a headless chrome. I'm not quite sure how your forensic analysis will be used but that might be more suitable since you'll be able do do things like: 
  • Suspend and resume the world programatically (i.e. suspend all dom timers and loading tasks)
  • Hook network requests (so you know when they're pending, when they're available or even control the order in which they return) 
  • Serialize the DOM and eventually layout tree
  • Send input programatically 
There isn't much code landed right now but hopefully Q2 there will be.

Also, which is the task runner that currently runs the loading tasks / network requests (I am confused between NewLoadingTaskRunner or the LoadingTaskRunner)

The former is a loading task queue associated with a specific Frame the latter is a default loading task queue for things like detatched documents and other stuff where there isn't a Frame.  Eventually we hope to get rid of the the renderer wide default task runners, they'll likely end up being moved to the WebView.

Roberto Perdisci

unread,
Feb 16, 2016, 6:45:57 AM2/16/16
to Chromium-dev, pvad...@gmail.com

Alex, thanks for all this great information. 

You mentioned an ongoing project to build a headless chrome. Is there any public document that outlines the approach and steps that will be taken to get this done? (similar to the docs you guys wrote related to the Blink/Renderer scheduler architecture: https://goo.gl/Rhv3yB).

Thanks!


Roberto

Sami Kyostila

unread,
Feb 16, 2016, 9:03:31 AM2/16/16
to roberto....@gmail.com, Chromium-dev, pvad...@gmail.com
ti 16. helmikuuta 2016 klo 11.46 Roberto Perdisci <roberto....@gmail.com> kirjoitti:

Alex, thanks for all this great information. 

You mentioned an ongoing project to build a headless chrome. Is there any public document that outlines the approach and steps that will be taken to get this done? (similar to the docs you guys wrote related to the Blink/Renderer scheduler architecture: https://goo.gl/Rhv3yB).

You can follow crbug.com/546953 for updates about Headless Chrome. 
 
- Sami
Reply all
Reply to author
Forward
0 new messages