Description[tracing] Simplify and improve thread-hopping logic of memory-infra
By contract MemoryDumpManager invokes the MemoryDumpProvider's
OnMemoryDump() method on the thread specified (by the MDP) in the
RegisterDumpProvider() call.
At the same time, it guarantees that at most one MDP is enabled at any
time. This is to avoid to have the MDPs dealing with thread-safety.
Assuming to have the following situation:
MDP_1 @ Thread_A, MDP_2 @ Thread_B, MDP_3 @ Thread_A, MDP_4 @ Thread_B
The way ProcessMemoryDump would have acted before this change is:
CreateProcessDump():
PostTask(Thread_A, ContinueAsyncProcessDump(MDP_1))
PostTask(Thread_B, ContinueAsyncProcessDump(MDP_2))
PostTask(Thread_A, ContinueAsyncProcessDump(MDP_3))
PostTask(Thread_B, ContinueAsyncProcessDump(MDP_4))
On each ContinueAsyncProcessDump() in each thread:
AutoLock(lock_)
MDP_X->OnMemoryDump()
if (last_dump)
FinalizeAndAddToTrace()
This strategy has two problems:
1) performance-wise: it is suboptimal, as it performs more thread hops
than necessary (ABAB instead of just AB).
2) It is deadlock prone: essentially this spawns N tasks on various
threads and then linearizes them on the |lock_|. This can cause
deadlocks if other tasks on the message loops have dependencies.
This is the case of crbug.com/505725, which is fixed by this CL.
The new strategy is conceptually simpler, smarter and avoids
inter-locking the message loops, as follows:
- The MDPs are kept in order according to their thread affinity.
- When CreateProcessDump() is invoked, only one task (the first in the
set) is posted.
- Each task, which corresponds to an invocation of
ContinueAsyncProcessDump() invokes the dump provider without taking
the lock_. When done posts the next task (or finalizes the dump).
By posting one task at a time we still guarantee that the OnMemoryDump
calls are linearized (per PMD) even if the lock is not taken.
Furthermore, given the order of the MDP set, the thread hopping is
reduced to the minimum.
The only tricky part of this CL is dealing with changes of the dump
providers (i.e. calls to (Un)RegisterDumpProvider) while an
asynchronous process dump is in progress. In this (very unlikely)
case the choice is to abort the current dump.
BUG=497144, 505725
Committed: https://crrev.com/ca7a49016df9b30f326811246d70f7472dea4d66
Cr-Commit-Position: refs/heads/master@{#337580}
Patch Set 1 #Patch Set 2 : Add test #Patch Set 3 : Fix win #
Total comments: 51
Patch Set 4 : petrcermak's review #
Total comments: 1
Patch Set 5 : Re dsinclair #7 #
Messages
Total messages: 12 (4 generated)
|